在三层架构DAL层多次开启和关闭Connection对象好吗?

程序猫的世界 2015-01-04 05:43:47
在DAL层中,每次执行查询以后都会关闭prepareStatement对象和Connection对象,请问这样做合适吗?
我的SQLHelper写成是静态的了,DAL层每个查询都从SQLHelper中获取一个PrepareStatement对象,然后每次执行完对应的查询后都会关闭pstmt对象和connection对象,然而这只是在DAL层,在BLL层中一般会调用1-5个DAL的方法,也就是说,一轮业务逻辑下来,Connection对象会开启和关闭1-5次,这样对性能有影响吗?有没有高手帮我改一下,不胜感激!


主要是性能方面的问题,其他的没什么!!!就怕性能不足!!!但是又不想让BLL层接触数据库的东西,达到分层效果。[color=#FF0000][/color]


下面是我的SQLHelper代码:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 数据库通用逻辑组件
* */

public class SQLHelper {
/** 声明数据库三大连接对象 */
public static Connection conn = null;// 数据库连接对象
public static Statement stmt = null;// 数据库命令执行对象
public static PreparedStatement pStmt = null;//数据库预编译命令执行对象
public static ResultSet rs = null;// 数据库结果集对象


/** 不允许实例化该类 */
private SQLHelper(){}


/** 连接数据库语句 */
//设置数据库连接驱动,默认使用JDBC4进行连接
private static String dbDrive = "com.microsoft.sqlserver.jdbc.SQLServerDriver";

//数据库连接地址以及连接的数据库名
private static String dbLocate = "localhost";
private static String dbName = "sq_a1076";
private static String dbPort = "1433";
private static String dbURL = "jdbc:sqlserver://"+ dbLocate +":"+ dbPort +";DatabaseName="+ dbName +"";

// 数据库帐号和密码
private static String dbUser ="" ;//忽略这个吧,我删掉了
private static String dbPwd = "";



//============================================================
// 获取各种连接对象,用于内部使用
//============================================================
/** 获取Connection连接对象 */
private static Connection getConnection() {
Connection conn = null;
try {
Class.forName(dbDrive);
conn = DriverManager.getConnection(dbURL, dbUser, dbPwd);
}
catch (Exception e) {
e.printStackTrace();
}

//判断是否成功生成conn连接对象
if (conn == null) {
System.err.println("警告:数据库连接失败!");
}
return conn;
}// method


/**
* 获取Statement对象
*
* @return 返回一个指针可滚动、可更新的SQL语句执行对象
*/
public static Statement getStatement(){
conn = getConnection();
if(conn == null){
return null;
}
try{
return conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
}catch(Exception e){
//TO-DO 是否需要关闭Connection?
e.printStackTrace();
return null;
}
}



/**
* 获取PrepareStatement对象
*
* @param sql 特定的带'?'的SQL执行语句
* 示例:String sql = "select * from goods where goodsName=? and goodsType=?";
*
* @return 返回一个预编译指针可滚动、可更新SQL语句执行对象
*/
public static PreparedStatement getPreparedStatement(String sql){
conn = getConnection();

if(conn == null){
return null;
}
try{
return conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);//使用第一个方法
}catch(Exception e){
e.printStackTrace();
return null;
}
}

/** 关闭数据库连接 */
public static void closeConnection() throws Exception{
// 关闭连接对象
try {
if (conn != null) {
conn.close();
}
} catch (Exception e) {
throw e;
}
}// method

}// class



下面是DAL层中其中一个SQL原子执行语句:

public User findUserByUserName(String userName) throws Exception {
User user = null;//一个可以指向用户对象的变量

String sql = "select userName,userTypeId,personId from [User] where userName=?";

pstmt = SQLHelper.getPreparedStatement(sql);
pstmt.setString(1, userName);

ResultSet rs = pstmt.executeQuery();

while(rs.next()){
user = new User();
user.setUserName(rs.getString(1));
user.setUserTypeId(rs.getInt(2));
user.setPersonId(rs.getInt(3));
}

pstmt.close();
SQLHelper.closeConnection();

return user;
}



感激各位大神的帮助
...全文
165 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
程序猫的世界 2015-01-07
  • 打赏
  • 举报
回复
引用 6 楼 etnet 的回复:
你的代码都不是性能问题了,是肯定会出多线程问题。 除非你能保证,同一时间SqlHelper只有一个线程被调用。 A线程调用了getPreparedStatement,B线程也调用了getPreparedStatement。。。这时候A先调用结束然后调用了closeConnection关掉了Connection,那么等B线程调用结束后如何关掉B线程用的Connection? 这个Connection就泄漏了,迟早会达到数据库连接上限。 所以建议是除非你能保证,同一时间只有一个线程调用SqlHelper上的方法,不然别这么做。 你可以使用DataSource数据源,这都说烂的事了。比如C3P0之类的,你只需要问他拿Connection使用完调用close就可以了。 性能由C3P0来保证。当然数据源实现有好多种了。
好,后面我把数据库SQLHelper写成动态的了,不知道这样行不行,我也在多线程环境下调用过,在SQL Manager看连接,在程序结束后就没有连接了,应该是没问题了,以后再用C3P0,谢谢
程序猫的世界 2015-01-07
  • 打赏
  • 举报
回复
引用 5 楼 u010097361 的回复:
[quote=引用 4 楼 u010097361 的回复:] 一个Connection 的开启和关闭一般用于代表一个事务,对于Connection ,设置为一个成员变量的时候,当出现多线程调用这个Connection 成员变量,如果不处理同步问题,则可能你在线程1中调用这个Connection成员变量的时候,发现这个是一个空指针,于是就新建了一个Connection,但是如果同时线程2也在跑,也同时发现这个是一个空指针,同样新建了一个Connection(多线程就是这样的,因为你没有处理异步问题) ,这样你的Connection 关闭就很有问题了,并且可能会很快占用完数据库连接(new 了太多Connection)! 所以最佳的做法就是,每次操作数据库之前都独立获取一个Connection对象,并且操作完之后对其进行关闭!也就很好地保证了事务的一致性以及代码的同步操作。
可以把每次单独获取Connection和prepareStatement的代码写到一起提供复用。 多次开启和关闭独立的Connection是没有问题的,一般都是这么做的,如果想更加优化,一般推荐使用连接池! [/quote] 可以给各小例子吗?谢谢,我不知道怎么复用,是静态还是动态的?!
程序猫的世界 2015-01-05
  • 打赏
  • 举报
回复
引用 2 楼 bao110908 的回复:
不要这么做,我在 CSDN 强调过不下 10 次了,不要把 Connection 等 JDBC 对象弄成静态的,这会产生非常严重的问题。 JDBC connection 讨论 http://bbs.csdn.net/topics/360027520#post-361821072 Connection能设置成静态的吗 http://bbs.csdn.net/topics/350052222#post-351357361
还是不是很懂,连接泄漏这方面的问题,那应该怎么做? 在三层架构里面,我不想DAL和BAL耦合太大,求支招!
etnet 2015-01-05
  • 打赏
  • 举报
回复
你的代码都不是性能问题了,是肯定会出多线程问题。 除非你能保证,同一时间SqlHelper只有一个线程被调用。 A线程调用了getPreparedStatement,B线程也调用了getPreparedStatement。。。这时候A先调用结束然后调用了closeConnection关掉了Connection,那么等B线程调用结束后如何关掉B线程用的Connection? 这个Connection就泄漏了,迟早会达到数据库连接上限。 所以建议是除非你能保证,同一时间只有一个线程调用SqlHelper上的方法,不然别这么做。 你可以使用DataSource数据源,这都说烂的事了。比如C3P0之类的,你只需要问他拿Connection使用完调用close就可以了。 性能由C3P0来保证。当然数据源实现有好多种了。
痴心贼 2015-01-05
  • 打赏
  • 举报
回复
引用 4 楼 u010097361 的回复:
一个Connection 的开启和关闭一般用于代表一个事务,对于Connection ,设置为一个成员变量的时候,当出现多线程调用这个Connection 成员变量,如果不处理同步问题,则可能你在线程1中调用这个Connection成员变量的时候,发现这个是一个空指针,于是就新建了一个Connection,但是如果同时线程2也在跑,也同时发现这个是一个空指针,同样新建了一个Connection(多线程就是这样的,因为你没有处理异步问题) ,这样你的Connection 关闭就很有问题了,并且可能会很快占用完数据库连接(new 了太多Connection)! 所以最佳的做法就是,每次操作数据库之前都独立获取一个Connection对象,并且操作完之后对其进行关闭!也就很好地保证了事务的一致性以及代码的同步操作。
可以把每次单独获取Connection和prepareStatement的代码写到一起提供复用。 多次开启和关闭独立的Connection是没有问题的,一般都是这么做的,如果想更加优化,一般推荐使用连接池!
痴心贼 2015-01-05
  • 打赏
  • 举报
回复
一个Connection 的开启和关闭一般用于代表一个事务,对于Connection ,设置为一个成员变量的时候,当出现多线程调用这个Connection 成员变量,如果不处理同步问题,则可能你在线程1中调用这个Connection成员变量的时候,发现这个是一个空指针,于是就新建了一个Connection,但是如果同时线程2也在跑,也同时发现这个是一个空指针,同样新建了一个Connection(多线程就是这样的,因为你没有处理异步问题) ,这样你的Connection 关闭就很有问题了,并且可能会很快占用完数据库连接(new 了太多Connection)! 所以最佳的做法就是,每次操作数据库之前都独立获取一个Connection对象,并且操作完之后对其进行关闭!也就很好地保证了事务的一致性以及代码的同步操作。
  • 打赏
  • 举报
回复
不要这么做,我在 CSDN 强调过不下 10 次了,不要把 Connection 等 JDBC 对象弄成静态的,这会产生非常严重的问题。 JDBC connection 讨论 http://bbs.csdn.net/topics/360027520#post-361821072 Connection能设置成静态的吗 http://bbs.csdn.net/topics/350052222#post-351357361
程序猫的世界 2015-01-04
  • 打赏
  • 举报
回复
主要是性能方面的问题,其他的没什么!!!就怕性能不足!!!但是又不想让BLL层接触数据库的东西,达到分层效果。

67,516

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧