【发布时间】:2019-11-16 11:20:10
【问题描述】:
我现在正在使用 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);
}
【问题讨论】:
-
嗯...我想不出简单的方法,但在我脑海中,您可以使用由 AspectJ 提供支持的拦截器。拦截器将负责管理和提供 DAO 使用的连接实例。
-
@FanaSithole 我不使用 Spring。
-
是的,我知道,AspectJ 不是 Spring,Spring AOP 相当于 AspectJ
-
@FanaSithole 如果我不使用任何框架会更好。
-
如果您不想要框架,我建议您对数据访问层使用代理模式来执行您在 Aspect 中所做的相同操作
标签: java jdbc transactions dao