Remember the DRY and KISS principles of programming.
Here are some other resources with good info on general programming principles.
As a maintainer or reviewer of anyone's code (our own or someone elses), when examining code we look for code smells. These give general indications of programming practices which are less than ideal. When we find code smells, it's a good clue that we need to look more closely and consider why the code smells.
There are a few obvious code smells, mostly pointed out by others already:
- Ambiguous Naming Convention
- Re-purposing Existing Names
- Repetitive Code Patterns
- Improper Use of Exceptions
- Failure to Release Resources
- Lack of Comments
Objects and other Variables are nouns. Methods and other functions are verbs. Name them accordingly. Do not use acronyms or abbreviations, but do not use sentences for your names either. There is no need for joining words such as 'The' or 'With'. Most importantly, one should also always strive to maintain consistent naming convention, whatever style you choose. This is more in reference to @Shree's use of executeWithPreparedStatement.
executePreparedStatement is better. It conforms to the naming convention used for the other methods in the library and avoids the use of an unnecessary preposition that doesn't add any meaning to the identifier.
Same for DBUtil. These abbreviations are common enough that there is little risk of confusion but it should still be avoided. DatabaseUtility is best. We can only assume that DB means Database, we can't be sure until we inspect source code or documentation. Forcing the reader of the code to have to guess, or research should be avoided whenever possible.
Re-using names that you are deriving from is OK when you are recreating a function that does the same thing in a different way. It is not OK when you have extended the functionality of the code you are deriving from. Pick a new name that better describes why your method is different than the original.
Repetitive Code Patterns
Next to KISS, DRY should be the most important principle of programming. DRY is why we do programming. To automate things. Failing the DRY principle means you are doing more work than you need to, introducing more potential for error and making it more difficult to maintain.
When you see repetitive code patterns, such as blanket exception handling or methods that look almost identical, consider why is it repetitive and how can you reduce the duplication of those pieces of code. Often it means reconsidering the method of implementation, not just splitting things up more.
Errors and exceptions should always be handled gracefully.
Never trap exceptions and then not handle them. Printing a stack trace is not handling them. You are merely acknowledging that a problem can happen at that point but you don't care. Why add extra code if you don't care? The only thing accomplished is that the problem is guaranteed to not be fixable from outside of your function, since no caller can know that anything went wrong.
Exceptions that are unhandled should be allowed to flow up the call stack until they are handled, or until the main function is reached and then an unhandled exception error occurs.
You are better off to simply not catch the exceptions at all and just let them get passed on until you get an unhandled exception error.
You can trap them do something with them and then rethrow the exceptions if they are not actually being handled.
Make sure that you are not overriding valid handles when you open new connections.
The connect() method needs to make sure that the connection object is not already valid.
As well, in the disconnect() method you should reassign connection=null after it has been closed so that the invalid handle can't accidentally be used.
Make sure to close all open handles when you are done with them. This includes things like PreparedStatement, Statement and ResultSet objects, not just connections. These objects go into object pools just like the connection pool, which can build up and eat RAM if you forget to close things. (TIP: they all derive from the AutoCloseable/Closeable interface)
Lack of Comments
This seems so trivial but it is not. This is the biggest code smell. While we should always strive to create self-documented code, we still need comments to summarize what it is the code is doing and so that formal documentation can be generated with the least effort, written by the people who actually wrote the code. Comments come first, before code. Always. This is one most programmers most often neglect. Me too.
I should mention that I'm mostly speaking of inline documentation, not trying to teach the reader how every bit of code works.
The converse code smell to a lack of comments is too much comments. If you need comments to describe how your code works and not just what it does, then your code is probably too complex.