传统的jdbc样板代码太多。现在提供对jdbc简化的轻量级工具或框架也不少,Spring JDBC Template,jodd db,commons-dbutils,...。我只用过这几个,可能还有更多.这里不谈论orm与jdbc的优劣.为什么要简介这个呢?因为jodd足够轻量并且对官方的api提供了更贴近工作的封闭.适度而灵活.本文只谈一些让您快速上手的api简述
jodd.db.DbManager
通过DBManager可以获取到的关键对象:ConnectionProvider,DbSessionProvider,DbTransactionMode.下面会一一谈到
其实常写jdbc的同仁对上面几个词(Connection,Session,Transaction)并不陌生,我们来一起看看JDBC的代码需要的步骤
1.获取Connection
2.创建一个Statement
3.如果是查询可能会到ResultSet
来一起看一看jodd db是怎样简化的
1:获取Connection / ConnectionProvider
通过DbManager.getConnectionProvider() 或者 ConnectionProvider接口的实现类
ConnectionPoolDataSourceConnectionProvider,
CoreConnectionPool,
DataSourceConnectionProvider,
DriverManagerConnectionProvider,
XADataSourceConnectionProvider
相关对象:DbSession
和hibernate中的session意思一样,对事务的设置或调用都是在此对象上进行
创建方式:
方式1:DbManager.getSessionProvider() .getDbSession()
方式2:new DbSession(ConnectionProvider类实例构造)
到此为止,为下一步工作需要的对象都介绍到了.看一看代码吧:
public static DbSession getJNDIInstance(){
return new DbThreadSession(new DataSourceConnectionProvider(config.getConfig("jndi")));
}
public static DbSession getInstance(){
if(config.getConfig("debug").equals("1")) return getJNDIInstance();
String dc=config.getDbConfig().getDriver();//"com.mysql.jdbc.Driver";
String url=config.getDbConfig().getUrl();//"jdbc:mysql://localhost:3306/iqido";
String un=config.getDbConfig().getUsername();//"root";
String up=config.getDbConfig().getPassword();//"root";
return new DbThreadSession(new DriverManagerConnectionProvider(dc,url,un,up));
}
2.创建一个Statement / DbQuery[DbOomQuery]
DbQuery是DbOomQuery的父类,DbOomQuery对查询进行一些处理,在后面提到注解时会提到,也可以实现jodd.db.QueryMapper<T>来封装查询的jdbc样板代码,spring jdbc也有这一概念.
创建一个DbQuery对象需要参数.
DbQuery(DbSession session, java.lang.String sqlString)
DbOomQuery(DbSession session, java.lang.String sqlString)
还有两个其它的构造函数
String SQL="SELECT 列 FROM 表名 WHERE 条件";
DbSession session = ConnectionInstance.getInstance();
DbOomQuery q=new DbOomQuery(session,SQL);
3.如果是查询可能会到ResultSet / QueryMapper<T>
传统的jdbc在涉及ResultSet时有大量的代码.我们前后对比一下
rs=ps.executeQuery();
while(rs!=null && rs.next()){
p=new Provide();
p.setDomain(rs.getString("domain"));
p.setHost(rs.getString("host"));
p.setName(rs.getString("name"));
p.setChannels(rs.getInt("channels"));
}
QueryMapper<T>就是把while中的代码封装到它的唯一方法中:
public <T> process(ResultSet rs) throws SQLException {}
class ProvideMapper implements QueryMapper<Provide>{
@Override
public Provide process(ResultSet rs) throws SQLException {
// TODO Auto-generated method stub
Provide p=new Provide();
p.setPid(rs.getInt("pid"));
p.setDomain(rs.getString("domain"));
p.setName(rs.getString("name"));
p.setHost(rs.getString("host"));
p.setChannels(rs.getInt("channels"));
return p;
}
}
DbOomQuery在此时用下列方法可以简化jdbc查询时的样板代码
<T> T find(QueryMapper<T> queryMapper)
<T> java.util.List<T> list(QueryMapper<T> queryMapper)
<T> java.util.Set<T> listSet(QueryMapper<T> queryMapper)
@Override
public Provide getProvide(int pid) {
// TODO Auto-generated method stub
String SQL="SELECT pid,domain,name,host,channels FROM king_provide WHERE pid=?";
Provide p=null;
DbSession session = ConnectionInstance.getInstance();
DbOomQuery q = new DbOomQuery(session,SQL);
q.forcePreparedStatement();
q.setInteger(1, pid);
p=q.find(new ProvideMapper());
ConnectionInstance.closeInstance(q,session);
return p;
}
当然写个QueryMapper接口实现类还是觉得麻烦,这时可以使用jodd db注解
类级用:@DbTable,如果类名与表名不一样,可以用value指定表名:
@DbTable(value="king_provide")
public class Provide {}
属性用:@DbColumn,如果属性与表的列名不一样,可以用value指定列名
主键用:@DbId,如果属性与表的列名不一样,可以用value指定列名
注解接口在:jodd.db.oom.meta包中
@DbTable(value="king_provide")
public class Provide {
@DbId
int pid;
/**
* 域名
*/
@DbColumn
String domain;
/**
* 名称
*/
@DbColumn
String name;
/**
* 主机
*/
@DbColumn
String host;
/**
* 频道数量
*/
@DbColumn
int channels;
}
注解后,哪么就不需用QueryMapper接口实现类了,直接使用
<T> T find(java.lang.Class... types)
<T> java.util.List<T> list(java.lang.Class... types)
<T> java.util.Set<T> listSet(java.lang.Class... types)
@Override
public Provide getProvide(int pid) {
// TODO Auto-generated method stub
String SQL="SELECT pid,domain,name,host,channels FROM king_provide WHERE pid=?";
Provide p=null;
DbSession session = ConnectionInstance.getInstance();
DbOomQuery q = new DbOomQuery(session,SQL);
q.forcePreparedStatement();
q.setInteger(1, pid);
p=q.find(Provide.class);
ConnectionInstance.closeInstance(q,session);
return p;
}
1.如果提示事务是只读,可以用DbTransactionMode.setReadOnly(DbTransactionMode.READ_WRITE )
事务的开启,提交,回滚跟jdbc差不多
2.生成主键,jdbc用
ps=conn.prepareStatement(SQL,new String[]{"pid"});
//...
rs=ps.getGeneratedKeys();
jodd示例
DbOomQuery q = new DbOomQuery(session,SQL);
q.setGeneratedColumns("pid");
//...
ResultSet rs = q.getGeneratedColumns();
或者
DbOomQuery q = new DbOomQuery(session,SQL);
q.setGeneratedColumns("pid");
//...
long id = q.getGeneratedKey();
@PetiteBean
public class AppService {
@Transaction
public List<Message> findLastMessages(int count) {
DbSqlBuilder dbsql =
sql("select $C{m.*} from $T{Message m} " +
"order by $m.messageId desc limit :count");
DbOomQuery dbquery = query(dbsql);
dbquery.setInteger("count", count);
return dbquery.list(Message.class);
}
//...
}
4.PreparedStatement中的参数设置方法还是原来的用法.setXXX(),getXXX()
5.关于批量sql
jdbc:
void addBatch(String sql)throws SQLExceptionint[] executeBatch()
jodd db截止到3.6还没有提供类spring jdbcTemplate中的批量操作.所以只能从session中获得 connection,由jdbc来实现,它提供的
JbQuery.public void setBatch(java.lang.String name,java.lang.Object[] array,int startingIndex)
只是生成sql的占位符数量
6.更多的说明文档请访问: http://jodd.org/doc/db/index.html