具体来说指的是数据库,表等定义信息(DDL信息).
1.数据库的元数据:
DatabaseMetaData metaData = Connection.getMetaData();
这个对象表示该Connection 对象所连接的数据库的元数据,元数据包括关于数据库的表、受支持的SQL 语法、存储过程、此连接功能等等的信息.至于对象方法,就自己查看JDK API.其中里面大部分都是Get方法.
2.
ParameterMetaData metaData=stmt.getParameterMetaData();
一个
ParameterMetaData 对象,它包含有关此
PreparedStatement 对象的每个参数标记的编号、类型和属性的信息.
3.
ResultSetMetaData rsmd = rs.getMetaData();
可用于获取关于
ResultSet
对象中列的类型和属性信息的对象
|
数据库元数据有什么作用?就是让我们用来简单封装JDBC.在JDBC中一系列的操作中,都有很多相同的步骤,不同只是SQL语句和参数.而DQL语句可能存在结果.而数据库的操作语言都是执行stmt.executeUpdate. 而查询语言就要稍微复杂一点.分为返回结果ResultSet res无非封装Bean或者是List<Bean>中.封装时使用ResultSetHandle接口处理器.而不同结果集实现处理器是不同.BeanHandle实现ResultSetHandle接口用来处理封装一条记录.BeanListHandle实现ResultHandle用来封装多条记录.这就是所谓的策略模式.最后上代码: /**
* 封装JDBC中的update,insert,delete方法.
*
@param
sql
*
@param
params
*/
public
void
update(String
sql
,Object...params){
try
{
Connection conn =
dataSource
.getConnection();
PreparedStatement stmt = conn.prepareStatement(
sql
);
ParameterMetaData metaData = stmt.getParameterMetaData();
int
paramCount=metaData.getParameterCount();
if
(paramCount>0){
if
(params==
null
|| params.
length
<=0){
throw
new
IllegalArgumentException(
"参数不匹配."
);
}
if
(paramCount!=params.
length
){
throw
new
IllegalArgumentException(
"参数不匹配."
);
}
for
(
int
i=0;i<paramCount;i++){
//设置参数
stmt.setObject(i+1, params[i]);
}
}
stmt.executeUpdate();
}
catch
(SQLException e) {
throw
new
RuntimeException(e);
}
}
/**
* 封装JDBC中的Query方法
*/
public
Object query(String sql,ResultSetHandler rsh,Object...params){
try
{
Connection conn =
dataSource
.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
ParameterMetaData metaData = stmt.getParameterMetaData();
int
paramCount=metaData.getParameterCount();
if
(paramCount>0){
if
(params==
null
|| params.
length
<=0){
throw
new
IllegalArgumentException(
"参数不匹配."
);
}
if
(paramCount!=params.
length
){
throw
new
IllegalArgumentException(
"参数不匹配."
);
}
for
(
int
i=0;i<paramCount;i++){
stmt.setObject(i+1, params[i]);
}
}
ResultSet rs=stmt.executeQuery();
//怎么讲结果集封装到JavaBean中.
Object result = rsh.handle(rs);
return
result;
}
catch
(SQLException e) {
throw
new
RuntimeException(e);
}
}
public
interface
ResultSetHandler {
Object handle(ResultSet rs);
}
两种处理器:
PS:
列名和字段必须要求一致.目前还做不到自定义字段名和字段名的映射关系.
策略模式:图示
场景中的要素:三个妙计,一个锦囊,一个赵云,妙计是亮哥给的,妙计放在锦囊里,俗称就是锦囊妙计嘛,那赵云就是一个干活的人,从锦囊取出妙计,执行,然后获胜
|
了解DBUtil框架,主要熟悉它的不同处理器Handle.具体就不介绍啦,自己查看文档吧.
ArrayHandler
ArrayListHandler
*BeanHandler
*BeanListHandler
ColumnListHandler
KeyedHandler
MapHandler
MapListHandler
*
ScalarHandler
QueryRunner qr = new QueryRunner(数据源);
QueryRunner qr = new QueryRunner(); //与事务控制相关.
|
1.Dao层对于事物的控制(一般不使用,只负责增删改查,不关注业务逻辑)
/**
* 在DButils中使用控制事务,使用同一Connection对象连接.
*/
private
QueryRunner
qr
=
new
QueryRunner();
@Override
public
void
transfer(String sourceName, String destName,
float
money) {
Connection
conn
=
null
;
try
{
conn
= DBCPUtil.
getConnection
();
conn
.setAutoCommit(
false
);
qr
.update(
conn
,
"update account set money=money-? where name=?"
,
new
Object[] {
money, sourceName });
int
a
= 1/0; //抛出异常
qr
.update(
conn
,
"update account set money=money+? where name=?"
,
new
Object[] {
money, destName });
conn
.commit();
}
catch
(Exception e) {
throw
new
RuntimeException(e);
}
finally
{
if
(
conn
!=
null
){
try
{
/*放回数据库连接池*/
conn
.close();
}
catch
(SQLException e) {
throw
new
RuntimeException(e);
}
conn
=
null
;
}
}
}
|
2.Service层对于事物的处理(Service中抛出SQLException,如果Dao换成Hibernate实现的话.就会出现问题)
Dao层的设计Connection对象注入进来:
public
void
transfer(String sourceName, String destName,
float
money){
Connection conn =
null
;
try
{
conn = DBCPUtil.
getConnection
();
conn.setAutoCommit(
false
);
AccountDao dao =
new
AccountDaoImpl(conn);
Account
source = dao.findAccountByName(sourceName);
Account
dest = dao.findAccountByName(destName);
source.setMoney(source.getMoney()-money);
dest.setMoney(dest.getMoney()+money);
dao.updateAccount(source);
int
a
=1/0;
dao.updateAccount(dest);
conn.commit();
}
catch
(SQLException e) {
throw
new
RuntimeException(e);
}
finally
{
if
(conn!=
null
){
try
{
conn.close();
}
catch
(SQLException e) {
e.printStackTrace();
}
}
}
}
|
3.通过ThreadLocal解决上面问题的事务处理 ThreadLocal,直译为“线程本地”或“本地线程”,如果你真的这么认为,那就错了!其实,它就是一个容器,用于存放线程的局部变量,我认为应该叫做 ThreadLocalVariable(线程局部变量)才对.
编写一个控制事务的类:TransactionManager
public
void
transfer(String sourceName, String destName,
float
money) {
TransactionManager.
startTransaction
();
AccountDao dao =
new
AccountDaoImpl(TransactionManager.
getConnection
());
Account source = dao.findAccountByName(sourceName);
Account dest = dao.findAccountByName(destName);
source.setMoney(source.getMoney() - money);
dest.setMoney(dest.getMoney() + money);
dao.updateAccount(source);
int
a
= 1 / 0;
dao.updateAccount(dest);
TransactionManager.
commitTransaction
();
TransactionManager.
release
();
}
|