为了改善之前的增删改查操作,故做了一个小工具。只展示个别方法,道理都是一样的。
这个BaseDao
对下面代码的构造方法中内容引出来的一些基础知识点:
关于this:若存在继承关系,则不管是子类还是父类,this指的都是那个new出来的对象实例。
关于this.成员 和 this.方法 先在本类中找有没有,如果没有则沿着继承关系往上找。故BaseDao
还有就是getGenericSuperclass()这个方法要区别于getSuperclass()方法。
二者都是获取直接继承的父类,只是前者能获取到父类泛型的实体类型。后者则不行。
如果不写成抽象类,你直接来个new BaseDao
ParameterizedType表示的是参数化类型(我觉得可以理解成带泛型实体的类)。比如BaseDao
public abstract class BaseDao {
private Class klass = null;
public BaseDao() {
//获取子类对象直接继承的父类(包含泛型参数) 此处的this是new出来的对象实例
Type superClass = this.getClass().getGenericSuperclass();
//检测该类是否带参
if(superClass instanceof ParameterizedType) {
ParameterizedType paraType = (ParameterizedType) superClass;
//获取泛型表示的真实的实体类型
Type[] args = paraType.getActualTypeArguments();
if(args != null && args.length > 0 && (args[0] instanceof Class)) {
this.klass = (Class) args[0];
}
}
}
//通用的增删改操作
protected int updata(String sql, Object...args) {
Connection conn = null;
PreparedStatement state = null;
try {
conn = JdbcUtils.getConnection();
state = conn.prepareStatement(sql);
for(int index = 0; index < args.length; index++) {
state.setObject(index + 1, args[index]);
}
return state.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.close(conn, state, null);
}
return -1;
}
//获取对象集合
protected List getList(String sql, Object...args){
Connection conn = null;
PreparedStatement state = null;
ResultSet rs = null;
List dataList = new ArrayList<>();
try {
conn = JdbcUtils.getConnection();
state = conn.prepareStatement(sql);
for(int index = 0; index < args.length; index++) {
state.setObject(index + 1, args[index]);
}
state.executeQuery();
rs = state.getResultSet();
//获取结果集的一些元数据
ResultSetMetaData metaData = rs.getMetaData();
while(rs.next()) {
Object obj = this.klass.newInstance();
int count = metaData.getColumnCount();
for(int index = 1; index <= count; index++) {
//获取别名 注意别名就是JavaBean中的成员名
String fieldName = metaData.getColumnLabel(index);
Object value = rs.getObject(fieldName);
//传入对象 成员名 成员值 反射设置值
setValue(obj, fieldName, value);
}
dataList.add((T) obj);
}
return dataList;
} catch (Exception e) {
e.printStackTrace();
}finally {
JdbcUtils.close(conn, state, rs);
}
return null;
}
protected E getValue(String sql, Object...args) {
Connection conn = null;
PreparedStatement state = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
state = conn.prepareStatement(sql);
for(int index = 0; index < args.length; index++) {
state.setObject(index + 1, args[index]);
}
state.executeQuery();
rs = state.getResultSet();
if(rs.next()) {
return (E) rs.getObject(1);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JdbcUtils.close(conn, state, rs);
}
return null;
}
private void setValue(Object obj, String fieldName, Object value) {
try {
Field field = this.klass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
需要注意的一点是数据库中的字段名称和java的成员名称可能会不同。所以在制造sql语句的时候一定要利用别名。
首先需要导入jar包:我用的是commons-dbutils-1.3.jar
代码示例:
public abstract class DataBase {
private Class klass = null;
private QueryRunner queryRunner = null;
public DataBase() {
Type superClass = this.getClass().getGenericSuperclass();
if(superClass instanceof ParameterizedType) {
ParameterizedType paraType = (ParameterizedType) superClass;
Type[] args = paraType.getActualTypeArguments();
if(args != null && args.length > 0 && (args[0] instanceof Class)) {
this.klass = (Class) args[0];
}
}
this.queryRunner = new QueryRunner();
}
//获取对象集合 BeanListHandler
protected List getList(String sql, Object...args){
Connection conn = JdbcUtils.getConnection();
try {
return this.queryRunner.query(conn, sql,
new BeanListHandler(klass), args);
} catch (SQLException e) {
e.printStackTrace();
}finally{
JdbcUtils.close(conn, null, null);
}
return null;
}
//查询特殊值new ScalarHandler()
protected E getValue(String sql, Object...args) {
Connection conn = JdbcUtils.getConnection();
try {
return (E) this.queryRunner.query(conn, sql, new ScalarHandler(), args);
} catch (SQLException e) {
e.printStackTrace();
}finally{
JdbcUtils.close(conn, null, null);
}
return null;
}
//批量操作
protected void batch(String sql, Object[]...args) {
Connection conn = JdbcUtils.getConnection();
try {
this.queryRunner.batch(conn, sql, args);
} catch (SQLException e) {
e.printStackTrace();
}finally{
JdbcUtils.close(conn, null, null);
}
}
}
基于此工具的一个测试:
定义IUserDao接口:
public interface IUserDao {
public List getUserListByMoney(double money);
public long getUserCount();
public void batchUpdateMoney(List userList);
}
实现类:
public class UserDaoImpl extends DataBase implements IUserDao{
public UserDaoImpl() {
JdbcUtils.scanf("/druid.properties");
}
@Override
public List getUserListByMoney(double money) {
String sql = "select id, username userName, password, email, money from t_user where money=?";
return getList(sql, new Object[]{money});
}
@Override
public long getUserCount() {
String sql = "select count(*) from t_user";
return getValue(sql, new Object[]{});
}
//批量操作 以批量更新余额为例
@Override
public void batchUpdateMoney(List userList) {
String sql = "update t_user set money=? where username=?";
//总共更新的记录数
int size = userList.size();
Object[][] args = new Object[size][2];
//填充数组
for(int index = 0; index < size; index++) {
Object[] arg = new Object[2];
arg[0] = userList.get(index).getMoney();
arg[1] = userList.get(index).getUserName();
args[index] = arg;
}
batch(sql, args);
}
}
测试类:
public class Test {
public static void main(String[] args) {
UserDaoImpl userDao = new UserDaoImpl();
System.out.println("总用户个数: " + userDao.getUserCount());;
System.out.println("--------------获取余额为10000元的用户---------------------------------");
List userList = userDao.getUserListByMoney(10000.0);
for(User user : userList) {
System.out.println(user);
}
userList = new ArrayList();
userList.add(new User("san", "", "", 3333.0));
userList.add(new User("feng", "", "", 3333.0));
System.out.println("修改san和feng的余额为3333");
userDao.batchUpdateMoney(userList);
System.out.println("修改成功");
System.out.println("--------------获取余额为3333元的用户---------------------------------");
userList = userDao.getUserListByMoney(3333.0);
for(User user : userList) {
System.out.println(user);
}
}
}
测试结果: