多个线程(客队端)共享一个connection的问题. 如果其中一个事务执行了commit语句,其它事务修改的数据会不会也同时被commit?
如果会,请问有没有方法可以让每个线程的事务独立,相互commit但不影响? 我知道不同的数据库处理可能不同,大家可以分别讨论不同数据库.这里只讨论多线程共享一个connection的问题。 如果为每次个线程(客队端)new 一个connection这个方法我知道,我只想讨论共享一个connection的可行性. 因为共享一个connection性能会更高.
如果会,请问有没有方法可以让每个线程的事务独立,相互commit但不影响? 我知道不同的数据库处理可能不同,大家可以分别讨论不同数据库.这里只讨论多线程共享一个connection的问题。 如果为每次个线程(客队端)new 一个connection这个方法我知道,我只想讨论共享一个connection的可行性. 因为共享一个connection性能会更高.
解决方案 »
- java数据库驱动加载出问题了!急!
- 紧急求救: 如何实现窗口中的组件大小随其窗口大小的改变而改变?
- 可以在本地机器上调试socket程序吗?(简单聊天工具)
- 怎样socket才能一直占着一个tcp连接
- 北京 急招java开发人员
- 关于java连接数据源的问题
- 在JB7下,用JDBC连接SQLSERVER2K老是出错!各位帮我看看!谢了!
- java 输出字符到系统光标所在位置
- applet是不是不能用Dialog啊???(在线急送分)
- 寻VJ++ 6.0中文正式版下载网址!高分相送!!
- 用JAVA的Swing实现Html中的超链接问题?顺便散分...
- 我的本地硬盘里某个有很多文本文件 我想用java一个个循环读出来 该如何实现
--------------
会如果会,请问有没有方法可以让每个线程的事务独立,相互commit但不影响? 我知道不同的数据库处理可能不同,大家可以分别讨论不同数据库.
--------------
一个客户端一个connection,如果担心connection太多,就用数据库连结池,取不到数据库连结的客户端会等待这里只讨论多线程共享一个connection的问题。 如果为每次个线程(客队端)new 一个connection这个方法我知道,我只想讨论共享一个connection的可行性. 因为共享一个connection性能会更高.
--------------
不可行,每个客户端有相对独立的事务,所以不应该互相干扰
简单介绍连接池机制:
1.项目启动时创建好初始数目的数据库连接,初始为空闲状态!这部分连接将永远不会断开,直到你的应用程序退出运行!
2.当某个类要使用连接时,到连接池中随机找寻一个空闲状态的连接给此类使用,此时修改该连接状态为使用,此状态告诉其他类将不能再使用该连接,直到该连接重新被置成空闲状态!
3.当该类使用完该连接以后调用close方法将该连接归还连接池,将状态修改为空闲状态!此处的close方法并不是真正的关闭连接,而是将连接放回到连接池中.
4.当连接池中所有的连接都被使用,而又有新的使用连接请求时,那么连接池会自动去创建一个新的连接供使用,该新连接使用完后不会被断开,将永久留在连接池中.此时连接池中连接的数目将增加一个.
5.直到连接池中的连接数目达到配置的最大数目,并且所有的连接都在被使用时,再有新的要使用连接的请求才会处于等待状态.但一般情况下该情况几乎不会发生.因为所有的地方同一时刻使用连接的并发几率很小!所以根据自己项目中并发情况来设置连接池中连接的数目.
6.连接池里的连接在使用完后,必须调用相应的close方法将连接归还到连接池当中,这样才能保证连接池正常使用.否则长时间不归还连接会导致连接池无可用连接,从而导致应用无法操作.
to lip009: 连接池是很好的方案,不知道java本身有没有专门处理连接池相关的类? 我用过其它一些开发工具,有专门的连接池(类).
________________________________________有的,DBCP和C3P0都是相当不错的连接池开源框架:
DBCP http://commons.apache.org/dbcp/
C3P0 http://sourceforge.net/projects/c3p0
让应用服务器来管理。像Tomcat的JNDI数据源底层就是使用DBCP来实现的。
比如说:我执行以下代码,实际上是经常tomcat连接池处理,并不是直接连接或断开数据库,对吗? 如果是, 按照4楼所说原理,我执行close()后,只是与tomcat连接池断开联系,实际上并不是与数据库断开连接.
connection = DriverManager.getConnection(dburl, uid, pwd)
connecttion.close()
"实际上是经常tomcat连接池处理" => "实际上是经过tomcat连接池处理"
看到这个问题,我想到一个新的方法,不知道能不能实现:
使用ThreadLocal来实现:
写一个工具类来得到Connection:
public class UtilConnection{
private static ThreadLocal local = new TreadLocal();
static {
try{
class.forName("oracle.jdbc.driver.DriverOracle");
}catch(....){
}
} public static Connection getCurrentConnection(){
Connection con =(Connection) local.get();
if(con == null){
con = DriverManager.getConnection();
local.set(con);
}
return con;
}
public static void closeConnection(){
Connection con = (Connection) local.get();
if(con != null){
con.close();
}
local.set(null);
}
}
在使用时直接用:
Connection con = UtilConnection.getCurrentConnection();
不知道这样好不好,没测试过,高手说下,这样做可以不.
<ResourceParams name="jdbc/DBPool">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>oracle.jdbc.driver.OracleDriver</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:oracle:thin:@10.1.1.101:1521:orcl</value>
</parameter>
<parameter>
<name>username</name>
<value>oracle</value>
</parameter>
<parameter>
<name>password</name>
<value>oracle</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>10</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>10</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>-1</value>
</parameter>
</ResourceParams> </Context>2.在你的web工程里的web.xml配置JNDI
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/DBPool</res-ref-name>注意这里的名字和上边连接池的名字要一致
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
* Author:BluesLee
* CreateDate:2006-06-12 22:51:00
* Modifier:BluesLee
* ModifyDate:2006-06-12 22:51:00
* Version:1.0
* Copyright\u00A92006 xxxx 沪ICP备06××××××号
* All right reserved.
*/
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.CallableStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.apache.log4j.Logger;
import java.sql.DriverManager;
/**
* 本类是数据库连接的管理类,因此在整个系统中没有必要出现多个,一个就够用了
* 因此,决定在此类上使用单态设计模式,只提供本类的一个实例出去。
* 在此我是用单态的饿汉模式进行使用
*/
public class DBConnectionManager {
private static Logger logger=Logger.getLogger(DBConnectionManager.class.getName());
/**
* 本静态变量用来存放本系统启动时由Struts生成的连接池的数据源
*/
private static DataSource datasource;
/**
* 由于本类使用单态设计模式,因此不允许在使用中通过New进行实例化,那么本类就要提供一个
* 此类的实例供外界使用,这就是供外界使用的实例
*/
private static DBConnectionManager dbConManager=new DBConnectionManager();
private DBConnectionManager(){}
/**
* 此静态方法用来向类的静态变量赋值,用来在系统中使用
* @param mydatasource 传入的struts生成的数据源
*/
public static void setDatasource(DataSource mydatasource) {
logger.info("设置数据源");
if(datasource==null){
datasource = mydatasource;
}
}
/**
* 由于本类使用单态模式,不允许其他的类使用New进行创建实例
* 因此在这里提供一个共有的静态方法来向外界提供自己的一个实例。
* @return 返回本类的唯一实例
*/
public static DBConnectionManager getInstance() {
logger.info("获得数据库连接管理类的实例");
return dbConManager;
}
/**
* 此方法提供一个可用的数据库连接,从连接池中取得可用连接
* @return 可用的数据库连接
*/
public Connection getConnection() {
Connection conn = null;
try {
logger.info("从连接池中获得空闲的数据库连接");
logger.info(datasource);
conn = datasource.getConnection();
logger.info("拿到连接---------");
return conn;
}
catch (SQLException ex) {
ex.printStackTrace();
}
return null;
}
/**
* 这是一个用来关闭所有的数据库连接相关的打开对象的方法,这样作的好处是不用在每一次调用了sql之后
* 要写一大串的关闭操作。
* @param conn 将要关闭的数据库连接
* @param st 将要关闭的数据库操作对象
* @param pst 将要关闭的预处理数据库操作对象
* @param cst 将要关闭的数据库存储过程调用对象
* @param rst 将要关闭的数据库记录集对象
* @throws java.lang.Exception 有可能要抛出的异常
*/
public void closeAll(Connection conn,Statement st,PreparedStatement pst,CallableStatement cst,ResultSet rst)
throws Exception{
if(rst!=null){
rst.close();
}
if(st!=null){
st.close();
}
if(pst!=null){
pst.close();
}
if(cst!=null){
cst.close();
}
if(conn!=null){
conn.close();
}
logger.info("==========>关闭连接成功!");
}
}4.在servlet里获取数据源public class MyServlet extends HttpServlet {
public MyServlet() {
super();
} public void init() throws ServletException {
/**得到数据源*/
try {
Context initCtx = new InitialContext();
DataSource datasource = (DataSource) initCtx.lookup(
"java:comp/env/jdbc/MyDBA");
DBConnectionManager.setDatasource(datasource);
logger.info("DataSourcePlugIn已经初始化完成...");
}
catch (NamingException ex) {
ex.printStackTrace();
}
}
public void destroy() {
super.destroy();
} public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}5.在web.xml里配置该servlet在项目启动的时候加载 <servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>MyServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
* 根据用户ID查询用户信息
* @param doi 用户信息对象父接口,包含有用户ID参数
* @return 返回查询结果对象父接口引用
*/
public DataObjectIF findOne(DataObjectIF doi) {
java.sql.Connection conn = null;
java.sql.ResultSet rs = null;
java.sql.PreparedStatement ps = null; UserInfoData uid = (UserInfoData) doi;
UserInfoData result = new UserInfoData();
String sql = "select * from user_info where id=?";
conn = DBConnectionManager.getInstance().getConnection();
try {
ps = conn.prepareStatement(sql);
ps.setLong(1, uid.getId());
rs = ps.executeQuery();
if (rs.next()) {
result.setId(rs.getLong("id"));
result.setUsername(rs.getString("username"));
result.setPassword(rs.getString("password"));
}
}
catch (SQLException ex) {
ex.printStackTrace();
}
finally {
try {
DBConnectionManager.getInstance().closeAll(conn, null, ps, null, rs);
}
catch (Exception ex1) {
ex1.printStackTrace();
}
}
return result;
}
j2ee对于每一个请求创建一个线程为其服务,ThreadLocal就是为每个线程保存资源的工具。
链接con共享肯定是不可能的,那样事务根本没法管理,更别说复杂的事务管理了。
连接池属于链接复用而不是链接共享,con链接在同一时刻是为一个客户服务的直到客户归还了该链接。
BOOL CPatientLogin::OnInitDialog()
{
CDialog::OnInitDialog();
CString ListID; m_fy.AddString("1元");
m_fy.AddString("2元");
m_fy.AddString("3元");
_ConnectionPtr m_pConnection;
_CommandPtr m_pCommand;
_RecordsetPtr m_pRecordset; m_pConnection.CreateInstance(_uuidof(Connection));
m_pRecordset.CreateInstance(_uuidof(Recordset));
m_pCommand.CreateInstance("ADODB.COMMAND");
try{
_bstr_t strConnect = "driver={SQL Server};server=CHINESE-20171AC\\SQLEXPRESS;DATABASE=HISdata;UID=bbs;PWD=bbs111;";
m_pConnection->Open(strConnect,"","",-1);
CString strSQL="select * from Department";
BSTR bstrSQL=strSQL.AllocSysString();
m_pRecordset->Open(bstrSQL,(IDispatch *)m_pConnection,adOpenDynamic,adLockOptimistic,adCmdText);
_variant_t varValue;
varValue = m_pRecordset->Fields->GetItem("DepartmentID")->Value;
if(varValue.vt!=VT_NULL){
while(!m_pRecordset->adoEOF)
{
m_ks.AddString((char *)_bstr_t(varValue = m_pRecordset->Fields->GetItem("DepartmentID")->Value));
m_pRecordset->MoveNext();
}
}
strSQL="select * from PatientLogin";
bstrSQL=strSQL.AllocSysString();
m_pRecordset->Open(bstrSQL,(IDispatch*)m_pConnection,adOpenDynamic,adLockOptimistic,adCmdText); varValue=m_pRecordset->Fields->GetItem("CaseID")->Value;
if(varValue.vt!=VT_NULL){
m_pRecordset->MoveLast();
ListID=(char *)_bstr_t(varValue = m_pRecordset->Fields->GetItem("CaseID")->Value);
int m=atoi(ListID);
m++;
m_mz.SetWindowText(_bstr_t(m));
}
}
catch(_com_error e)
{
AfxMessageBox(e.Description());
}
m_pRecordset->Close();
return TRUE;
}
出错是从颜色标记处开始的