Data Access Object (DAO). Class level
When designing an information system, some layers are identified that are responsible for the interaction of various modules of the system. A database connection is one of the most important components of an application. Part of the code is always highlighted, the module responsible for sending requests to the database and processing the responses received from it. In general, the definition of a Data Access Object describes it as a layer between the database and the system. DAO abstracts the system entities and makes them displayed on the database, defines the general methods of using the connection, its receipt, closing and (or) return to the Connection Pool .
The pinnacle of the hierarchy of DAOis an abstract class or interface with a description of common methods that will be used when interacting with the database. Typically, these are search methods, key removal, updating, etc.
The set of methods is not complete, it depends on the specific system. The dummy type K is the entity key; the rare table describing the entity does not have a primary key. Also, in this class it would be logical to place the method of closing the PrepareStatement instance .
Implementing a DAO at the class level involves using a single connection to invoke more than one method of an inherited DAO class. In this case, at the top of the DAO AbstractController hierarchy , connection is declared as a field . An abstract class will look like this.
It is worth noting that in this example we get an instance of Connection from the connection pool, which, accordingly, is worth implementing or using ready-made solutions. We create methods to get getPrepareStatement ( String sql ) and close it closePrepareStatement ( PreparedStatement ps ) . The implementation of a specific DAO class, with this logic, should never close the database connection in its methods. The connection is closed in that part of the business logic from where the method was called. An example of a specific DAO class will look as follows.
An example of an entity class.
The Connection instance is available to the getPrepareStatement (String sql) method , which in turn is available to any method of a specific DAO class. It should be remembered that the copy should be closed PrepareStatement when it finally working out in blocks, and return to the pool compound returnConnectionInPool () in terms of the logic of the system where the method was called.
The pinnacle of the hierarchy of DAOis an abstract class or interface with a description of common methods that will be used when interacting with the database. Typically, these are search methods, key removal, updating, etc.
public abstract class AbstractController {
public abstract List getAll();
public abstract E getEntityById(K id);
public abstract E update(E entity);
public abstract boolean delete(K id);
public abstract boolean create(E entity);
}
The set of methods is not complete, it depends on the specific system. The dummy type K is the entity key; the rare table describing the entity does not have a primary key. Also, in this class it would be logical to place the method of closing the PrepareStatement instance .
public void closePrepareStatement(PreparedStatement ps) {
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Class level
Implementing a DAO at the class level involves using a single connection to invoke more than one method of an inherited DAO class. In this case, at the top of the DAO AbstractController hierarchy , connection is declared as a field . An abstract class will look like this.
public abstract class AbstractController {
private Connection connection;
private ConnectionPool connectionPool;
public AbstractController() {
connectionPool = ConnectionPool.getConnectionPool();
connection = connectionPool.getConnection();
}
public abstract List getAll();
public abstract E update(E entity);
public abstract E getEntityById(K id);
public abstract boolean delete(K id);
public abstract boolean create(E entity);
// Возвращения экземпляра Connection в пул соединений
public void returnConnectionInPool() {
connectionPool.returnConnection(connection);
}
// Получение экземпляра PrepareStatement
public PreparedStatement getPrepareStatement(String sql) {
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return ps;
}
// Закрытие PrepareStatement
public void closePrepareStatement(PreparedStatement ps) {
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
It is worth noting that in this example we get an instance of Connection from the connection pool, which, accordingly, is worth implementing or using ready-made solutions. We create methods to get getPrepareStatement ( String sql ) and close it closePrepareStatement ( PreparedStatement ps ) . The implementation of a specific DAO class, with this logic, should never close the database connection in its methods. The connection is closed in that part of the business logic from where the method was called. An example of a specific DAO class will look as follows.
public class UserController extends AbstractController {
public static final String SELECT_ALL_USERS = "SELECT * FROM SHEMA.USER";
@Override
public List getAll() {
List lst = new LinkedList<>();
PreparedStatement ps = getPrepareStatement(SELECT_ALL_PLANET);
try {
ResultSet rs = ps.executeQuery();
while (rs.next()) {
User user = new User();
planet.setId(rs.getInt(1));
planet.setName(rs.getString(2));
lst.add(user);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
closePrepareStatement(ps);
}
return lst;
}
@Override
public Planet getEntityById(Integer id) {
return null;
}
@Override
public boolean delete(Integer id) {
return false;
}
@Override
public boolean create(Planet entity) {
return false;
}
}
An example of an entity class.
public class User implements Serializable {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
The Connection instance is available to the getPrepareStatement (String sql) method , which in turn is available to any method of a specific DAO class. It should be remembered that the copy should be closed PrepareStatement when it finally working out in blocks, and return to the pool compound returnConnectionInPool () in terms of the logic of the system where the method was called.