我现在正在使用JDBC,并且想为数据访问和业务逻辑创建单独的层。我为每个实体创建了多个DAO,并为我的业务逻辑创建了多个服务。但是我在交易方面遇到了问题。在每个DAO中,我都有CRUD,可以在每个操作中打开连接,然后将其关闭。但是,如果我需要在交易中使用多种操作,它将无法正常工作。
所以我为整个DAO创建一个连接,但是我需要为DAO之外的每个操作打开和关闭连接。
我的DAO示例
public class UserDAOImpl implements UserDAO {
private Connection connection;
public UserDAO(Connection connection) {
this.connection = connection;
}
// CRUD operations
}
抽象DAO工厂
public abstract class DAOFactory {
public abstract UserDAO getUserDAO();
public abstract ItemDAO getItemDAO();
public abstract OrderDAO getOrderDAO();
public abstract RoleDAO getRoleDAO();
public static DAOFactory getDAOFactory(Class<? extends DAOFactory> factoryClass) throws IllegalAccessException, InstantiationException {
return factoryClass.newInstance();
}
}
MySQL DAO工厂的实现示例
public class MySqlDAOFactory extends DAOFactory {
private UserDAO userDAO;
private ItemDAO itemDAO;
private OrderDAO orderDAO;
private RoleDAO roleDAO;
@Override
public UserDAO getUserDAO() {
if (userDAO == null) {
userDAO = new UserDAOImpl(getConnection());
}
return userDAO;
}
@Override
public ItemDAO getItemDAO() {
if (itemDAO == null) {
itemDAO = new ItemDAOImpl(getConnection());
}
return itemDAO;
}
@Override
public OrderDAO getOrderDAO() {
if (orderDAO == null) {
orderDAO = new OrderDAOImpl(getConnection());
}
return orderDAO;
}
@Override
public RoleDAO getRoleDAO() {
if (roleDAO == null) {
roleDAO = new RoleDAOImpl(getConnection());
}
return roleDAO;
}
static {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection connection = null;
Context initCtx = null;
try {
initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource) envCtx.lookup("jdbc/mysql");
connection = ds.getConnection();
} catch (NamingException | SQLException e) {
e.printStackTrace();
}
return connection;
}
}
DAO方法示例
public Optional<User> findById(Long id) {
User user = null;
try (PreparedStatement statement = connection.prepareStatement("SELECT * FROM shop.user WHERE id = ?", Statement.RETURN_GENERATED_KEYS)) {
statement.setLong(1, id);
ResultSet resultSet = statement.executeQuery();
resultSet.next();
user = userMapper.map(resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
return Optional.ofNullable(user);
}
答案 0 :(得分:1)
通常,您不必处理DAO级别的事务。最好在服务层应用事务管理,因为这样可以控制何时需要事务或不需要事务时的逻辑,还可以控制回滚策略等其他方面。
根据您的情况,您可以查看JTA文档。该API提供了批注和其他工具,可轻松管理您的交易:)
答案 1 :(得分:0)
现在,我已经创建了用于管理所有DAO之间的连接的类。我已经将抽象类DAOFactory
更改为接口并创建抽象类JdbcDaoFactory
并扩展了我的DaoManager
类。
DAOFactory
public interface DAOFactory {
UserDAO getUserDAO();
ItemDAO getItemDAO();
OrderDAO getOrderDAO();
RoleDAO getRoleDAO();
}
public abstract class JdbcDaoFactory implements DAOFactory {
protected Connection connection;
private UserDAO userDAO;
private ItemDAO itemDAO;
private OrderDAO orderDAO;
private RoleDAO roleDAO;
protected JdbcDaoFactory(Connection connection) {
this.connection = connection;
}
@Override
public UserDAO getUserDAO() {
if (userDAO == null) {
userDAO = new UserDAOImpl(connection);
}
return userDAO;
}
@Override
public ItemDAO getItemDAO() {
if (itemDAO == null) {
itemDAO = new ItemDAOImpl(connection);
}
return itemDAO;
}
@Override
public OrderDAO getOrderDAO() {
if (orderDAO == null) {
orderDAO = new OrderDAOImpl(connection);
}
return orderDAO;
}
@Override
public RoleDAO getRoleDAO() {
if (roleDAO == null) {
roleDAO = new RoleDAOImpl(connection);
}
return roleDAO;
}
}
public class JdbcDaoManager extends JdbcDaoFactory implements AutoCloseable {
public JdbcDaoManager() {
super(DbHelper.getConnection());
}
public void beginTransaction() throws SQLException {
connection.setAutoCommit(false);
}
public void commitTransaction() throws SQLException {
connection.commit();
connection.setAutoCommit(true);
}
public void rollbackTransaction() throws SQLException {
connection.rollback();
connection.setAutoCommit(true);
}
@Override
public void close() throws SQLException {
connection.close();
}
}
但是我仍然不确定该解决方案的正确性... 这是用法的示例。
有交易
try (JdbcDaoManager daoManager = new JdbcDaoManager()) {
try {
daoManager.beginTransaction();
daoManager.getUserDAO().insert(new User("user1", "12345"));
daoManager.getUserDAO().insert(new User("user2", "12345"));
daoManager.getUserDAO().insert(new User("user3", "12345"));
daoManager.commitTransaction();
} catch (SQLException e) {
daoManager.rollbackTransaction();
}
} catch (SQLException e) {
e.printStackTrace();
}
无交易
try (JdbcDaoManager daoManager = new JdbcDaoManager()) {
daoManager.getUserDAO().insert(new User("user1", "12345"));
} catch (SQLException e) {
e.printStackTrace();
}