一 JDBC JDBC JDBC 中使用 Transaction Transaction Transaction 编程(事务编程)
1. 1. 1. 事务是具备以下特征 (ACID)(ACID) (ACID) 的工作单元:
原子性(Atomicity ) —— 如果因故障而中断,则所有结果均被撤消;
一致性(Consistency ) —— 事务的结果保留不变;
隔离性( Isolation ) —— 中间状态对其它事务是不可见的;
持久性( Durability ) —— 已完成的事务结果上持久的。
原子操作,也就是不可分割的操作,必须一起成功一起失败。
2. 2. 2. 事务处理三步曲:(事务是一个边界)
① connection.setAutoCommit(false); connection.setAutoCommit(false);connection.setAutoCommit(false); // 把自动提交关闭
②正常的 DBDBDB 操作 // 若有一条 SQL SQL SQL 语句失败了,自动回滚
③ connection.commit() connection.commit() connection.commit() // 主动提交
或 connection.rollback() connection.rollback() connection.rollback()// 主动回滚www.tarena.com.cn
8
3. 3. 3. JDBC JDBC JDBC 事务并发产生的问题和事务隔离级别
JDBC 事务并发产生的问题 :
①脏读( D irty R ead s )一个事务读取了另一个并行事务还未提交的数据。
②不可重复读( UnPrpeatable Read )一个事务再次读取之前的数据时,得到的数据不一
致,被另一个已提交的事务修改。
③幻读( P hantom Read )一个事务重新执行一个查询,返回的记录中包含了因为其它最
近提交的事务而产生的新记录。
为了避免以上三种情况的出现,则采用
事务隔离级别 :
以上的五个事务隔离级别都是在 ConnectionConnection Connection 类中定义的静态常量,使用
setTransactionIsolation(intsetTransactionIsolation(int setTransactionIsolation(int level) level) level) 方法可以设置事务隔离级别。
比如: con.setTransactionIsolation(Connection.con.setTransactionIsolation(Connection. con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED );););
完整的代码片段:
try{ try{ try{
con.setAutoCommit(false) con.setAutoCommit(false)con.setAutoCommit(false) ; ; ; // step step step ①把自动提交关闭
Statement Statement Statement stmstmstm = == con.createStatement(); con.createStatement(); con.createStatement();
stm.executeUpdate("insertstm.executeUpdate("insert stm.executeUpdate("insert into into intoperson(id, person(id, person(id, name, name, name, age) age) age) values(520,values(520, values(520, 'X-Man', 'X-Man', 'X-Man', 18)"); 18)");18)");
stm.executeUpdate("insertstm.executeUpdate("insert stm.executeUpdate("insert into into intoPerson(id, Person(id, Person(id, name, name, name, age) age) age) values(521,values(521, values(521, 'Super', 'Super', 'Super', 19)"); 19)");19)");
// step step step ②正常的 DBDBDB 操作
con.commit(); con.commit(); con.commit();// step step step ③成功主动提交
} } } catch(SQLException catch(SQLExceptioncatch(SQLException e){ e){ e){
try{ try{ try{
con.rollback(); con.rollback();con.rollback();
} } } catch(Exception catch(Exceptioncatch(Exception e){ e){ e){ e.printStackTrace(); e.printStackTrace();e.printStackTrace(); } } } // step step step ③′失败则主动回滚
} } }
TRANSACTION_NONE TRANSACTION_NONETRANSACTION_NONE 不使用事务
TRANSACTION_READ_UNCOMMITTEDTRANSACTION_READ_UNCOMMITTED TRANSACTION_READ_UNCOMMITTED 可以读取未提交数据
TRANSACTION_READ_COMMITTEDTRANSACTION_READ_COMMITTED TRANSACTION_READ_COMMITTED
可以避免脏读,不能够读取没提交的数据,
最常用的隔离级别大部分数据库的默认
隔离级别
TRANSACTION_REPEATABLE_READTRANSACTION_REPEATABLE_READ TRANSACTION_REPEATABLE_READ 可以避免脏读,重复读取
TRANSACTION_SERIALIZABLETRANSACTION_SERIALIZABLE TRANSACTION_SERIALIZABLE 可以避免脏读,重复读取和幻读,(事务串
行化)会降低数据库效率www.tarena.com.cn
9
六、 JavaBean JavaBean JavaBean 定义
1 、是一个普通的 Java 类;
2 、在结构上没有预先的规定,不需要容器;
3 、要求放在包中,要求实现java.io.Serializalbe 接口
4 、要求有一个无参的构造方法;
5 、属性的类型必须保持唯一,返回值必须和set 方法参数类型一致
6 、对每个属性要有对应的 get 和 set 方法。注:隐藏属性可以没有。
另外, POJO 与 JavaBean 的区别:
POJO —— P ure O ld J ava Object or P lain O rdinary J ava O bject (简单 Java 类对象)
POJO 原则上不鼓励在 JavaBean 里面写业务逻辑方法。简单说POJO 除了能赋值,也
就是提供 get/set 方法,别的什么也不能做,它就好比一个水杯 , 不是个能烧水的水壶,因为
它没有烧水 () 这个方法,因此只能盛水。 POJO 主要用来和数据库里的表进行对应。
七、 JDBC2.0 JDBC2.0 JDBC2.0 新特性:
1 1 1 、 ScrollabilityScrollability Scrollability 可滚动结果集(可双向滚动),这种结果集不但可以双向滚动,相对定位,
绝对定位,并且可以修改数据信息。
滚动:可支持双向绝对与双向相对滚动,对结果集可进行多次迭代。
con.createStatement(ResultSet.TYPE_SCROLL_con.createStatement(ResultSet.TYPE_SCROLL_con.createStatement(ResultSet.TYPE_SCROLL_ IN IN IN SENSITIVE, SENSITIVE,SENSITIVE,
ResultSet.CONCUR_UPDATABLE);ResultSet.CONCUR_UPDATABLE); ResultSet.CONCUR_UPDATABLE);
TYPE_FORWARD_ONLY TYPE_FORWARD_ONLYTYPE_FORWARD_ONLY :
该常量指示指针只能向前移动的 ResultSet ResultSet ResultSet 对象的类型。
TYPE_SCROLL_INSENSITIVETYPE_SCROLL_INSENSITIVE TYPE_SCROLL_INSENSITIVE :
该常量指示可滚动但通常不受其他的更改影响的ResultSet ResultSet ResultSet 对象的类型。
TYPE_SCROLL_SENSITIVE TYPE_SCROLL_SENSITIVETYPE_SCROLL_SENSITIVE :
该常量指示可以更新的 ResultSet ResultSet ResultSet 对象的并发模式。
滚动特性,对 ResultSet ResultSet ResultSet 调用:
绝对定位: boolean absolute(int row)
可以使用此方法跳到指定的记录位置。定位成功返回 true ,不成功返回 false false false ,若
返回值为 false false false ,则游标不会移动。
void afterLast() ,游标跳到最后一条记录之后。
void beforeFirst() ,游标跳到第一条记录之前。(跳到游标初始位)
相对定位: b oolean first() ,游标指向第一条记录。
b oolean last() ,游标指向最后一条记录。
b oolean next() ,此方法是使游标向下一条记录移动。
b oolean previous() ,可以使游标向上一条记录移动,前提是未到首条记录。www.tarena.com.cn
10
2 、 Updatability 结果集可更新。 ( 主要应用于桌面应用 )
ResultSet ResultSet ResultSet 结果集中,先使用moveToInsertRow() moveToInsertRow() moveToInsertRow() ,然后可以使用updateXxx(int updateXxx(int updateXxx(int
column, column, column, columnTypecolumnType columnType value) value) value) 方法来更新指定列数据,再使用insertRow() insertRow() insertRow() 方法插入记录,
最后将游标指回原位: moveToCurrentRow() moveToCurrentRow() moveToCurrentRow() 。
更新: rs.updateInt(1, ” 13800 ” ); // 修改
rs.deleteRow(); // 删除
rs.updateRow();
注:只有在必要的时候(如桌面应用)才用结果集更新数据库,因为使用结果集更新数
据库效率低下。可更新结果集还要看数据库驱动程序是否支持,如 Oracle 支持,而 MyS QL
就不支持。并且只能针对一张表做结果集更新。而且不能有 join 操作。必须有主键,必须
把所有非空且没有默认值的字段查出。处理可更新结果集时不能用 select * 来执行查询语
句,必须指出具体要查询的字段。
能否使用可更新结果集,要看使用的数据库驱动是否支持,还有只能用于单表且表中有
主键字段(可能会是联合主键),不能够有表连接,会取所有非空字段且没有默认值。
总之,能否使用 JDBC2.0 JDBC2.0 JDBC2.0 ResultSet ResultSet ResultSet 的新特性要看数据库驱动程序是否支持。
3 、 Batch updates 可批量更新
将一组对数据库的更新操作发送到数据库统一执行(数据库支持并发执行操作),以提
高效率。主要是通过减少数据( SQL 语句或参数)在网络上传输的次数来节省时间。
( 1 )对于 Statement Statement Statement 的批量更新处理:
stm. addBatch(String sql 1 ) ; 方法会在批处理缓存中加入一条 sql sql sql 语句。
stm.addBatch(String sql2);
int[] results = stm. executeBatch() ,执行批处理缓存中的所有sql sql sql 语句。
( 2 )对于 PreparedStatement PreparedStatement PreparedStatement 的批量更新处理:
pstm.setInt(1, 11);
pstm.setString(2, ” haha ” ); …
pstm. addBatch() 将一组参数添加到此PreparedStatement PreparedStatement PreparedStatement 对象的批处理命令中。
int[] results = pstm. executeBatch() 将一批命令提交给数据库来执行,如果全部命令
执行成功,则返回更新计数组成的数组。
注意 : : :
int[] 中每一个数表示该 SQL 语句所影响的记录条数。
PreparedStatement PreparedStatementPreparedStatement 中使用批量更新时,要先设置好参数后使用addBatch() addBatch() addBatch() 方法加入
缓存。
批量更新中只能使用更新或插入语句www.tarena.com.cn
11
八、 SQL3.0 SQL3.0 SQL3.0 规范中的新类型
Array Array Array 数组类型,主要用于保存一些类似于数组结构的数据。
Sturct Sturct Sturct 结构
Blob Blob Blob 大的二进制数据文件,最多存储 4G 。
Clob Clob Clob 大文本文件对象,最多存储 4G 。
在使用上述大对象的时候,在使用 JDBC 插入记录时要先插入一个空的占位对象,然后使用
select blobdata from t_blob where id =" + id + " for update 这样的语法来对获得的大对
象,进行实际的写入操作 Blo b 通过 getBinaryOutputStream() 方法获取流进行写入。
getBinaryStream() 方法获得流来获取 Blob 中存储的数据。
C lob 的操作也和 B lob 相同。getAsciiStream() 方法用于读取存储的文本对象,
getAsciiOutputStream() 方法获得流用来向文件对象写入的。
BLOB 与 CLOB 的异同点:
①都可以存储大量超长的数据;
② BLOB (Binary Large Object) 以二进制格式保存于数据库中,特别适合保存图片、视
频文件、音频文件、程序文件等;
③ CLOB (Character Large Object) 以 Character 格式保存于数据库中,适合保存比较长的
文本文件。
九、 SQL SQL SQL 数据类型及其相应的 Java Java Java 数据类型
SQL SQL SQL 数据类型 Java Java Java 数据类型说明
------------------------------------------------------------------------------------------------------------------------------------------
INTEGER 或者 INT int 通常是个 32 位整数
SMALLINT short 通常是个 16 位整数
NUMBER(m, n) java.sql.Numeric 合计位数是 m 的定点十进制数,小数后面有n 位数
DECIMAL(m, n) 同上
DEC(m, n) java.sql.Numeric 合计位数是 m 的定点十进制数,小数后面有 n 位数
FLOAT(n) double 运算精度为 n 位二进制数的浮点数
REAL float 通常是 32 位浮点数
DOUBLE double 通常是 64 位浮点数
CHAR(n) String 长度为 n 的固定长度字符串
CHARACTER(n) 同上
VARCHAR(n) String 最大长度为 n 的可变长度字符串
BOOLEAN boolean 布尔值
DATE java.sql.Date 根据具体设备而实现的日历日期
TIME java.sql.Time 根据具体设备而实现的时间戳
TIMESTAMP java.sql.Timestamp 根据具体设备而实现的当日日期和时间
BLOB java.sql.Blob 二进制大型对象
CLOB java.sql.Clob 字符大型对象
ARRAY java.sql.Array 数组类型www.tarena.com.cn
12
十、面向对象的数据库设计
类的关联,继承在数据库中的体现:
类定义 - - - > 表定义
类属性 - - - > 表字段
类关系 - - - > 表关系
对象 - - - > 表记录
注: Oid( 对象 id) 与业务无关!在数据库中每条记录都对应一个唯一的 id 。
Id 通常是用来表示记录的唯一性的,通常会使用业务无关的数字类型。
Object id 对象的 id , sequence 只有 Oracle 才可用,对象 id ( OID )使用高低位算法先
生成高位,在生成低位,通过运算获得对象 id 。
类应当对象到表,属性对应字段,对象对应记录。
㈠类继承关系对应表:
1 、为每一个类建一张表。通过父类的 Oid 来体现继承关系。
特点:在子类表中引用父类表的主键作为自己的外键。
优点:方便查询、属性没有冗余、支持多态。
缺点:表较多,读写效率低。生成报表比较麻烦。
2 、为每一个具体实体类建一个表
特点:父类的属性被分配到每一个子类表中。
优点:做报表比较容易。
缺点:如果父类发生改变会引起所有的子表随之更改。
并且不支持多态,数据会有冗余。
3 、所有的类在一张表中体现,加一个类型辨别字段
特点:效率高,查询不方便,用于重复字段不多时。
优点:支持多态,生成报表很简单。
缺点:如果如何一个类发生变化,必须改表。字段多,难以维护。
㈡类关联关系对应表
1 、一对一关联,类关系对应成表时有两种做法:
一是共享主键,也就是一方引用另一方的主键既作为外键又作为自身的主键。
二是外键引用,一方引用另一方的主键作为自身的外键,并且自己拥有主键。
2 、一对多关联,也就是多端引用一端的主键当作外键,多端自身拥有主键。
3 、多对多关系,多对多关系是通过中间表来实现的,中间表引用两表的主键当作联合
主键,就可以实现多对多关联。www.tarena.com.cn
13
十一、 JDB JDB JDB C C C 应用的分层
分层就是对功能的隔离,并面向接口编程,降低层与层间的耦合性。
软件的分层初步:
JSP Struts
重新封装可复用封装信息懂业务逻辑数据访问层数据层
调业务无技术难度与业务无关
谁依赖谁就看谁调用谁。
软件的分层设计,便于任务的划分、降低层间的耦合。
结合 PMS 的设计方法,思考这样分层的好处。
并且,使代码尽量减少重复,可复用性好,扩展余地加大,而且尽量减少硬编码。
需求:实现对 Person Person Person 类的数据库持久化基本操作( CRUD CRUD CRUD )。
包结构:
B/S 架构和 C/S 架构:
C/S 架构:两层体系结构,主要应用于局域网中。
B/S 架构:三层体系结构,表现层 + 业务逻辑层 + 数据存储层
注:层面越多,软件越复杂,但更灵活。分层是必须的,但凡事均要有个度。
层次一旦确定,数据就必须按层访问,不能跨层访问。层与层之间最好是单向依赖(单
View Controller Action Service
/ Biz
DAO DBDBDB
tarena
pms
service
dao
entity
util
impl
PersonDao.java
PersonDaoOraImpl.java
PersonDaoMysqlImpl.java
AbstractPersonDao.java
PersonService.java
Person.java
JdbcUtil .java DaoFactory.java
ConnectionFactory.java
dao.properties
dbconfig.properties
Model Model Model 部分
对时间的操作:
ps.setDate(1, Date.valueOf( “ 2007- 12 -13 ” )); // 注意是用 java.sql.Date
ps.setTimestamp(2, new Timestamp(System.currentTimeMillis()));// 对系统时间的截取www.tarena.com.cn
14
向调用)。
(一) JNDI (命名路径服务)
定义:是 Java 的命名和路径服务接口。而 JDBC 是 Java 的数据库访问接口。 JNDI
和 JDBC 是平级关系。 JDBC 存储的数据都是以二维表的接口来大规模存储数据;而 JND I
也用于存储数据,存储的是差异性比较大的 Java 对象,是一些比较零散的信息。
JDBC 取数据时用 SQL 语句访问数据。 JDBCAPI 依赖于驱动程序;而 JNDI 依赖于
服务提供者。 JDBC 一般把数据存储到关系型数据库;而 JNDI 一般把数据存储到小型数
据库、文件,甚至是注册表中。
( JNDI 的方法是在 javax.naming 包下)
bind(String name, Object obj) 将名称绑定到对象资源,建立指定的字符串和对象资源的
关联;
lookup(String name) 通过指定的字符串获得先前绑定的资源
以下是将资源和 JNDI 命名绑定的方法
public static void bind(String context,Object obj) throws NamingException
{
Properties pro = new Properties();
//Weblogic 的 JNDI 服务器参数
pro.put(InitialContext.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
pro.put(InitialContext.PROVIDER_URL,"t3://localhost:7001");
Context ctx = new InitialContext(pro);
ctx.bind(context, obj); // 建立指定的字符串和对象资源的关联
}
(二) DataSourse
定义: 1 、 DataSourse (数据源),包含了连接数据库所需的信息,可以通过数据源获得数
据库连接,有时由于某些连接数据库的信息会变更,所以经常使用包含数据库连接信息的数
据源。
2 、一个标准的数据库连接工厂,保存与数据库相关的信息,可以将数据库的连接信息放在
一个共享的空间进行提取,不用在本地安装。支持 JNDI 的绑定,支持连接池,支持分布
式服务,用 getConnection 方法可获得与数据库的连接。数据源应该由管理员创建(目的www.tarena.com.cn
15
是为了保证数据库的安全)。所以数据源对象一般放在 JNDI 服务器中。
通过 JNDI 获得绑定的资源
public static Object lookup(String context)throws NamingException
{
Properties pro = new Properties();
//Weblogic 的 JNDI 服务器参数
pro.put(InitialContext.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
pro.put(InitialContext.PROVIDER_URL, "t3://localhost:7001");
Context ctx = new InitialContext(pro);
return ctx.lookup(context); // 通过指定的字符串获得先前绑定的资源。
}
(四)分布式的事务管理器 JTA JTAJTA
分布式事务是通过多个异地数据库执行一组相关操作,要保证原子操作的不可分,也不
用再由自己写 commit 和 rollback ,全部都交给中间服务器( TM )来处理。(两阶段提交),
也就是在中间服务器发送 sql 语句等待数据库回应,都回应操作成功才提交,否则同时回滚。
① Regester
② TM execute()
③ Commit TM
④ TM commit DB
(五) RowSet RowSet RowSet
行集,这是一个 JavaBean (事件机制),它增强了 ResultSet 的功能,包装了
Connection 、 Statement 、 ResultSet 、DriverManager 。通过 RowSet 可以获得数据源,
设置隔离级别,也可以发送查询语句,也实现了离线的操作遍历, RowSet 也支持预编译的
Statement 。
RowSet 中的方法大致上和 ResultSet 相同,当需要使用时请查阅JAVA API 参考文档。
达内科技
commit commit commit
TM TM TM
DB1
DB2
commit commit commit
commit commit commit
con1 con1 con1
con2 con2 con2