您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

JDBC连接数据库实例讲解

2024/7/18 2:57:04发布29次查看
1 使用statement执行含有动态信息的sql语句时有几个不足:
1.1 由于需要将动态数据拼接到sql语句中,这导致程序复杂度高,容易出错
1.2 拼接的数据若含有sql语法内容就会导致拼接后的sql语法含义改变而出现sql注入攻击
1.3 当大批量执行语义相同,但是含有动态数据的sql时效率很差2 使用statement执行sql语句不好的原因2.1 当执行一条sql语句发送到数据库时,数据库先将该sql解析并生成一个执行计划(这个过程会消耗资源和性能),如果多次执行一样的sql语句,数据库会重用执行计划,但是若多次执行语义相同但是含有动态数据的sql时,数据库会生成不同的执行计划,严重影响数据库的开销
2.2 例如执行 select * from userifo_fury 生成一个执行计划再次执行select * from userifo_fury 就会重用上面的执行计划(因为这是静态的sql语句 
但是,执行insert into userifo values(1, 'jack','122314','141234@qq.com','fury',15600) ) 生成一个执行计划,再执行执行insert into userifo values(2, 'rose','122314','141234@qq.com','fury',15600)由于内容不同,会再次生成另外一个执行计划,若执行1000次上述情况的insert,数据库会产生1000个执行计划,这样就严重影响了数据库的效率
因此,statement只适合执行静态的sql语句,不适合执行动态的sql语句
3 利用preparedstatement代替statement编写简单没有sql注入问题批量执行语义相同的sql语句会重用执行计划 1 package cn.xiangxu.entity; 2  3 import java.io.serializable; 4  5 public class user implements serializable { 6  7     private static final long serialversionuid = -5109978284633713580l; 8      9     private integer id;10     private string name;11     private string pwd;12     public user() {13         super();14         // todo auto-generated constructor stub15     }16     public user(integer id, string name, string pwd) {17         super();18         this.id = id;19         this.name = name;20         this.pwd = pwd;21     }22     @override23     public int hashcode() {24         final int prime = 31;25         int result = 1;26         result = prime * result + ((id == null) ? 0 : id.hashcode());27         return result;28     }29     @override30     public boolean equals(object obj) {31         if (this == obj)32             return true;33         if (obj == null)34             return false;35         if (getclass() != obj.getclass())36             return false;37         user other = (user) obj;38         if (id == null) {39             if (other.id != null)40                 return false;41         } else if (!id.equals(other.id))42             return false;43         return true;44     }45     public integer getid() {46         return id;47     }48     public void setid(integer id) {49         this.id = id;50     }51     public string getname() {52         return name;53     }54     public void setname(string name) {55         this.name = name;56     }57     public string getpwd() {58         return pwd;59     }60     public void setpwd(string pwd) {61         this.pwd = pwd;62     }63     @override64     public string tostring() {65         return user [id= + id + , name= + name + , pwd= + pwd + ];66     }67     68     69 70 }
user表对应的实体类
 1 package testjdbc; 2  3 import java.sql.connection; 4 import java.sql.drivermanager; 5 import java.sql.preparedstatement; 6 import java.sql.resultset; 7 import java.sql.sqlexception; 8 import java.util.arraylist; 9 import java.util.list;10 11 import org.junit.test;12 13 import cn.xiangxu.entity.user;14 15 public class testcase {16     @test17     public void test01() {18         connection conn = null;19         preparedstatement ps = null;20         resultset rs = null;21         try {22             class.forname(com.mysql.jdbc.driver); // 加载数据库驱动23             24             conn = drivermanager.getconnection( // 初始化连接对象25                     jdbc:mysql://localhost:3306/test, root, 182838);26             27             28             string sql = select * from user where pwd = ? ; // 拼接sql语句,位置参数用?代替29             30             ps = conn.preparestatement(sql); // 初始化预编译执行对象31             32             ps.setstring(1, 182838); // 设置sql语句中的位置位置参数(注意:是从1开始数不是从0开始数)33             34             rs = ps.executequery(); // 执行sql语句35             36             list<user> users = new arraylist<user>(); // 创建一个集合来存放记录对象37             while(rs.next()) { // 遍历结果集38 //                system.out.println(====================);39 //                system.out.println(rs.getint(id));40 //                system.out.println(rs.getstring(name));41 //                system.out.println(rs.getstring(pwd));42                 user user = new user();43                 user.setid(rs.getint(id));44                 user.setname(rs.getstring(name));45                 user.setpwd(rs.getstring(pwd));46                 users.add(user); // 向集合中添加元素47             }48             49             system.out.println(users); // 打印输出集合50             for(user user : users) {51                 system.out.println(user);52             }53             54             // 释放资源55             rs.close();56             ps.close();  57             conn.close();58             59         } catch (exception e) {60             // todo auto-generated catch block61             e.printstacktrace();62         } finally {63             if(rs != null) {64                 try {65                     rs.close();66                 } catch (sqlexception e) {67                     // todo auto-generated catch block68                     e.printstacktrace();69                 }70             }71             if(ps != null) {72                 try {73                     ps.close();74                 } catch (sqlexception e) {75                     // todo auto-generated catch block76                     e.printstacktrace();77                 }78             }79             if(conn != null) {80                 try {81                     conn.close();82                 } catch (sqlexception e) {83                     // todo auto-generated catch block84                     e.printstacktrace();85                 }86             }87         }88         89     }90     91 }
使用预编译statement的实例
4 利用properties对象读取properties配置文件中的信息4.1 properties继承了hashtable类,properties对象也是使用键值对的方式来保存数据,但是properties对象的键和值都是字符串类型class properties extends hashtable<object,object>
4.2 properties 类中的主要方法4.2.1 public synchronized void load(inputstream instream) throws ioexception将properties属性文件的文件输入流加载到properties对象
4.2.2 public void store(outputstream out, string comments) throws ioexception 将properties对象中的属性列表保存到输出流文件中
注意:第二个参数表示注释信息(注意:properties文件中不能用中文),在注释信息后面会自动添加一个时间信息
注意:新创建的文件在项目的根目录下面(问题:为什么在eclipse中没有,但是到文件夹中却能找到???)
4.2.3 public string getproperty(string key)获取属性值,参数是属性的键
 4.2.4 public synchronized object setproperty(string key, string value)修改属性值,参数1是属性的键,参数2是属性的新值
4.3 案例要求:读取properties配置文件总的属性值,将读取到的属性值进行修改后保存到另外一个properties配置文件中
 1 package cn.xiangxu.entity; 2  3 import java.io.fileinputstream; 4 import java.io.fileoutputstream; 5 import java.io.inputstream; 6 import java.util.iterator; 7 import java.util.properties; 8  9 public class test {10     public static void main(string[] args) {11         try {12             properties prop = new properties(); // 创建properties对象13             14 //            prop.load(new fileinputstream(config.properties)); // 使用这种方式时,配置文件必须放在项目的根目录下15             inputstream  is = test.class.getclassloader().getresourceasstream(config/config.properties); // 读取属性文件16             17             prop.load(is); // 加载属性列表18             19             iterator<string> it=prop.stringpropertynames().iterator(); // 将配置文件中的所有key放到一个可迭代对象中20             while(it.hasnext()){ // 利用迭代器模式进行迭代21                 string key=it.next(); // 读取下一个迭代对象的下一个元素22                 system.out.println(key+:+prop.getproperty(key)); // 根据key值获取value值(获取属性信息)23             }24             25             is.close(); // 关闭输入流,释放资源26             27             fileoutputstream ofile = new fileoutputstream(b.properties, true);//创建一个输出流文件,true表示追加打开28             prop.setproperty(maxactive, 33); // 修改属性信息29             prop.store(ofile, zhe shi yi ge xin de shu xing pei zhi wen jian.); // 将properties对象中的内容放到刚刚创建的文件中去30             ofile.close(); // 关闭输出流,释放资源31             32         } catch (exception e) {33             // todo auto-generated catch block34             e.printstacktrace();35         }  36     }37 }
读取属性配置文件信息
等待读取的properties配置文件的位置如下图所示
5 数据库连接池5.1 什么是数据库连接池程序启动时就创建足够多的数据库连接,并将这些连接组成一个连接池,由程序自动地对池中的连接进行申请、使用、释放
5.2 数据库连接池的运行机制》程序初始化时创建连接池
》需要操作数据库时向数据库连接池申请一个可用的数据库连接
》使用完毕后就将数据库连接还给数据库连接池(注意:不是关闭连接,而是交给连接池)
》整个程序退出时,断开所有连接,释放资源(即:管理数据库连接池的那个线程被杀死后才关闭所有的连接)
5.3 数据库连接池的编程步骤5.3.1 导包
5.3.2 声明threadlocal、basicdatasource成员变量(注意:这两个成员变量是静态的)
5.3.3 在静态代码块中实例化那两个成员变量,并通过properties对象读取配置文件信息,利用这些配置文件信息给basicdatasource对象进行初始化处理
5.3.4 编写创建连接静态方法利用basicdatasource对象实例化一个连接对象
将这个连接对象放到threadlocal对象中
5.3.5 编写释放连接静态方法从threadlocal对象中获取连接对象
清空threadlocal对象
判断连接对象是否释放
6 利用数据库连接池操作数据库项目结构图
1 # zhe shi zhu shi , yi ban bu yong zhong wen 2 # deng hao liang bian mei you kong ge, mo wei mei you fen hao3 # hou mian bu neng you kong ge4 driverclassname=com.mysql.jdbc.driver5 url=jdbc:mysql://localhost:3306/test6 username=root7 password=1828388 maxactive=1009 maxwait=3000
properties配置文件
 1 <project xmlns="http://maven.apache.org/pom/4.0.0" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://maven.apache.org/pom/4.0.0 "> 2   <modelversion>4.0.0</modelversion> 3   <groupid>cn.xiangxu</groupid> 4   <artifactid>testjdbc</artifactid> 5   <version>0.0.1-snapshot</version> 6   <dependencies> 7       <dependency> 8           <groupid>mysql</groupid> 9           <artifactid>mysql-connector-java</artifactid>10           <version>5.1.37</version>11       </dependency>12       <dependency>13           <groupid>junit</groupid>14           <artifactid>junit</artifactid>15           <version>4.12</version>16       </dependency>17       <dependency>18           <groupid>commons-dbcp</groupid>19           <artifactid>commons-dbcp</artifactid>20           <version>1.4</version>21       </dependency>22   </dependencies>23 </project>
maven依赖文件
 1 package cn.xiangxu.tools; 2  3   import java.io.ioexception; 4   import java.io.inputstream; 5 import java.sql.connection; 6 import java.sql.sqlexception; 7 import java.util.properties; 8  9 import org.apache.commons.dbcp.basicdatasource;10 11 public class dbutil {12     /*13      * threadlocal用于线程跨方法共享数据使用14      * threadlocal内部有一个map,  key为需要共享数据的线程本身,value就是其需要共享的数据15      */16     private static threadlocal<connection> tl; // 声明一个类似于仓库的东西17     private static basicdatasource datasource; // 声明一个数据库连接池对象18     19     // 静态代码块,在类加载的时候执行,而且只执行一次20     static {21         tl = new threadlocal<connection>(); // 实例化仓库对象22         datasource = new basicdatasource(); // 实例数据库连接池对象23 24         properties prop = new properties(); // 创建一个properties对象用(该对象可以用来加载配置文件中的属性列表)25         inputstream is = dbutil.class.getclassloader().getresourceasstream(config/mysql.properties); // 读取配置文件信息26         try {27             prop.load(is); // 加载配置文件中的属性列表28             29             string driverclassname = prop.getproperty(driverclassname); // 获取属性信息30             string url = prop.getproperty(url);31             string username = prop.getproperty(username);32             string password = prop.getproperty(password);33             integer maxactive = integer.parseint(prop.getproperty(maxactive));34             integer maxwait = integer.parseint(prop.getproperty(maxwait));35             36             datasource.setdriverclassname(driverclassname); // 初始化数据库连接池(即:配置数据库连接池的先关参数)37             datasource.seturl(url);38             datasource.setusername(username);39             datasource.setpassword(password);40             datasource.setmaxactive(maxactive);41             datasource.setmaxwait(maxwait);42             43             is.close(); // 关闭输入流,释放资源44         } catch (ioexception e) {45             // todo auto-generated catch block46             e.printstacktrace();47         }  48         49     }50     51      /**52       * 创建连接对象(注意:静态方法可以直接通过类名来调用)53      * @return 连接对象54      * @throws exception55      */56     public static connection getconnection() throws exception {  57         try {58              connection conn = datasource.getconnection();  // 创建连接对象(利用数据库连接池进行创建)59             tl.set(conn);  // 将连接对象放到仓库中60             return conn;  61         } catch (exception e) {62              // todo auto-generated catch block63              e.printstacktrace();64             throw e;65         }66     }67     68     /**69      * 关闭连接对象(注意:静态方法可以通过类名直接调用)70      * @throws exception71      */72     public static void closeconnection() throws exception {73         connection conn = tl.get(); // 从仓库中取出连接对象74         tl.remove(); // 清空仓库75         if(conn != null) { // 判断连接对象是否释放资源76             try {77                 conn.close();78             } catch (exception e) {79                 // todo auto-generated catch block80                 e.printstacktrace();81                 throw e;82             }83         }84     }85 86 }
数据库连接池类
 1 package testjdbc; 2  3   import java.sql.connection; 4   import java.sql.preparedstatement; 5   import java.sql.resultset; 6  7   import org.junit.test; 8  9 import cn.xiangxu.tools.dbutil;10 11 public class testdbutil {12       @test13     public void test01() {14         try {15               connection conn = dbutil.getconnection(); // 创建连接对象16               string sql = select * from user ; // 拼接sql语句17               preparedstatement ps = conn.preparestatement(sql); // 创建执行对象18               resultset rs = ps.executequery(sql); // 执行sql语句19             while(rs.next()) { // 遍历结果集20                 system.out.println(rs.getstring(name));21             }22         } catch (exception e) {23             e.printstacktrace();24         } finally {  // 关闭连接,释放资源25             try {26                 dbutil.closeconnection();27             } catch (exception e) {28                 e.printstacktrace();29             }30         }31     }32 }
数据库连接池的应用
以上就是jdbc连接数据库实例讲解的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product