删除了很多对其他包的引用,现在应该是最小可用的版本了。
索性opensource,LGPL协议,欢迎大家试用。这玩意最大的优点,就是只是一个工具,而不是框架,所以与标准的JDBC和preparedstatement结合的很顺畅,能大幅度降低jdbc写法的工作量,
不过个人还是建议,写入用orm,读取在合适的时候稍微用一下绑定数据的DTO的代码,所以提供了GenericSelect类和GenericUpdate的rawSql函数,方便大家自己拼where的sql,真遇到复杂的select查询,大家还是别指望了,其实hibernate甚至nutzDAO也都指望不上的。
这个工具包,彻底贯彻了读写分离的思想,如果实现读取,需要继承GenericReader,如果实现写入,继承GenericWriter。
而且闲的蛋疼,把自动创建表和数据库也加上了。具体代码参考GenericCreator。
不过里面依赖的的guava,这个是用来测试的。实际用可以删掉。
话说回来,用异步的guava的AsyncEventBus+Executors.newFixedThreadPool()+CountDownLatch()进行多线程的测试,非常高效,强烈推荐。
github地址:
刚刚有更新了,修改了几个bug
依赖的包:
c3p0-0.9.2.1
cos-26Dec2008
guava-15.0
mchange-commons-java-0.2.3.4
mysql-connector-java-5.1.18-bin
下面贴一个具体的实现:代码在github的com.kami.console包下面.
关于最麻烦的Select操作,可以参考如下:
新建一个继承了BaseReader的对象,具体如何在自己的DAO用这个工具可以参考find(TestTable t)的实现,这个find(TestTable t)只是一个例子,无任何实际意义。在这里面也可以随意添加findByXXX的方法。
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.kami.console;
import com.kamike.db.SysDbInst;
import com.kamike.db.generic.BaseReader;
import com.kamike.db.generic.GenericSelect;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author THiNk
*/
public class TestTableReader extends BaseReader {
public TestTableReader(String dbName) {
super(dbName);
}
@Override
public GenericSelect createSelect() {
return new TestTableSelect();
}
@Override
public GenericSelect createSelect(TestTable t) {
return new TestTableSelect(t);
}
public long count(T t) {
GenericSelect select = createSelect();
ResultSet rs = null;
PreparedStatement ps = null;
Connection conn = null;
long ret = 0;
try {
conn = SysDbInst.getInstance().getDatabase().getSingleConnection();
ps = conn.prepareStatement(select.countSQL(select.rawSql(dbName)+ "where t.count=? "), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ps.setLong(1, t.getCount());//这里的查询参数的绑定,只能自己动手,丰衣足食了。
rs = ps.executeQuery();
ret = select.count(rs);
} catch (Exception e) {
ret =0;
System.out.println(this.getClass().getName() + e.toString());
} finally {
try {
if (rs != null) {
rs.close();
rs = null;
}
if (ps != null) {
ps.close();
ps = null;
}
if (conn != null) {
conn.close();
conn = null;
}
} catch (SQLException ex) {
Logger.getLogger(BaseReader.class.getName()).log(Level.SEVERE, null, ex);
}
}
return ret;
}
@Override
public ArrayList find(TestTable t) {
GenericSelect select = createSelect();
ResultSet rs = null;
PreparedStatement ps = null;
Connection conn = null;
ArrayList ret = null;
try {
conn = SysDbInst.getInstance().getDatabase().getSingleConnection();
ps = conn.prepareStatement(select.rawSql(dbName) + "where t.count=? ", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ps.setLong(1, t.getCount());//这里的查询参数的绑定,只能自己动手,丰衣足食了。
rs = ps.executeQuery();
ret = select.fetch(rs);
} catch (Exception e) {
ret = new ArrayList<>();
System.out.println(this.getClass().getName() + e.toString());
} finally {
try {
if (rs != null) {
rs.close();
rs = null;
}
if (ps != null) {
ps.close();
ps = null;
}
if (conn != null) {
conn.close();
conn = null;
}
} catch (SQLException ex) {
Logger.getLogger(BaseReader.class.getName()).log(Level.SEVERE, null, ex);
}
}
return ret;
}
}
然后是实体对象定义:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.kami.console;
import com.kamike.db.generic.FieldLength;
import com.kamike.db.generic.FieldName;
import com.kamike.db.generic.Id;
import com.kamike.db.generic.TableName;
import java.util.Date;
/**
*
* @author THiNk
*/
@TableName("test_table")
public class TestTable {
@Id
@FieldName("id")
@FieldLength(64)
private String id;
@FieldName("count")
private long count;
@FieldName("name")
@FieldLength(255)
private String name;
@FieldName("ready")
private boolean ready;
@FieldName("create_date")
private Date createDate;
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* @return the count
*/
public long getCount() {
return count;
}
/**
* @param count the count to set
*/
public void setCount(long count) {
this.count = count;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the ready
*/
public boolean isReady() {
return ready;
}
/**
* @param ready the ready to set
*/
public void setReady(boolean ready) {
this.ready = ready;
}
/**
* @return the createDate
*/
public Date getCreateDate() {
return createDate;
}
/**
* @param createDate the createDate to set
*/
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
}
然后要实现GenericSelect需要的几个对象new的方法,重载一下GenericSelect。。万恶的Java半吊子泛型。。
/*
* 就写一个new。。不过两个构造器,有参的无参的都要这么实现,还有调用父类的构造器
*/
package com.kami.console;
import com.kamike.db.generic.GenericSelect;
/**
*
* @author THiNk
*/
public class TestTableSelect extends GenericSelect {
public TestTableSelect(TestTable t) {
super(t);
}
public TestTableSelect() {
super();
}
@Override
public TestTable create() {
return new TestTable();
}
}
然后就是调用了。
//查询测试
TestTableReader tts=new TestTableReader("kamike");
TestTable template=new TestTable();
template.setCount(500);
ArrayList testList=tts.find(template);