在 DAO 模式中通过构造函数的连接在任何情况下都是不安全的吗?
Can connection passing through constructor in DAO pattern be unsafe in any case?
我正在使用 DAO 模式。在我的例子中,DAO 不会打开或关闭连接;相反,连接是通过构造函数传递给它的;它使用该连接来执行其工作。通过构造函数传递到 DAO 层的连接在任何情况下都不安全吗?如果是,请告诉我如何。
我是这样使用它的:
这是所有 DAO 实现的父级:
public abstract class SuperDAO {
private Connection connection;
public SuperDAO(Connection connection) { this.connection = connection; }
public Connection getConnection() { return this.connection; }
}
这是用户业务对象:
public class User {
private String userId;
private String password;
public String getUserId() { return this.userId; }
public void setUserId(String userId) { this.userId = userId; }
public String getPassword() { return this.password; }
public void setPassword(String password) { this.password = password; }
}
这是用户业务对象的 DAO:
public interface UserDAO {
User getUser(String userId, String password);
}
这是用户业务对象 DAO 的SQL服务器实现:
public class SQLServerUserDAO extends SuperDAO implements UserDAO {
public SQLServerUserDAO(Connection connection) { super(connection); }
public User getUser(String userId, String password) {
// perform task; use getConnection() for connection; dont close connection
}
}
这是 DAO 工厂:
public abstract class DAOFactory {
public static final int SQL_SERVER = 1;
protected Connection connection;
public static DAOFactory getDAOFactory(int factoryType, Connection connection) {
DAOFactory daoFactory = null;
switch (factoryType) {
case SQL_SERVER:
daoFactory = new SQLServerDAOFactory();
daoFactory.connection = connection;
break;
}
return daoFactory;
}
public abstract UserDAO getUserDAO();
}
这是 DAO 工厂的 SQL 服务器实现:
public class SQLServerDAOFactory extends DAOFactory {
public UserDAO getUserDAO() {
UserDAO userDAO = new SQLServerUserDAO(connection);
return userDAO;
}
}
这就是我的使用方式:
Connection connection = null;
try {
connection = ... // obtain a connection;
DAOFactory daoFactory = DAOFactory.getDAOFactory(DAOFactory.SQL_SERVER, connection);
UserDAO userDAO = daoFactory.getUserDAO();
...
} finally {
connection.close();
}
在什么情况下这段代码会被破解?请指教。
谢谢
Can connection passing through constructor to DAO layer be unsafe in
any case?
不,您的使用方式是安全的。
但是,你 reinventing the wheel. Rather use an existing ORM tool。
In which cases this code will be broken?
如果您使用的是容器管理的事务,并且您在事务上下文之外获取连接,而您的 DAO 代码在事务上下文中执行,那么它将被破坏。
例如,这会很糟糕:
@Stateless
public static class MyBean implements MyBusinessInterface {
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void doSomething(Connection connection) {
new SomeDAO().doSomething(connection);
}
}
换句话说,如果您根本不使用容器管理的事务,或者如果您在与 DAO 相同的事务上下文中从托管连接池获取连接,则您的代码没有问题。
注意:在 finally
块中,您有可能 NullPointerException
试图在空连接变量上调用 close()
。
如果改为这样做,您将始终有一个连接要关闭:
Connection connection = //obtain a connection
try {
DAOFactory daoFactory = DAOFactory.getDAOFactory(DAOFactory.SQL_SERVER, connection);
UserDAO userDAO = daoFactory.getUserDAO();
// etc
} finally {
connection.close();
}
我正在使用 DAO 模式。在我的例子中,DAO 不会打开或关闭连接;相反,连接是通过构造函数传递给它的;它使用该连接来执行其工作。通过构造函数传递到 DAO 层的连接在任何情况下都不安全吗?如果是,请告诉我如何。
我是这样使用它的:
这是所有 DAO 实现的父级:
public abstract class SuperDAO {
private Connection connection;
public SuperDAO(Connection connection) { this.connection = connection; }
public Connection getConnection() { return this.connection; }
}
这是用户业务对象:
public class User {
private String userId;
private String password;
public String getUserId() { return this.userId; }
public void setUserId(String userId) { this.userId = userId; }
public String getPassword() { return this.password; }
public void setPassword(String password) { this.password = password; }
}
这是用户业务对象的 DAO:
public interface UserDAO {
User getUser(String userId, String password);
}
这是用户业务对象 DAO 的SQL服务器实现:
public class SQLServerUserDAO extends SuperDAO implements UserDAO {
public SQLServerUserDAO(Connection connection) { super(connection); }
public User getUser(String userId, String password) {
// perform task; use getConnection() for connection; dont close connection
}
}
这是 DAO 工厂:
public abstract class DAOFactory {
public static final int SQL_SERVER = 1;
protected Connection connection;
public static DAOFactory getDAOFactory(int factoryType, Connection connection) {
DAOFactory daoFactory = null;
switch (factoryType) {
case SQL_SERVER:
daoFactory = new SQLServerDAOFactory();
daoFactory.connection = connection;
break;
}
return daoFactory;
}
public abstract UserDAO getUserDAO();
}
这是 DAO 工厂的 SQL 服务器实现:
public class SQLServerDAOFactory extends DAOFactory {
public UserDAO getUserDAO() {
UserDAO userDAO = new SQLServerUserDAO(connection);
return userDAO;
}
}
这就是我的使用方式:
Connection connection = null;
try {
connection = ... // obtain a connection;
DAOFactory daoFactory = DAOFactory.getDAOFactory(DAOFactory.SQL_SERVER, connection);
UserDAO userDAO = daoFactory.getUserDAO();
...
} finally {
connection.close();
}
在什么情况下这段代码会被破解?请指教。
谢谢
Can connection passing through constructor to DAO layer be unsafe in any case?
不,您的使用方式是安全的。
但是,你 reinventing the wheel. Rather use an existing ORM tool。
In which cases this code will be broken?
如果您使用的是容器管理的事务,并且您在事务上下文之外获取连接,而您的 DAO 代码在事务上下文中执行,那么它将被破坏。
例如,这会很糟糕:
@Stateless
public static class MyBean implements MyBusinessInterface {
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void doSomething(Connection connection) {
new SomeDAO().doSomething(connection);
}
}
换句话说,如果您根本不使用容器管理的事务,或者如果您在与 DAO 相同的事务上下文中从托管连接池获取连接,则您的代码没有问题。
注意:在 finally
块中,您有可能 NullPointerException
试图在空连接变量上调用 close()
。
如果改为这样做,您将始终有一个连接要关闭:
Connection connection = //obtain a connection
try {
DAOFactory daoFactory = DAOFactory.getDAOFactory(DAOFactory.SQL_SERVER, connection);
UserDAO userDAO = daoFactory.getUserDAO();
// etc
} finally {
connection.close();
}