- 浏览: 188154 次
- 性别:
- 来自: 上海
文章分类
最新评论
一、基础知识
1. 数据持久化
2. 在java中数据库存储技术分类
3. JDBC概念
4. JDBC常用(重要)类/接口
5. JDBC应用步骤
二、加载与注册驱动
三、建立连接
四、访问数据库
1. 用Statement来执行sql语句
2. 用PreparedStatement来执行sql语句
3. PreparedStatement与Statement比较
4. Statement不安全性
5. 使用Callable Statement
五、处理执行结果
六、释放数据库连接
七、数据库事务
1. 概述
2. 事务的ACID属性
3. JDBC 事务处理
八、批量处理JDBC语句
1. 概述
2. Statement批量处理
3. PreparedStatement批量传参
九、使用 JDBC 处理元数据
1. 概述
2. 获取数据库元数据
3. ResultSetMetaData
十、创建可滚动、更新的记录集
1. Statement
2. PreparedStatement
3. ResultSet滚动的结果集使用
十一、JDBC连接池
1. 为什么要使用JDBC连接池
2. 数据库连接池(connection pool)
3. 数据库连接池工作原理
4. 使用数据库连接池的优点
5. 常用数据库连接池介绍
一、基础知识
1. 数据持久化
持久化(persistence):对象在内存中创建后,不能永久存在。把对象永久的保存起来就是持久化的过程。而持久化的实现过程大多通过各种关系数据库来完成。
持久化的主要应用是将内存中的数据存储在关系型数据库中,当然也可以存储在磁盘文件、XML数据文件中。
2. 在java中数据库存储技术分类
JDBC直接访问数据库。
第三方O/R工具,如Hibernate,mybatis。这些工具都是对JDBC的封装。
3. JDBC概念
JDBC(Java Datebase Connectivity)是一个独立于特定数据库管理系统、通用的sql数据库存取和操作的公共接口。它是JAVA语言访问数据库的一种标准。
4. JDBC常用(重要)类/接口
Java.sql.Driver接口是所有JDBC驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不用的实现。
在程序中不需要直接去访问实现了Driver接口的类,而是由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现。
DriverManager类,用来创建连接,它本身就是一个创建Connection的工厂,设计的时候使用的就是Factory模式,给各数据库厂商提供接口,各数据库厂商需要实现它;
Connection接口,根据提供的不同驱动产生不同的连接;
Statement接口,用来发送SQL语句;
Resultset接口,用来接收查询语句返回的查询结果。
5. JDBC应用步骤
1.注册加载一个驱动
2.创建数据库连接(Connection)
3.创建statement,发送sql语句
4.执行sql语句
5.处理sql结果
6.关闭statement和connection
二、加载与注册驱动
加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动的类名:
Class.forName(driver);
如:
注册MYSQL数据库驱动器
Class.forName("com.mysql.jdbc.Driver");
注册ORACLE数据库驱动器
Class.forName("oracle.jdbc.driver.OracleDriver");
三、建立连接
可以调用 DriverManager 类的 getConnection(…….) 方法建立到数据库的连接:
Connection conn = DriverManager.getConnection(url,uid,pwd);
JDBC URL 用于标识一个被注册的驱动程序,驱动程序管理器通过这个 URL 选择正确的驱动程序,从而建立到数据库的连接。
JDBC URL的标准由三部分组成,各部分间用冒号“:”分隔。
JDBC URL格式:
协议:<子协议>:<子名称>
说明:
协议:JDBC URL中的协议总是jdbc
子协议:子协议用于标识一个数据库驱动程序
子名称:一种标识数据库的方法。子名称可以依不同的子协议而变化,用子名称的目的是为了定位数据库提供足够的信息
jdbc:<子协议>:<子名称>:是一个JNI方式的命名
注:JNI是Java Native Interface的缩写。从Java 1.1开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。
如:
mysql的JDBC URL: jdbc:mysql://localhost:3306/mydbname
oracle的JDBC URL: jdbc:oracle:thin: @localhost :1521:mydbname
四、访问数据库
数据库连接被用于向数据库服务器发送命令和 SQL 语句,在连接建立后,需要对数据库进行访问,执行 sql 语句。
在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:
Statement
PrepatedStatement
CallableStatement
1. 用Statement来执行sql语句
Statement对象用于执行静态的 SQL 语句,并且返回执行结果。
通过调用 Connection 对象的 createStatement 方法创建该对象:
Statement sm = conn.createStatement();
Statement 接口中定义了下列方法用于执行 SQL 语句:
sm.executeQuery(sql); // 执行数据查询语句(select)
sm.executeUpdate(sql); // 执行数据更新语句(delete、update、insert、drop等)
2. 用PreparedStatement来执行sql语句
PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句。
可以通过调用 Connection 对象的 preparedStatement() 方法获取 PreparedStatement 对象:
String sql = "INSERT INTO user (id,name) VALUES (?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, 1);
ps.setString(2, "admin");
ResultSet rs = ps.executeQuery(); // 查询
int c = ps.executeUpdate(); // 更新
PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用 PreparedStatement 对象的 setXXX() 方法来设置这些参数。 setXXX() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值。
3. PreparedStatement与Statement比较
(1)使用PreparedStatement,代码的可读性和可维护性比Statement高。
(2)PreparedStatement 能最大可能提高性能。
DBServer会对预编译语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。
在statement语句中,即使是相同操作但因为数据内容不一样,所以整个语句本身不能匹配,没有缓存语句的意义。事实是没有数据库会对普通语句编译后的执行代码缓存。这样每执行一次都要对传入的语句编译一次。
(3)PreparedStatement能保证安全性,但 Statement有sql注入等安全问题。
4. Statement不安全性
SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令,从而利用系统的 SQL 引擎完成恶意行为的做法。如下代码:
String username="a' or 1=1 or 1='";
String psw="b";
String sql = "select count(*) from t_user where username='"+username+"' and psw='"+psw+"'";
sql语句如下:
select count(*) from t_user where username='a' or 1=1 or 1='' and psw='b'
用 PreparedStatement 取代 Statement 就可以解决。
5. 使用Callable Statement
当不直接使用SQL语句,而是调用数据库中的存储过程时,要用到Callable Statement。
CallabelStatement从PreparedStatement继承。
例如:
String sql = "{call insert_users(?,?)}";
// 调用存储过程
CallableStatement st = conn.prepareCall(sql);
st.setInt(1, 1);
st.setString(2, "admin");
// 在此 CallableStatement对象中执行 SQL 语句,该语句可以是任何种类的 SQL 语句。
st.execute();
五、处理执行结果
查询语句,返回记录集ResultSet。
更新语句,返回数字,表示该更新影响的记录数。
ResultSet:
ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet 接口由数据库厂商实现。
ResultSet 接口的常用方法:
next():将游标往后移动一行,如果成功返回true;否则返回false。ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象的 next() 方法移动到下一行。
getXxx(String name):返回当前游标下某个字段的值。如:getInt("id")或getSting("name")。
六、释放数据库连接
rs.close();
ps.close(); 或者 stat.close();
conn.close();
一般是在finally里面进行释放资源。
七、数据库事务
1. 概述
在数据库中,所谓事务是指一组逻辑操作单元,使数据从一种状态变换到另一种状态。
为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单元:当它全部完成时,数据的一致性可以保持,而当这个单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态。
事务的操作:先定义开始一个事务,然后对数据作修改操作,这时如果提交(COMMIT),这些修改就永久地保存下来,如果回退(ROLLBACK),数据库管理系统将放弃您所作的所有修改而回到开始事务时的状态。
2. 事务的ACID属性
2.1 原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
2.2 一致性(Consistency)
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。(数据不被破坏)
2.3 隔离性(Isolation)
事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
2.4 持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。
3. JDBC 事务处理
在JDBC中,事务默认是自动提交的,每次执行一个 SQL 语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
为了让多个 SQL 语句作为一个事务执行,需调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务:
conn.setAutoCommit(false);
在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务
conn.commit();
在出现异常时,调用 rollback(); 方法回滚事务,一般再catch模块中执行回滚操作。
conn.rollback();
可以通过Connection的getAutoCommit()方法来获得当前事务的提交方式。
注意:在MySQL中的数据库存储引擎InnoDB支持事务,MyISAM不支持事务。
八、批量处理JDBC语句
1. 概述
当需要批量插入或者更新记录时。可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率。
JDBC的批量处理语句包括下面两个方法:
addBatch(String):添加需要批量处理的SQL语句或是参数;
executeBatch();执行批量处理语句;
通常我们会遇到两种批量执行SQL语句的情况:
多条SQL语句的批量处理;
一个SQL语句的批量传参;
2. Statement批量处理
Statement sm = conn.createStatement();
sm.addBatch(sql1);
sm.addBatch(sql2);
...
//批量处理
sm.executeBatch()
//清除sm中积攒的参数列表
sm.clearBatch();
3. PreparedStatement批量传参
PreparedStatement ps = conn.preparedStatement(sql);
for(int i=1;i<100000;i++){
ps.setInt(1, i);
ps.setString(2, "name"+i);
ps.setString(3, "email"+i);
ps.addBatch();
if((i+1)%1000==0){
//批量处理
ps.executeBatch();
//清空ps中积攒的sql
ps.clearBatch();
}
}
注意:MySQL不支持批量处理。
批量处理应该设置一个上限,当批量处理列表中的sql累积到一定数量后,就应该执行,并在执行完成后,清空批量列表。
一般在excel导入数据的时候会用到批处理。
九、使用 JDBC 处理元数据
1. 概述
Java 通过JDBC获得连接以后,得到一个Connection 对象,可以从这个对象获得有关数据库管理系统的各种信息,包括数据库中的各个表,表中的各个列,数据类型,触发器,存储过程等各方面的信息。根据这些信息,JDBC可以访问一个实现事先并不了解的数据库。
获取这些信息的方法都是在DatabaseMetaData类的对象上实现的,而DataBaseMetaData对象是在Connection对象上获得的。
2. 获取数据库元数据
DatabaseMetaData 类中提供了许多方法用于获得数据源的各种信息,通过这些方法可以非常详细的了解数据库的信息:
getURL():返回一个String类对象,代表数据库的URL。
getUserName():返回连接当前数据库管理系统的用户名。
isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。
getDatabaseProductName():返回数据库的产品名称。
getDatabaseProductVersion():返回数据库的版本号。
getDriverName():返回驱动驱动程序的名称。
getDriverVersion():返回驱动程序的版本号。
3. ResultSetMetaData
可用于获取关于 ResultSet 对象中列的类型和属性信息的对象:
getColumnName(int column):获取指定列的名称
getColumnCount():返回当前 ResultSet 对象中的列数。
getColumnTypeName(int column):检索指定列的数据库特定的类型名称。
getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。
isNullable(int column):指示指定列中的值是否可以为 null。
isAutoIncrement(int column):指示是否自动为指定列进行编号,这样这些列仍然是只读的。
十、创建可滚动、更新的记录集
1. Statement
Statement stmt = conn.createStatement(type,concurrency);
2. PreparedStatement
PreparedStatement stmt = conn.prepareStatement(sql,type,concurrency);
type说明:
ResultSet的Type
说明
TYPE_FORWARD_ONLY
结果集不能滚动,只可向前滚动
TYPE_SCROLL_INSENSITIVE
双向滚动,但不及时更新,就是如果数据库里的数据修改过,并不在ResultSet中反应出来
TYPE_SCROLL_SENSITIVE
双向滚动,并及时跟踪数据库的更新,以便更改ResultSet中的数据
Concurrency(并发类型)说明:
ResultSet的Concurrency(并发类型)
说明
CONCUR_READ_ONLY
结果集不可用于更新数据库
CONCUR_UPDATABLE
结果集可以用于更新数据库
3. ResultSet滚动的结果集使用
First:将指针移动到此 ResultSet 对象的第一行
Last:将指针移动到此 ResultSet 对象的最后一行
beforeFirst:将指针移动到此 ResultSet 对象的开头,正好位于第一行之前
afterLast:将指针移动到此 ResultSet 对象的末尾,正好位于最后一行之后
isFirst:检索指针是否位于此 ResultSet 对象的第一行
isLast:检索指针是否位于此 ResultSet 对象的最后一行
isBeforeFirst:检索指针是否位于此 ResultSet 对象的第一行之前
isAfterLast:检索指针是否位于此 ResultSet 对象的最后一行之后
Relative:按相对行数(或正或负)移动指针
Next:将指针从当前位置下移一行
Previous:将指针移动到此 ResultSet 对象的上一行
Absolute:将指针移动到此 ResultSet 对象的给定行编号
如:
rs.absolute(80); //将指针移动到ResultSet 对象的第80行记录。
注意:该特性对Oralce数据有效。但是在Mysql数据库中无效,Mysql只支持TYPE_SCROLL_INSENSITIVE,CONCUR_READ_ONLY。
十一、JDBC连接池
1. 为什么要使用JDBC连接池
普通的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证用户名和密码。需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接。这样的方式将会消耗大量的资源和时间。数据库的连接资源并没有得到很好的重复利用.若同时有几百人甚至几千人在线,频繁的进行数据库连接操作将占用很多的系统资源,严重的甚至会造成服务器的崩溃。
对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将导致重启数据库。
这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。
为解决传统开发中的数据库连接问题,可以采用数据库连接池技术。
2. 数据库连接池(connection pool)
数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。
数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。
3. 数据库连接池工作原理
4. 使用数据库连接池的优点
(1)资源重用:
由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性。
(2)更快的系统反应速度
数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间。
(3)新的资源分配手段
对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源。
(4)统一的连接管理,避免数据库连接泄露
在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露。
5. 常用数据库连接池介绍
JDBC 的数据库连接池使用 javax.sql.DataSource 来表示,DataSource 只是一个接口,该接口通常由服务器(Weblogic, WebSphere, Tomcat)提供实现,也有一些开源组织提供实现,如:
DBCP 数据库连接池
C3P0 数据库连接池
Proxpool 数据库连接池
其中,DBCP和C3P0用得比较多。
Tomcat 在 7.0 以前的版本都是使用 commons-dbcp 做为连接池的实现。
数据源和数据库连接不同,数据源无需创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可。
当数据库访问结束后,程序还是像以前一样关闭数据库连接:conn.close(); 但它并没有关闭数据库的物理连接,它仅仅把数据库连接释放,归还给了数据库连接池。
以上来自http://my.oschina.net/hongdengyan/blog/182978#OSC_h2_6
1. 数据持久化
2. 在java中数据库存储技术分类
3. JDBC概念
4. JDBC常用(重要)类/接口
5. JDBC应用步骤
二、加载与注册驱动
三、建立连接
四、访问数据库
1. 用Statement来执行sql语句
2. 用PreparedStatement来执行sql语句
3. PreparedStatement与Statement比较
4. Statement不安全性
5. 使用Callable Statement
五、处理执行结果
六、释放数据库连接
七、数据库事务
1. 概述
2. 事务的ACID属性
3. JDBC 事务处理
八、批量处理JDBC语句
1. 概述
2. Statement批量处理
3. PreparedStatement批量传参
九、使用 JDBC 处理元数据
1. 概述
2. 获取数据库元数据
3. ResultSetMetaData
十、创建可滚动、更新的记录集
1. Statement
2. PreparedStatement
3. ResultSet滚动的结果集使用
十一、JDBC连接池
1. 为什么要使用JDBC连接池
2. 数据库连接池(connection pool)
3. 数据库连接池工作原理
4. 使用数据库连接池的优点
5. 常用数据库连接池介绍
一、基础知识
1. 数据持久化
持久化(persistence):对象在内存中创建后,不能永久存在。把对象永久的保存起来就是持久化的过程。而持久化的实现过程大多通过各种关系数据库来完成。
持久化的主要应用是将内存中的数据存储在关系型数据库中,当然也可以存储在磁盘文件、XML数据文件中。
2. 在java中数据库存储技术分类
JDBC直接访问数据库。
第三方O/R工具,如Hibernate,mybatis。这些工具都是对JDBC的封装。
3. JDBC概念
JDBC(Java Datebase Connectivity)是一个独立于特定数据库管理系统、通用的sql数据库存取和操作的公共接口。它是JAVA语言访问数据库的一种标准。
4. JDBC常用(重要)类/接口
Java.sql.Driver接口是所有JDBC驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不用的实现。
在程序中不需要直接去访问实现了Driver接口的类,而是由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现。
DriverManager类,用来创建连接,它本身就是一个创建Connection的工厂,设计的时候使用的就是Factory模式,给各数据库厂商提供接口,各数据库厂商需要实现它;
Connection接口,根据提供的不同驱动产生不同的连接;
Statement接口,用来发送SQL语句;
Resultset接口,用来接收查询语句返回的查询结果。
5. JDBC应用步骤
1.注册加载一个驱动
2.创建数据库连接(Connection)
3.创建statement,发送sql语句
4.执行sql语句
5.处理sql结果
6.关闭statement和connection
二、加载与注册驱动
加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动的类名:
Class.forName(driver);
如:
注册MYSQL数据库驱动器
Class.forName("com.mysql.jdbc.Driver");
注册ORACLE数据库驱动器
Class.forName("oracle.jdbc.driver.OracleDriver");
三、建立连接
可以调用 DriverManager 类的 getConnection(…….) 方法建立到数据库的连接:
Connection conn = DriverManager.getConnection(url,uid,pwd);
JDBC URL 用于标识一个被注册的驱动程序,驱动程序管理器通过这个 URL 选择正确的驱动程序,从而建立到数据库的连接。
JDBC URL的标准由三部分组成,各部分间用冒号“:”分隔。
JDBC URL格式:
协议:<子协议>:<子名称>
说明:
协议:JDBC URL中的协议总是jdbc
子协议:子协议用于标识一个数据库驱动程序
子名称:一种标识数据库的方法。子名称可以依不同的子协议而变化,用子名称的目的是为了定位数据库提供足够的信息
jdbc:<子协议>:<子名称>:是一个JNI方式的命名
注:JNI是Java Native Interface的缩写。从Java 1.1开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。
如:
mysql的JDBC URL: jdbc:mysql://localhost:3306/mydbname
oracle的JDBC URL: jdbc:oracle:thin: @localhost :1521:mydbname
四、访问数据库
数据库连接被用于向数据库服务器发送命令和 SQL 语句,在连接建立后,需要对数据库进行访问,执行 sql 语句。
在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:
Statement
PrepatedStatement
CallableStatement
1. 用Statement来执行sql语句
Statement对象用于执行静态的 SQL 语句,并且返回执行结果。
通过调用 Connection 对象的 createStatement 方法创建该对象:
Statement sm = conn.createStatement();
Statement 接口中定义了下列方法用于执行 SQL 语句:
sm.executeQuery(sql); // 执行数据查询语句(select)
sm.executeUpdate(sql); // 执行数据更新语句(delete、update、insert、drop等)
2. 用PreparedStatement来执行sql语句
PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句。
可以通过调用 Connection 对象的 preparedStatement() 方法获取 PreparedStatement 对象:
String sql = "INSERT INTO user (id,name) VALUES (?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, 1);
ps.setString(2, "admin");
ResultSet rs = ps.executeQuery(); // 查询
int c = ps.executeUpdate(); // 更新
PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用 PreparedStatement 对象的 setXXX() 方法来设置这些参数。 setXXX() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值。
3. PreparedStatement与Statement比较
(1)使用PreparedStatement,代码的可读性和可维护性比Statement高。
(2)PreparedStatement 能最大可能提高性能。
DBServer会对预编译语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。
在statement语句中,即使是相同操作但因为数据内容不一样,所以整个语句本身不能匹配,没有缓存语句的意义。事实是没有数据库会对普通语句编译后的执行代码缓存。这样每执行一次都要对传入的语句编译一次。
(3)PreparedStatement能保证安全性,但 Statement有sql注入等安全问题。
4. Statement不安全性
SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令,从而利用系统的 SQL 引擎完成恶意行为的做法。如下代码:
String username="a' or 1=1 or 1='";
String psw="b";
String sql = "select count(*) from t_user where username='"+username+"' and psw='"+psw+"'";
sql语句如下:
select count(*) from t_user where username='a' or 1=1 or 1='' and psw='b'
用 PreparedStatement 取代 Statement 就可以解决。
5. 使用Callable Statement
当不直接使用SQL语句,而是调用数据库中的存储过程时,要用到Callable Statement。
CallabelStatement从PreparedStatement继承。
例如:
String sql = "{call insert_users(?,?)}";
// 调用存储过程
CallableStatement st = conn.prepareCall(sql);
st.setInt(1, 1);
st.setString(2, "admin");
// 在此 CallableStatement对象中执行 SQL 语句,该语句可以是任何种类的 SQL 语句。
st.execute();
五、处理执行结果
查询语句,返回记录集ResultSet。
更新语句,返回数字,表示该更新影响的记录数。
ResultSet:
ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet 接口由数据库厂商实现。
ResultSet 接口的常用方法:
next():将游标往后移动一行,如果成功返回true;否则返回false。ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象的 next() 方法移动到下一行。
getXxx(String name):返回当前游标下某个字段的值。如:getInt("id")或getSting("name")。
六、释放数据库连接
rs.close();
ps.close(); 或者 stat.close();
conn.close();
一般是在finally里面进行释放资源。
七、数据库事务
1. 概述
在数据库中,所谓事务是指一组逻辑操作单元,使数据从一种状态变换到另一种状态。
为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单元:当它全部完成时,数据的一致性可以保持,而当这个单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态。
事务的操作:先定义开始一个事务,然后对数据作修改操作,这时如果提交(COMMIT),这些修改就永久地保存下来,如果回退(ROLLBACK),数据库管理系统将放弃您所作的所有修改而回到开始事务时的状态。
2. 事务的ACID属性
2.1 原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
2.2 一致性(Consistency)
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。(数据不被破坏)
2.3 隔离性(Isolation)
事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
2.4 持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。
3. JDBC 事务处理
在JDBC中,事务默认是自动提交的,每次执行一个 SQL 语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
为了让多个 SQL 语句作为一个事务执行,需调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务:
conn.setAutoCommit(false);
在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务
conn.commit();
在出现异常时,调用 rollback(); 方法回滚事务,一般再catch模块中执行回滚操作。
conn.rollback();
可以通过Connection的getAutoCommit()方法来获得当前事务的提交方式。
注意:在MySQL中的数据库存储引擎InnoDB支持事务,MyISAM不支持事务。
八、批量处理JDBC语句
1. 概述
当需要批量插入或者更新记录时。可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率。
JDBC的批量处理语句包括下面两个方法:
addBatch(String):添加需要批量处理的SQL语句或是参数;
executeBatch();执行批量处理语句;
通常我们会遇到两种批量执行SQL语句的情况:
多条SQL语句的批量处理;
一个SQL语句的批量传参;
2. Statement批量处理
Statement sm = conn.createStatement();
sm.addBatch(sql1);
sm.addBatch(sql2);
...
//批量处理
sm.executeBatch()
//清除sm中积攒的参数列表
sm.clearBatch();
3. PreparedStatement批量传参
PreparedStatement ps = conn.preparedStatement(sql);
for(int i=1;i<100000;i++){
ps.setInt(1, i);
ps.setString(2, "name"+i);
ps.setString(3, "email"+i);
ps.addBatch();
if((i+1)%1000==0){
//批量处理
ps.executeBatch();
//清空ps中积攒的sql
ps.clearBatch();
}
}
注意:MySQL不支持批量处理。
批量处理应该设置一个上限,当批量处理列表中的sql累积到一定数量后,就应该执行,并在执行完成后,清空批量列表。
一般在excel导入数据的时候会用到批处理。
九、使用 JDBC 处理元数据
1. 概述
Java 通过JDBC获得连接以后,得到一个Connection 对象,可以从这个对象获得有关数据库管理系统的各种信息,包括数据库中的各个表,表中的各个列,数据类型,触发器,存储过程等各方面的信息。根据这些信息,JDBC可以访问一个实现事先并不了解的数据库。
获取这些信息的方法都是在DatabaseMetaData类的对象上实现的,而DataBaseMetaData对象是在Connection对象上获得的。
2. 获取数据库元数据
DatabaseMetaData 类中提供了许多方法用于获得数据源的各种信息,通过这些方法可以非常详细的了解数据库的信息:
getURL():返回一个String类对象,代表数据库的URL。
getUserName():返回连接当前数据库管理系统的用户名。
isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。
getDatabaseProductName():返回数据库的产品名称。
getDatabaseProductVersion():返回数据库的版本号。
getDriverName():返回驱动驱动程序的名称。
getDriverVersion():返回驱动程序的版本号。
3. ResultSetMetaData
可用于获取关于 ResultSet 对象中列的类型和属性信息的对象:
getColumnName(int column):获取指定列的名称
getColumnCount():返回当前 ResultSet 对象中的列数。
getColumnTypeName(int column):检索指定列的数据库特定的类型名称。
getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。
isNullable(int column):指示指定列中的值是否可以为 null。
isAutoIncrement(int column):指示是否自动为指定列进行编号,这样这些列仍然是只读的。
十、创建可滚动、更新的记录集
1. Statement
Statement stmt = conn.createStatement(type,concurrency);
2. PreparedStatement
PreparedStatement stmt = conn.prepareStatement(sql,type,concurrency);
type说明:
ResultSet的Type
说明
TYPE_FORWARD_ONLY
结果集不能滚动,只可向前滚动
TYPE_SCROLL_INSENSITIVE
双向滚动,但不及时更新,就是如果数据库里的数据修改过,并不在ResultSet中反应出来
TYPE_SCROLL_SENSITIVE
双向滚动,并及时跟踪数据库的更新,以便更改ResultSet中的数据
Concurrency(并发类型)说明:
ResultSet的Concurrency(并发类型)
说明
CONCUR_READ_ONLY
结果集不可用于更新数据库
CONCUR_UPDATABLE
结果集可以用于更新数据库
3. ResultSet滚动的结果集使用
First:将指针移动到此 ResultSet 对象的第一行
Last:将指针移动到此 ResultSet 对象的最后一行
beforeFirst:将指针移动到此 ResultSet 对象的开头,正好位于第一行之前
afterLast:将指针移动到此 ResultSet 对象的末尾,正好位于最后一行之后
isFirst:检索指针是否位于此 ResultSet 对象的第一行
isLast:检索指针是否位于此 ResultSet 对象的最后一行
isBeforeFirst:检索指针是否位于此 ResultSet 对象的第一行之前
isAfterLast:检索指针是否位于此 ResultSet 对象的最后一行之后
Relative:按相对行数(或正或负)移动指针
Next:将指针从当前位置下移一行
Previous:将指针移动到此 ResultSet 对象的上一行
Absolute:将指针移动到此 ResultSet 对象的给定行编号
如:
rs.absolute(80); //将指针移动到ResultSet 对象的第80行记录。
注意:该特性对Oralce数据有效。但是在Mysql数据库中无效,Mysql只支持TYPE_SCROLL_INSENSITIVE,CONCUR_READ_ONLY。
十一、JDBC连接池
1. 为什么要使用JDBC连接池
普通的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证用户名和密码。需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接。这样的方式将会消耗大量的资源和时间。数据库的连接资源并没有得到很好的重复利用.若同时有几百人甚至几千人在线,频繁的进行数据库连接操作将占用很多的系统资源,严重的甚至会造成服务器的崩溃。
对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将导致重启数据库。
这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。
为解决传统开发中的数据库连接问题,可以采用数据库连接池技术。
2. 数据库连接池(connection pool)
数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。
数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。
3. 数据库连接池工作原理
4. 使用数据库连接池的优点
(1)资源重用:
由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性。
(2)更快的系统反应速度
数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间。
(3)新的资源分配手段
对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源。
(4)统一的连接管理,避免数据库连接泄露
在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露。
5. 常用数据库连接池介绍
JDBC 的数据库连接池使用 javax.sql.DataSource 来表示,DataSource 只是一个接口,该接口通常由服务器(Weblogic, WebSphere, Tomcat)提供实现,也有一些开源组织提供实现,如:
DBCP 数据库连接池
C3P0 数据库连接池
Proxpool 数据库连接池
其中,DBCP和C3P0用得比较多。
Tomcat 在 7.0 以前的版本都是使用 commons-dbcp 做为连接池的实现。
数据源和数据库连接不同,数据源无需创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可。
当数据库访问结束后,程序还是像以前一样关闭数据库连接:conn.close(); 但它并没有关闭数据库的物理连接,它仅仅把数据库连接释放,归还给了数据库连接池。
以上来自http://my.oschina.net/hongdengyan/blog/182978#OSC_h2_6
发表评论
文章已被作者锁定,不允许评论。
-
redis 客户端 jedis
2016-11-09 15:36 488 -
高效序列化工具kryo
2016-11-09 15:29 534 -
Jetty项目简介
2016-11-07 11:28 444jetty是一个开源、基于标准、全功能实现的Java服务器。它 ... -
Quartz 表达式
2016-08-26 15:13 382Quartz中时间表达式的设 ... -
org.apache.commons.dbutils
2016-08-26 11:20 339 -
org.quartz
2016-08-26 10:16 513 -
jedis
2016-08-24 18:08 455 -
待查看
2016-08-02 09:41 4011tair 2 tddl 3hsf 4 分库分表 pmd ... -
Notify、MetaQ、Kafka、ActiveMQ
2016-07-03 12:15 7891 Notify Notify是淘宝自主研发的一套消息服务引 ... -
Reactor、Disruptor
2016-04-27 12:55 1073Reactor 主要用于帮助开发者创建基于JVM的异步应用程序 ... -
redis学习(java调用方式)
2016-04-07 17:56 486【redis数据结构 – 简介 ... -
SonarQube代码质量管理平台安装与使用
2016-03-21 16:13 491代码质量管理工具 http://blog.csdn.net/h ... -
cat监控
2016-03-16 15:22 467 -
durid 数据库连接池
2016-03-15 09:35 1031Druid是Java语言中最好的数据库连接池。Druid能够提 ... -
dubbo 与zookeeper
2016-01-15 09:53 827详见 http://dubbo.io/ http:/ ... -
[Google Guava]
2015-11-25 14:32 6302.3-强大的集合工具类: ... -
跨数据库事务研究
2015-05-12 11:16 868两种方案: 1、分布式 ... -
httpClient 研究
2015-04-19 19:35 481虽然JDK 的 java.net 包中 ... -
dom4j 及其比较
2015-04-19 18:46 6461:DOM DOM 是用与平台和语言无关的方式表示 X ... -
Log4j 深入研究
2015-04-19 17:03 653一、介绍 Log4j是Apache的一个开放源代码项目,通过 ...
相关推荐
JDBC相关的jar包,包括commons-dbcp-1.4-bin,commons-dbutils-1.6-bin,commons-pool-1.5.6-bin,mysql-connector-java-5.1.7-bin
标题 "jdbc相关jar包.zip" 描述中包含的是一系列用于Java数据库连接(JDBC)的库,包括几个特定的数据源管理工具。这些库对于任何Java开发者来说都是至关重要的,尤其是那些需要处理数据库操作的开发者。现在,我们...
这个"neo4j-jdbc相关jar"压缩包包含了必要的库文件,确保了在Java环境中与Neo4j数据库无缝对接。 首先,我们需要理解JDBC的角色。JDBC是Java平台上的一个标准接口,它允许Java应用程序与各种类型的数据库进行通信。...
标题 "跟jdbc相关的一些类库" 提供的信息表明,这些文件是与Java数据库连接(JDBC)相关的类库。JDBC是Java平台上的一个标准API,用于与各种类型的数据库进行通信。下面将详细讨论这些类库及其在Java数据库编程中的...
### JDBC相关Jar包详解 在Java开发中,JDBC(Java Database Connectivity)是一种用于执行SQL语句的Java API,它可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了高度的抽象层...
### JDBC相关知识点详解 #### 一、JDBC简介 JDBC(Java Database Connectivity)是Java中用来对关系型数据库进行统一访问的标准API,它提供了一组接口与规范,允许Java程序连接多种数据库,并执行SQL语句,从而...
本归档文件"Jdbc相关知识点归档.pdf"将深入探讨JDBC的核心概念和应用。 1. JDBC驱动类型: - Type 1:纯Java API,通过ODBC桥连接数据库,性能较低。 - Type 2:部分Java,部分本地代码,如NetJDBC,适用于Oracle...
在这个名为“jdbc相关程序代码”的资源中,我们可以找到一系列用于演示JDBC操作的代码样本。这些示例通常会涵盖数据库连接、查询、更新、事务管理等核心功能。 首先,`DataSource`是Java JDBC API中的一个接口,它...
Java基础之JDBC相关代码是Java编程中一个重要的部分,主要涉及如何与关系型数据库进行交互。在Java中,JDBC(Java Database Connectivity)是一套规范,它为开发者提供了标准的API,使得Java应用程序能够连接到各种...
**JDBC概述** Java Database Connectivity (JDBC) 是Java编程语言中用于标准地访问数据库的API,由Sun Microsystems(现已被Oracle收购)开发并维护。它允许Java开发者通过编写Java代码来连接到各种类型的数据库,...
jdbc相关jar包---c3p0-0.9.5.2.jar----commons-logging-1.2.jar----druid-1.0.9.jar----mysql-----connector-java-8.0.17.jar----spring-beans-5.0.0.RELEASE.jar----spring-core-5.0.0.RELEASE.jar ----spring-...
标题中的“国产达梦数据库对应java-jdbc相关jar包”表明了这个压缩包包含的是用于连接达梦数据库的Java JDBC驱动程序。Java JDBC(Java Database Connectivity)是Java平台上的一个标准API,允许Java应用程序与各种...
Spring JDBC是Spring框架的一个核心模块,它为Java数据库连接(JDBC)提供了一种抽象层,使得开发者可以更轻松地处理数据库操作。Spring JDBC模块的主要目标是减少对JDBC API的直接依赖,通过提供一种更加高级、易于...
本文将深入探讨标题"JDBC相关jar包和配置文件"中涉及的知识点,包括MySQL驱动、数据库连接池(DBCP、C3P0、Druid)以及它们的配置文件。 首先,MySQL驱动是Java程序连接MySQL数据库的关键,文件`mysql-connector-...
Spring JDBC模块是Spring框架的一部分,它提供了对JDBC(Java Database Connectivity)的高级抽象,简化了数据库操作。在这个场景中,我们关注的是Spring JDBC的5.1.3版本。 **Spring JDBC 5.1.3 版本详解** ...
JDBC相关资料,简单易懂,绝对有用!(培训的相关资料)
1. 导入JDBC相关的Java库: ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; ``` 2. 加载JDBC驱动: ```java Class.forName(...
"spring-jdbc jar包"包含了Spring框架中与JDBC相关的所有类和接口,为开发者提供了强大的数据访问支持。 首先,我们来看看Spring JDBC的核心组件: 1. **JdbcTemplate**:这是Spring JDBC的核心类,它通过模板方法...
在标签“sqljdbc_3.0 jdbc”中,“sqljdbc”是指SQL Server JDBC驱动,而“jdbc”再次强调这是与JDBC相关的技术。SQL Server JDBC驱动支持JDBC 4.0规范,这意味着它提供了诸如自动注册驱动、批量处理、行集迭代器等...