jdbc mysql和sql server 建立连接代码 / tomcat+jdbc会出现的问题No suitable driver found for问题,

一. jdbc select(mysql / sql server)

(1) close( ) 关闭问题:conn / statement / resultSet 这三个对象,无论执行多个sql 语句,都不需要close( ),结果不会掺和导致错。但是良好的习惯是程序结束时去close( ),及时释放防止内存消耗。

(2) Connection 复用问题, 多线程共用一个Connection 对象,没问题, 他们不停地用这个Connection 对象去查询没问题, 猜测是Connection 类内部优化,

将多线程剥离开, 一个线程用Connection 去select 时, 这个任务是原子的, 执行后, 另一个线程用这个Connection 对象去select 的任务才能得以执行.

(3) 下面第一个代码这种串行查询问题,如果第一个sql 执行失败,下面的就无法执行,不科学,应该让多线程去执行。

如果是用多线程,则需要注意线程安全。

jdbc mysql select:

String url="jdbc:mysql://localhost:3306/seandb?useUnicode=true&characterEncoding=UTF-8";
Class.forName("com.mysql.jdbc.Driver");  
Connection conn=DriverManager.getConnection(url);   
Statement stmt = conn.createStatement();  
//第一次查询
ResultSet rs = stmt.executeQuery("select page,articlenum,namelink from scontent");
boolean resultFlag = false; 
while (rs.next()){
	resultFlag=true;
	System.out.println(rs.getString(1) +"  "+ rs.getString(2) +"  "+ rs.getString(3));
}
if(resultFlag==false)  
	logger.info("当前select 没有结果");
resultFlag = false; 
//第二次查询
rs = stmt.executeQuery("select page,articlenum,namelink from scontent"); //这个rs 不是上面的rs 了,是一个新的对象。这句看出stmt 对象可以复用
boolean resultFlag = false; 
while (rs.next()){
	resultFlag=true;
	System.out.println(rs.getString(1) +"  "+ rs.getString(2) +"  "+ rs.getString(3));
}
if(resultFlag==false)  
	logger.info("当前select 没有结果");

jdbc sql server select :

String url="jdbc:sqlserver://Arcrch.db.ua.qa.nt.ctcorp.com:5111;DatabaseName=ArSerchDB";
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection conn=DriverManager.getConnection(url,"username","password"); 
Statement stmt = conn.createStatement();  
ResultSet rs = stmt.executeQuery(SearchSql);

if (rs.next()) {
	do {
		System.out.println(rs.getString(1) +"  "+ rs.getString(2) +"  "+ rs.getString(3));
	} while (rs.next());
} else
	 logger.info("当前select 没有结果");

二. tomcat+jdbc会出现的问题No suitable driver found for问题,

  问题背景:正常启动tomcat,以下代码被执行,不会报错。如果修改了代码,哪怕加一个空格,这里的第二句就会报“ No suitable driver found for ” Exception。

  想解掉这个问题,需要补充几个知识。
  tomcat类加载:一个WEB程序,发布到Tomcat里面运行。首先是执行Tomcat org.apache.catalina.startup.Bootstrap类,这时候的类加载器  是ClassLoader.getSystemClassLoader()。而我们后面的WEB程序,里面的jar、resources都是由Tomcat内部来加载的,所以你在代码中动态
  加载jar、资源文件的时候,首先应该是使用Thread.currentThread().getContextClassLoader()。如果你使用Test.class.getClassLoader(),
  可能会导致和当前线程所运行的类加载器不一致(因为Java天生的多线程)。说明修改代码、tomcat自动热部署之后,是用了不同的类加载器。
  jdbc的DriverManager.getConnection(url)这个函数源码:
  
	private static Connection getConnection(
        String url, java.util.Properties info, Class<?> caller) throws SQLException {
        /*
         * When callerCl is null, we should check the application's
         * (which is invoking this class indirectly)
         * classloader, so that the JDBC driver class outside rt.jar
         * can be loaded from here.
         */
        ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
        synchronized (DriverManager.class) {
            // synchronize loading of the correct classloader.
            if (callerCL == null) {
                callerCL = Thread.currentThread().getContextClassLoader();
            }
        }

        if(url == null) {
            throw new SQLException("The url cannot be null", "08001");
        }

        println("DriverManager.getConnection(\"" + url + "\")");

        // Walk through the loaded registeredDrivers attempting to make a connection.
        // Remember the first exception that gets raised so we can reraise it.
        SQLException reason = null;


        for(DriverInfo aDriver : registeredDrivers) {
            // If the caller does not have permission to load the driver then
            // skip it.
            if(isDriverAllowed(aDriver.driver, callerCL)) {
                try {
                    println("    trying " + aDriver.driver.getClass().getName());
                    Connection con = aDriver.driver.connect(url, info);
                    if (con != null) {
                        // Success!
                        println("getConnection returning " + aDriver.driver.getClass().getName());
                        return (con);
                    }
                } catch (SQLException ex) {
                    if (reason == null) {
                        reason = ex;
                    }
                }


            } else {
                println("    skipping: " + aDriver.getClass().getName());
            }


        }


        // if we got here nobody could connect.
        if (reason != null)    {
            println("getConnection failed: " + reason);
            throw reason;
        }
        println("getConnection: no suitable driver found for "+ url);
        throw new SQLException("No suitable driver found for "+ url, "08001");
    }


	private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {
        boolean result = false;
        if(driver != null) {
            Class<?> aClass = null;
            try {
                aClass =  Class.forName(driver.getClass().getName(), true, classLoader);
            } catch (Exception ex) {
                result = false;
            }


             result = ( aClass == driver.getClass() ) ? true : false;
        }
        return result;
    }

 这里的getConnection函数在运行时,mysql的driver对象已经被注册,这个对象的类加载器是最开始的设为Aclassloader,
 callerCL是当前的类加载器,这两个参数代入isDriverAllowed()函数时,result = ( aClass == driver.getClass() ) ? true : false;
 这句返回false,所以在getConnection()这个函数中抛异常“No suitable driver found”。 可见类加载器变了,导致jdbc判断逻辑出错。
 jdbc的判断逻辑应该是用类加载 器是否相同,作为依据为了防止假驱动代替我们程序中的真驱动,而tomcat在进行热部署的时候,其实已经
 换了类加载器,所以他俩在这里配合会出错。解决问题方法:暂时没想到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值