So I have the first steps of a webapp, have class Doctor and I want to perform some operations like view all, insert, delete, etc. :
public class Doctor {
public String firstName;
public String lastName;
public int id;
public Doctor(){
}
public Doctor(int id, String first, String last){
setId(id);
setFirstName(first);
setLastName(last);
}
// getters and setters
Here is an implementation of one method from my interface Service. They are all pretty much the same with the appropriate sql queries. I tried following several different tutorials.
public class DAOImpl implements DAO{
public void insertUpdateDoctor(Doctor doctor){
String sql = "INSERT INTO doc_flight.docflight_doctors(id, first_name,last_name)" + "Values(?,?,?)";
jdbcTemplateObject.update(sql,new Object[]{doctor.getId(),doctor.getFirstName(),doctor.getLastName()});
Heres the part in main where I try to call it. The program doesn't even try to enter the method, it doesn't come up in debug and moves to the next method I try in main, view all, which works. Presumably, I'm not calling the method correctly and tried rewriting all parts several times. Help?!
Doctor test = new Doctor(17,"jack", "sparrow");
service.insertUpdateDoctor(test);
The issue itself it's not pretty clear for me.
If the problem is that when calling this:
Doctor test = new Doctor(17,"jack", "sparrow");
service.insertUpdateDoctor(test);
The runtime is not getting inside insertUpdateDoctor, just check how you are instantiating the object service
if the problem is that it's not executing correctly the sql statement, try by using a PreparedStatement (it's a good practice) by doing something like:
String connectionStr = StringUtils.format("INSERT INTO %s.docflight_doctors(id, first_name,last_name) Values(?,?,?)", this.databaseName);
try (Connection connection = this.dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(connectionStr)) {
preparedStatement.setInt(1, doctor.getId());
preparedStatement.setString(2, doctor.getFirstName());
preparedStatement.setString(3, doctor.getLastName());
preparedStatement.execute();
connection.commit();
} catch (Exception ex) {
this.logger.error(String.format("Error when inserting: %s", ex.toString()));
}
Hope it may help you.
For me I would not write this class from scratch, I would prefer to generate it in few clicks and save my time using The Cloud Wizard:
Go to https://codegen.cloud-wizard.com
Click on Java
From the technologies section press on Java SE
Select JDBC Class transformer.
In the metadata section enter a name for the JDBC Class e.g. (DoctorDao)
Add some fields e.g. first name and last name
Press on generate code and you will get your class ready and working as expected.
Related
We have many stored procedures and functions that we call on our DB and the setup for each call in our data access layer is really verbose with setting the inputs and registering the output etc... Is there a better solution to maybe generating the CallableStatement dynamically for any stored procedure or function with any types/amounts of parameters and output type?
We have a home brew solution and it is ugly... full of if/else, fors and whiles... very hard to read and maintain. We have also tried to centralize common boilerplate code for like function calls. I.E. All of the ones that take a Long and return a boolean, all use the same centralized method with dynamic Long and stored procedure string.
The code is from memory please don't pay too much attention to syntax, this is a design question more than anything.
//Client usage in Controller class
certAwarded = PackageName.isCertAwardedFor(personIDToCheck);
//In class that mimics the interface of the database packages
//There would be a method per public function
public static boolean isCertAwardedFor(Long personID){
return PackageUtils.isMet(personID, "{? = call PACKAGE.is_met(?)}");
}
//In Package scoped Utility class
//Attempt to centralize all single input param and return of boolean
//type of procedure calls.
static boolean isMet(Long personID, String proc){
boolean met = false;
try(AutoCloseableStatement stmt = new AutoCloseableStatement(proc)){
CallableStatement callableStmt = stmt.createStatement();
callableStmt.registerOutParameter(1, OracleTypes.VARCHAR2);
callableStmt.setLong(2, personID);
callableStmt.execute();
met = convertYNtoBool(callableStmt.getString(1));
}catch(SQLException ex){
Logger.log(ex);
}
return met;
}
///////////////////////////////////OR///////////////////////////////
//Client usage in Controller class
certAwarded = PackageName.isCertAwardedFor(personIDToCheck, CertPackageEnum);
//In class that mimics the interface of the database packages
//There would be a method per public function
public static boolean isCertAwardedFor(Long personID, PackageProc procCall){
return PackageUtils.call(personID, procCall.IS_CERT_AWARDED);
}
//In Package scoped Utility class
//Attempt to centralize all single input param and return of boolean
//type of procedure calls.
static boolean isMet(Long personID, String proc){
try(AutoCloseableStatement stmt = new AutoCloseableStatement(proc)){
CallableStatement callableStmt = stmt.createStatement();
LOTS OF CONDITIONS TO CHECK AND SET ALL POSSIBLE INPUTS AND OUTPUTS
}catch(SQLException ex){
Logger.log(ex);
}
return ?????
}
I'm trying to write a program to manage some clients. Each client has reservations, and each reservation has items.I know that I have one to many relationship, but I cannot figure out how to do that.
I'm not using Spring, only JDBC.
Without a database I did it like that:
public class Client {
private String _fullName;
private String _address;
private String _email;
private String _phoneNumber;
private List<Reservation> _reservations;
}
public class Reservation {
private List<Item> _items;
private int _totalSum;
private boolean _toDeliver;
private String _date;
}
public class Item {
//primary key.
private int _id;
private int _price;
private String _name;
}
Do I have to declare these Lists? Is it possible to do that without Spring, Hibernate and other stuff? I just want to know how design my program.
Yes, you can do everything just with a JDBC database driver.
The first thing you have to do is to design your database, that is your tables and constraints and etc.
Then you go back to Java and query your database using the JDBC.
A common approach to this is creating a DAO class, where you can decouple your database query from your code. It goes something like this:
public String getUserName(String userId) throws SQLException {
String sql = "SELECT name FROM user WHERE user_id = ?";
try (Connection connection = getConnection();
PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setString(1, userId);
try (ResultSet rs = stmt.executeQuery()) {
String name = rs.getString("name");
return name;
}
}
}
This is just a simple example, there's no error handling here, neither dealing with empty query results, there are better examples online to illustrate how to make a DAO and create a connection. Depending on where you are running this code, you would prefer using a Connection Pool for efficiency (another thing to read more about).
In your use case, you would have the DAO get the data to make your Item, create a new Item and return it from the DAO. There are plenty of examples of this online, if you have further questions, don't hesitate to ask.
For university, it is my excercise to develop a multiplayer game with Java. The communication between the clients shall not be handled with sockets or the like, but with the help of a MySQL database where the clients are adding their steps in the game. Because it is a game of dice, not a lot of queries are needed. (approximiately 30 queries per gaming session are needed).
I never used MySQL in connection with Java before, so this maybe is a beginner's fault. But actually, I often get an exception during the execution of my java project.
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: User my_username already has more than 'max_user_connections' active connections
My queries are executed in a DatabaseHelper.java class. The results are returned and evaluated in another class of the project. Since I use an MVC pattern, I evaluate the results in a controller or model class.
This for example is one of my quers in the DatabaseHelper.java class. The other queries are similar:
private static Connection conn;
private Connection getConn() {
return conn;
}
public void db_connect() throws ClassNotFoundException, SQLException{
// JDBC Klassen laden
Class.forName(dbClassName);
// Verbindungsversuch auf 5 Sekunden setzen
DriverManager.setLoginTimeout(5);
this.setConn(DriverManager.getConnection(CONNECTION,p)); // p contains the username and the database
}
public void db_close(){
try {
this.getConn().close();
} catch (SQLException e) {
if(GLOBALVARS.DEBUG)
e.printStackTrace();
}
}
public String[] query_myHighscores(int gameid, PlayerModel p) throws SQLException{
List<String> rowValues = new ArrayList<String>();
PreparedStatement stmnt;
if(gameid == GLOBALVARS.DRAGRACE)
stmnt = this.getConn().prepareStatement("SELECT score FROM highscore WHERE gid = ? and pname = ? ORDER BY score ASC LIMIT 0,3");
else
stmnt = this.getConn().prepareStatement("SELECT score FROM highscore WHERE gid = ? and pname = ? ORDER BY score DESC LIMIT 0,3");
stmnt.setInt(1, gameid);
stmnt.setString(2, p.getUname());
ResultSet rs = stmnt.executeQuery();
rs.beforeFirst();
while(rs.next()){
rowValues.add(rs.getString(1));
}
stmnt.close();
rs.close();
return (String[])rowValues.toArray(new String[rowValues.size()]);
}
The CONNECTION string is a string which looks like jdbc:mysql://my_server/my_database
In the HighscoreGUI.java class, I request the data like this:
private void actualizeHighscores(){
DatabaseHelper db = new DatabaseHelper();
try{
db.db_connect();
String[] myScoreDragrace = db.query_myHighscores(GLOBALVARS.GAME1); // id of the game as parameter
// using the string
} finally {
db.db_close();
}
So I tried:
Closing the statement and the ResultSet after each query
Used db_close() to close the connection to the dabase in the finally-block
Never returning a ResultSet (found out this may become a performance leak)
The stacktrace leads in the DatabaseHelper.java class to the line
this.setConn(DriverManager.getConnection(CONNECTION,p));
But I cannot find my mistake why I still get this exception.
I cannot change every settings for the database since this is a shared host. So I'd prefer a solution on Java side.
The problem is that you exceed your allowed set of connections to that database. Most likely this limit is exactly or very close to "1". So as soon as you request your second connection your program crashes.
You can solve this by using a connection pooling system like commons-dbcp.
That is the recommended way of doing it and the other solution below is only if you may not use external resources.
If you are prohibited in the external code that you might use with your solution you can do this:
Create a "Database" class. This class and only this class ever connects to the DB and it does so only once per program run. You set it up, it connects to the database and then all the queries are created and run through this class, in Java we call this construct a "singleton". It usually has a private constructor and a public static method that returns the one and only instance of itself. You keep this connection up through the entire livetime of your program and only reactivate it if it gets stall. Basically you implement a "Connection Pool" for the specific case of the pool size "1".
public class Database {
private static final Database INSTANCE = new Database();
private Database() {}
public static Database getInstance() {
return INSTANCE;
}
// add your methods here.
}
When the program terminates, close the Connection (using a shutdown hook).
1) In my application we have a table which stores some settings detail which are used heavily for every functionality.Basically some conditions are set up in this table which are checked.
Now currently what we are doing is making DB call every now and then to fetch the details and check the condition.This has resulted in lot of DB calls and repetitive calls for the same condition.There are quite a lot of condition records in this table.We need to change this to make it perform better.
2) In my previous project also i had same requirement where we have a configuration table where such settings are configured,there we implemented it like load the configuration from table at start up of application and store them in System.setProperty(name,value)..and later use System.getProperty(name) to retrieve it.In case any settings is changed we update this in its System property.This worked like a charm.
However,in my current case(point 1 above) I don't think my prev way is best way to do it because lot of records present in the table having lot of columns.
Can anyone suggest a way how to achieve such kind of behavior in Java? Some of them I can think of is
1) Using System.setProperty like I explained.
2) Using caching like EHCache - standalone or with hibernate(as we are using hibernate).
Any better way to store such global settings of application so as to avoid DB calls?
Best way to do it using Ehcache(but I have never implemented it). And you should not play with System property it may cause conflict with other system properties.
How I did it in my case I have created a bean class which is having properties as yor table column like autoid, name, address, mobile.
public Map<Integer, PersonBean> getTag()
{
Map<Integer, PersonBean> map= new HashMap<Integer, PersonBean>();
Connection conn =getConnection();
Statement st=null;
ResultSet rs=null;
try
{
String sql = "select autoid,name, address, mobile from person";//person table
st = conn.createStatement();
rs = st.executeQuery(sql);
while(rs.next()){
int tagid=rs.getInt("autoid");
String name=rs.getString("name");
String address=rs.getString("address");
String mobile=rs.getString("mobile");
PersonBean tagdeatilbean= new PersonBean(auotoid,name, address, mobile);
map.put(rs.getInt("autoid"), tagdeatilbean);
}
return map;
}
catch (SQLException e) {
}
finally
{
}
}
and bean class
public class PersonBean
{
private int autoid;
private String name;
private String address;
private String mobile;
public PersonBean(int autoid, String name, String address, String mobile)
{
this.autoid=autoid;
.....
....
}
//setter
//getter
}
If this is web application then you can load this cache map in init method and call the value according to autuid of row from map.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 12 years ago.
Before i go any further it would be nice to know if there is any major design flaws in my program so far. Is there anything worth changing before i continue?
Model
package model;
import java.sql.*;
import java.util.*;
public class MovieDatabase {
#SuppressWarnings({ "rawtypes", "unchecked" })
public List queryMovies() throws SQLException {
Connection connection = null;
java.sql.Statement statement = null;
ResultSet rs = null;
List results = new ArrayList();
try {
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "password");
statement = connection.createStatement();
String query = "SELECT * FROM movie";
rs = statement.executeQuery(query);
while(rs.next()) {
MovieBean bean = new MovieBean();
bean.setMovieId(rs.getInt(1));
bean.setTitle(rs.getString(2));
bean.setYear(rs.getInt(3));
bean.setRating(rs.getInt(4));
results.add(bean);
}
} catch(SQLException e) {
}
return results;
}
}
Servlet
public class Service extends HttpServlet {
#SuppressWarnings("rawtypes")
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("Movies!");
MovieDatabase movies = new MovieDatabase();
try {
List results = movies.queryMovies();
Iterator it = results.iterator();
while(it.hasNext()) {
MovieBean movie = new MovieBean();
movie = (MovieBean)it.next();
out.println(movie.getYear());
}
}
catch(SQLException e) {
}
}
}
Bean
package model;
#SuppressWarnings("serial")
public class MovieBean implements java.io.Serializable {
protected int movieid;
protected int rating;
protected int year;
protected String title;
public MovieBean() {
}
public void setMovieId(int movieidVal) {
movieid = movieidVal;
}
public void setRating(int ratingVal) {
rating = ratingVal;
}
public void setYear(int yearVal) {
year = yearVal;
}
public void setTitle(String titleVal) {
title = titleVal;
}
public int getMovieId() {
return movieid;
}
public int getRating() {
return rating;
}
public int getYear() {
return year;
}
public String getTitle() {
return title;
}
}
Here are a couple of suggestions:
Your MovieDatabase has the Connection creation embedded inside it. You don't use a Connection pool that way.
You embed the connection parameters (e.g., driver class, URL, etc.) inside your code. Best to externalize them.
You don't clean up any JDBC resources. This is guaranteed to bring you grief.
You have empty catch blocks. This is a heinous error. Log the stack trace. You'll have no way of knowing if anything is wrong as coded.
MovieBean? Names matter - make it Movie.
Your default constructor does nothing at all, and it's the only constructor you provide. Your String reference to title will be null. I think you should have one constructor that initializes all the fields properly.
Your Service should not extend Servlet. I think you should have a POJO interface and an implementation that has nothing to do with HTTP. You can't use this service (or test it) without the web.
Another empty catch block - you're asking for trouble. When will you learn to print the stack trace?
I wouldn't have a MovieDatabase; I'd go with a MovieDao interface that had CRUD operations, like this:
package persistence;
public interface MovieDao
{
List<Movie> find();
Movie find(int id);
List<Movie> find(String title);
void save(Movie movie);
void update(Movie movie);
void delete(Movie movie);
}
Much of the following is style, not necessarily the 'right' way, and certainly not the only way.
I'd move the database connection
to a try block in the servlet's #doGet. I'd pass the
connection to
MovieDatabase#queryMovies. The
reason is, what happens if in that same request you need
to do another query using another
class? Your connection is in
MovieDatabase and another class
would have no access to it. If you had a situation where both classes could update the database, you'd be unable to roll back the entire transaction. Not good.
I'd add a commit statement at the end of the 'success' path in #doGet
I'd add after try block containing the database connection an exception block, wherein I'd issue a rollback. So if there's an exception, a rollback would be performed every time.
I'd close the database connection in
#doGet's finally block. This is most important. edit - see the pseudocode below for an example
If you don't move the connection into the servlet, then straight
away you should close that
connection in #queryMovies' finally
clause.
If this were a larger project, I'd use Hibernate and its tools to
generate DAOs and models. Hibernate
would generate for you a class and
method that would return a
collection of MovieBeans to you.
You wouldn't have to do anything but
invoke it. Auto-generated database
access code is good.
I'd add a JSP and put the collection you're building into the request. Then your jsp could iterate over the collection and format it as appropriate. This moves the presentation of the information out of the servlet, which is a coordinator of action, not a formatter of data in the MVC model.
If you implemented the above suggestions, it would probably drop your number of lines of code by 50% or more. Learning Hibernate can be a headache, so it wouldn't necessarily be easier or faster the first time. The reason it reduces the lines of code (while doing pretty much the same work) is that generated code is pretty much right and coders don't have to worry about it.
I use the following pattern in my servlets all the time. This is pseudocode, not real java.
Connection conn = null;
try {
conn.getConnection(...);
// your implementation here
conn.commit();
} catch (Exception e) {
conn.rollback();
} finally {
conn.close();
}
The point is that the database connection can always be passed to workers, work is always committed unless something goes wrong. If something goes wrong, there's guaranteed to be a rollback. In either case, the database connection is closed when its all over.
It's pretty simple and straightforward, no big issues. The only thing I would point out is that you're doing a SELECT * then refer to the result set by column index. This is not a problem at this stage but if your schema changes (say, a field gets added in the middle) then your code will break. I would explicitly select the column names:
SELECT id, title, year, rating FROM movie
There are many things wrong (many have already pointed out most of them). Seems like the code is written in 90's. I strongly suggest you read about layered architecture, separation of concerns, MVC, DAO pattern. Then you will answer the question yourself and I will up vote your answer ;-).