在学习持久层框架之前,反复编写dao层代码编烦了,就自己实现了一个能方便地根据数据库表创建javaBean,并实现其增删改查,结果集转化为List集合,sql编译语句里参数赋值的自动化的“框架”。
本文所使用的数据库是mysql自带的simple data里的sakila数据库
先看一下使用效果:
- 先编写并运行测试类创建javaBean:
Country,City,Address,Customer
package com.iss.db.dao.toolkit;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
import com.iss.db.dao.connectdb.OffLineConn;
import com.iss.db.dao.dbinfo.DBConfig;
/**
* 创建javaBean源文件(下面的代码还可以进一步封装)
*/
public class CreateJavaBeanSource {
@Test
public void test01() throws Exception{
ResultSet rs = TableTool.execQuery(new OffLineConn(new DBConfig()).getConn().prepareStatement("select * from country where 1>2"));
String descTable = DBTool.descTable(rs);
System.out.println(descTable);
DBTool.createClazzToSource(rs, "src/main/java", "com.iss.db.bean.Country", "country");
rs = TableTool.execQuery(new OffLineConn(new DBConfig()).getConn().prepareStatement("select * from city where 1>2"));
descTable = DBTool.descTable(rs);
System.out.println(descTable);
DBTool.createClazzToSource(rs, "src/main/java", "com.iss.db.bean.City", "city");
rs = TableTool.execQuery(new OffLineConn(new DBConfig()).getConn().prepareStatement("select * from address where 1>2"));
descTable = DBTool.descTable(rs);
System.out.println(descTable);
DBTool.createClazzToSource(rs, "src/main/java", "com.iss.db.bean.Address", "address");
rs = TableTool.execQuery(new OffLineConn(new DBConfig()).getConn().prepareStatement("select * from customer where 1>2"));
descTable = DBTool.descTable(rs);
System.out.println(descTable);
DBTool.createClazzToSource(rs, "src/main/java", "com.iss.db.bean.Customer", "customer");
}
}
上述代码中DBTool.createClazzToSource(包含所有列的结果集,工程src名,javaBean全类名,数据库表名),还可以进一步封装使之更易用
- 编写上述4个javaBean对应的DAO类:
- CounryDao.java :
package com.iss.db.dao.tablemanager;
import com.iss.db.bean.Country;
import com.iss.db.dao.tableinfo.TableDic;
public class CountryDao extends TableManager{
public CountryDao(){
super(Country.class,new TableDic("country_id", "country", "country"));
}
}
2.CityDao.java
package com.iss.db.dao.tablemanager;
import com.iss.db.bean.City;
import com.iss.db.dao.tableinfo.TableDic;
public class CityDao extends TableManager {
public CityDao() {
super(City.class, new TableDic("city_id", "city", "city", "country_id"));
}
}
3.AddressDao.java
public class AddressDao extends TableManager{
public AddressDao(){
super(Address.class, new TableDic("address_id", "address", "address","address2","district","city_id","postal_code","phone"));
}
}
4.CustomerDao.java
public class CustomerDao extends TableManager{
public CustomerDao(){
super(Customer.class,new TableDic("customer_id", "customer","store_id","first_name","last_name","email","address_id","active"));
}
}
**上述代码其实只是在给TableManager传入参数,参数提供javaBean的class信息,以及数据库表的主要信息new TableDic(“主键”,”表明”,”更新操作的字段1”,”更新操作的字段2”,……)**
实现过程:
**1. 核心问题:遍历结果集创建java对象很麻烦,各种重复操作,如何省去?****代码组织结构如下:** ![代码组织结构](https://img-blog.csdn.net/20170803161700485?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2luYXRfMzQ4MjAyOTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)1.学过反射,想到可以通过反射调用对象的set方法为之赋值。
2.如过自动赋值,那么对于ResultSet的每一行,如果遍历它的各个字段,查阅发现ResultSet.getMetaData()方法可以获取各个列的信息(名称,类型)。
3.调用javaBean对象的set方法需要考虑传入参数类型, 那么没问题, setmethod.getGenericParameterTypes()[0].getTypeName()可以办到。
4. SQL数据库类型明显要比java里的类型多,需要做个类型对应。
5. 如何自动生成java源文件,那不就是io文件流嘛,拼接好javaBean字符串写入文件即可。
对该功能实现分多个层是为了易于修改和扩展,上图中HeadPicDao.java,MyTool.java与本文介绍的东西无关。
1)包DAO层细分了几个包:
1. dao.connectdb: 获取数据库连接的抽象,可以是永久连接,可以使连接池,OffLineConn是对GetDBConn的一个开发时实现,实际中可以使用数据库连接池,远程连接等来实现。
2. dao.tableinfo: 数据库表关键信息的抽象,关键信息包括(主键,表名,更新操作的字段[]),是创建某个表DAO层唯一需要的输入,TableDic是对TableInfo的实现,也可以用从配置文件获取表信息的方法实现TableInfo。
3. dao.dbinfo: 对数据库信息的抽象,关键信息包括(驱动名,数据库url,用户名,密码),这里就把数据库的信息写死在了DBconfig.java了,如果想换成从配置文件获取,只需要写一个从配置文件获取数据库信息的类实现DBInfo接口即可(策略模式)。
4. dao.toolkit:工具类,获得连接后可以使用的工具DBTool,制定了表之后可用的工具TableTool,数据格式转化工具MyTool(实现json, javaBean, ResultSet 等值间的转化)
5. dao.tablemanager: 每个表Dao的模板类,以及每个数据表对应的继承类,在继承里指定对应的javaBean和tableinfo信息即可
2) 特点:
1. 根据数据库表自动创建javaBean文件。
2. ResultSet到javaBean的变化依据数据库字段名在javaBean中找对应的set方法,判断set方法的输入参数类型和数据库表类型是否一致(类型匹配),匹配则调用这个set方法进行赋值。
3. 更新类操作根据初始化时指定的数据库表信息里的主键信息、更新字段信息进行,程序根据这些字段名自动从javaBean中提取信息进行更新或者插入操作。
4. 查询自动包装成javaBean,根据的是数据库表的属性。
5. 综上,javaBean可以任意添加成员变量,其它方法,只需要满足javaBean里的get方法是数据库属性的超集、javaBean里的set方法是tableinfo指定更新属性的超集即可。
核心代码如下 ( 其余代码会在后面贴上 )
**1. 结果集转化为javaBean集合(MyTool.java里面的部分代码)**数据类型映射表:
// 类型对照表,试着用反射实现javaBean装箱操作
public final static Map<String, String> TYPE_DIC = new HashMap<String, String>() {
{
put("VARCHAR", "java.lang.String");
put("VARCHAR2", "java.lang.String");
put("CHAR", "java.lang.String");
put("TEXT", "java.lang.String");
put("MEDIUMTEXT", "java.lang.String");
put("LONGTEXT", "java.lang.String");
put("INT", "java.lang.Integer,int");
put("SMALLINT", "java.lang.Short,short");
put("TINYINT", "java.lang.Short,short,java.lang.Boolean");
put("SMALLINT UNSIGNED","java.lang.Short,short");
put("FLOAT", "java.lang.Float,float");
put("DECIMAL", "java.lang.Float,folat");
put("DOUBLE", "java.lang.Double,double");
put("YEAR", "java.sql.Date,java.util.Date");
put("DATE", "java.sql.Date,java.util.Date");
put("TIME", "java.sql.Date,java.util.Date");
put("DATETIME", "java.sql.Timestamp,java.util.Date");
put("TIMESTAMP", "java.sql.Timestamp,java.util.Date");
put("ID", "java.lang.Long,long");
put("BIT", "java.lang.Boolean,boolean");
put("BINARY", "java.lang.Boolean,boolean");
put("BOOLEAN", "java.lang.Boolean,boolean");
put("BIGINT", "java.math.BigInteger,long");
put("INTEGER", "java.lang.Integer,int");// 或者long ?
put("BLOB", "java.lang.String");// 或者 java.lang.byte[] ?
put("GEOMETRY","java.lang.String");
put("TINYINT UNSIGNED","java.lang.Integer,int,java.lang.Byte,buty");
}
};
// 可以通过 valueOf(String arg)装箱的基本数据类型
public final static Map<String, String> BASIC_TYPE = new HashMap<String, String>() {
{
put("int", "java.lang.Integer");
put("long", "java.lang.Long");
put("float", "java.lang.Float");
put("double", "java.lang.Double");
// put("char","java.lang.Character");//他没有以字符串为参数的构造方法,但是数据库没有与之对应的类型,这里不对其进行单独处理
put("byte", "java.lang.Byte");
put("boolean", "java.lang.Boolean");
put("short", "java.lang.Short");
}
};
转换函数
/**
* ResultSet --> JavaBean
* 传入javaBean的class,从结果集取出数据创建对象并返回
* @param rs
* @param clazz
* @return
*/
public static <T> T resultSetToJavaBean(ResultSet rs, Class<T> clazz) {
T entity = null;
// TODO: java.sql.ResultSet转化为JavaBean
// 获取所有set方法以及set的属性名,并存入Map集合
Method[] methods = clazz.getMethods();
Map<String, Method> setMethods = new HashMap<String, Method>();
for (Method method : methods) {
// Pattern.compile("set.*").matcher(method.getName()).matches()
if (method.getName().substring(0, 3).equals("set")) {
setMethods.put(method.getName().substring(3,4).toLowerCase()+method.getName().substring(4), method);// 获取全部set方法的属性名以及方法本身
}
}
// 从result中获取值创建JavaBean对象
try {
ResultSetMetaData metaData = rs.getMetaData();
int cc = metaData.getColumnCount();
T ob = clazz.newInstance();
if (!rs.next()) {
return null;
}
for (int i = 1; i <= cc; i++) {
String coluname = metaData.getColumnName(i);// 列名,作为数据表列和JavaBean属性唯一匹配标识
coluname = nameInDb2nameInJava(coluname);
String coltype = metaData.getColumnTypeName(i);// 表的属性类型
Method setmethod = setMethods.get(coluname);// set方法
String argType = setmethod.getGenericParameterTypes()[0].getTypeName();// set方法的传入参数
if (!setMethods.containsKey(coluname)) {// 如果在javaBean中找不到列属性
throw new Exception("属性名异常:javaBean中不包含" + coluname + "属性");
} else if (TYPE_DIC.get(coltype) == null) {// 如果属性类型未列入
System.err.println("警告:" + coluname + "的类型为" + coltype + "是不常见类型,转化为String类型");
} else if (!TYPE_DIC.get(coltype).contains(argType)) {// 如果同一属性的类型无法匹配
throw new Exception("类型不匹配:属性" + coluname + "的数据库类型为" + coltype + "而JavaBean中类型是" + argType);
}
if (BASIC_TYPE.containsKey(argType)) {
argType = BASIC_TYPE.get(argType);
} // 如果是基本数据类型,则转化位java.lang下类型
Object argOb = null;// set方法的传入值
if (argType.contains("Date") || argType.contains("Time")) {
// 日期类型需要转化,而其他常见类型可以用传入字符串的构造方法创建对象
Timestamp data = rs.getTimestamp(nameInJava2nameInDb(coluname));
if (argType.contains("util")) {
// 如果是java.util.Date
argOb = new java.util.Date(data.getTime());
} else {
Class argClazz = Class.forName(argType);
argOb = argClazz.getConstructor(String.class).newInstance(data.getTime());
}
} else if (BASIC_TYPE.containsValue(argType)) {
// 如果是基本类型,用构造方法装箱创建对象
Class argClazz = Class.forName(argType);
argOb = argClazz.getConstructor(String.class).newInstance(rs.getString(nameInJava2nameInDb(coluname)));
} else {
// 其余的按照字符类型来处理
argOb = rs.getString(nameInJava2nameInDb(coluname));
}
// 调用JavaBean的set方法设置值
setMethods.get(coluname).invoke(ob, argOb);
}
entity = ob;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return entity;
}
/**
* ResultSet --> JavaBean 符合开发习惯的函数封装
*
* @param rs
* @param clazz
* @return
*/
public static <T> T handler(ResultSet rs, Class<T> clazz) {
return resultSetToJavaBean(rs, clazz);
}
/**
* ResultSet --> List<JavaBean>
*
* @param rs
* @param clazz
* @return
*/
public static <T> List<T> handlerList(ResultSet rs, Class<T> clazz) {
List<T> list = new ArrayList<T>();
T entity = null;
do{
entity = handler(rs, clazz);
list.add(entity);
}while(entity!=null);
if(list.size()>0)
list.remove(list.size()-1);
return list;
}
**2.自动生成javaBean源文件(DBTool.java里的部分代码)**
/**
* 根据数据库结果集创建类的字符,如果输出到文件io流则是javaBean源文件
* @param rs
* @return
*/
public static String createClazz(ResultSet rs, String clazzName) throws Exception {
StringBuffer sb = new StringBuffer();
ResultSetMetaData metaData = rs.getMetaData();
int cc = metaData.getColumnCount();
Map<String, String> desc = new HashMap<String, String>();
for (int i = 1; i <= cc; i++) {
String coluname = metaData.getColumnName(i);// 列名,作为数据表列和JavaBean属性唯一匹配标识
// 下划线命名法转化为驼峰命名法
coluname = MyTool.nameInDb2nameInJava(coluname);
String coltype = metaData.getColumnTypeName(i);// 表的属性类型
desc.put(coluname, TYPE_DIC.get(coltype));
}
// 把基本类型的属性转为基本类型
// 需要导的包
List<String> importPackage = new ArrayList<String>();
for (String filed : desc.keySet()) {
// System.out.println(filed+": "+desc.get(filed));
boolean flag = true;// 标记是否基本类型
for (String bst : BASIC_TYPE.keySet()) {
if (desc.get(filed).contains(bst)) {
desc.replace(filed, bst);
flag = false;
}
}
if (flag) {
if (desc.get(filed).contains(",")) {
importPackage.add(desc.get(filed).substring(desc.get(filed).indexOf(',') + 1, desc.get(filed).length()));
} else {
importPackage.add(desc.get(filed));
}
desc.replace(filed,
desc.get(filed).substring(desc.get(filed).lastIndexOf('.') + 1, desc.get(filed).length()));
}
}
// unique pakage-name
List<String> uniquepackage = new ArrayList<String>();
for (int i = 0; i < importPackage.size(); i++) {
boolean flag = true;
for(int j=0;j<uniquepackage.size();j++){
if(uniquepackage.get(j).equals(importPackage.get(i))){
flag = false;
break;
}
}
if(flag){
uniquepackage.add(importPackage.get(i));
}
}
uniquepackage.remove("java.lang.String");
importPackage = uniquepackage;
// package name
if (clazzName.contains(".")) {
sb.append("package " + clazzName.substring(0, clazzName.lastIndexOf(".")) + ";\r\n\r\n");
clazzName = clazzName.substring(clazzName.lastIndexOf(".") + 1, clazzName.length());
}
// import package
for (String string : importPackage) {
sb.append("import "+string + ";\r\n");
}
// 类名
sb.append("\r\npublic class " + clazzName + " {\r\n");
// 定义属性
for (String filed : desc.keySet()) {
sb.append("\tprivate " + desc.get(filed) + " " + filed + ";\r\n");
}
// 定义get/set方法
for (String filed : desc.keySet()) {
sb.append("\tpublic void set" + filed.substring(0, 1).toUpperCase() + filed.substring(1) + "( "
+ desc.get(filed) + " " + filed + " ) {\r\n");
sb.append("\t\tthis." + filed + " = " + filed + ";\r\n\t}\r\n");
sb.append("\tpublic " + desc.get(filed) + " get" + filed.substring(0, 1).toUpperCase()
+ filed.substring(1) + "() {\r\n");
sb.append("\t\treturn this." + filed + ";\r\n\t}\r\n");
}
// 定义toString方法
sb.append("\tpublic String toString() {\r\n\t\treturn \"" + clazzName + " [");
for (String filed : desc.keySet()) {
sb.append(filed + "=\" + " + filed + " + \",");
}
sb.delete(sb.length() - 1, sb.length());
sb.append("]\";\r\n\t}\r\n");
sb.append("}\r\n\r\n");
return sb.toString();
}
/**
* 给出src文件名,给出javaBean的全类名,给出数据库表的名字自动创建数据表对应的javaBean的java源文件
* 如:
* new BeanTool().createClazzToSource("src/main/java","com.iss.db.bean.KKUser","user");
*
* @param srcName
* @param clazzFullName
* @param tableName
*/
public static void createClazzToSource(ResultSet rs,String srcName,String clazzFullName,String tableName){
try {
if(!srcName.endsWith("/")){
srcName+="/";
}
String path = "";
String fileName = "";
if(clazzFullName.contains(".")){
fileName = clazzFullName.substring(clazzFullName.lastIndexOf(".")+1,clazzFullName.length())+".java";
path = srcName +clazzFullName.substring(0,clazzFullName.lastIndexOf(".")).replace('.', '/')+"/";
}else{
fileName = clazzFullName+".java";
path = srcName;
}
fileName = fileName.substring(0, 1).toUpperCase()+fileName.substring(1);
System.out.println(path);
System.out.println(fileName);
File ff = new File(path+fileName);
if(!ff.exists()){ff.createNewFile();}
BufferedWriter bf = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(ff)));
String a = createClazz(rs, clazzFullName);
bf.write(a);bf.flush();bf.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
**3.前面函数使用的属性名转化函数(MyTool.java里的部分代码)**
数据库采用下划线命名规则,java里采用驼峰式命名规则,需要转化
/**
* 数据库里下划线命名规则转化为java里面驼峰式命名
* @param dbname
* @return
*/
public static String nameInDb2nameInJava(String nameInDb) {
String coluname = nameInDb.toLowerCase();
if (Pattern.compile("^\\S+_+\\S+$").matcher(coluname).find()) {
char[] ca = coluname.toCharArray();
for (int j = 1; j < ca.length - 1; j++) {
if (ca[j]=='_') {
ca[j]='\0';
ca[j + 1] = Character.toUpperCase(ca[j + 1]);
}
}
coluname = new String(ca);
}
return coluname.replaceAll("\0", "");
}
/**
* 驼峰命名规则转化为下划线命规则
* @param nameInJava
* @return
*/
public static String nameInJava2nameInDb(String nameInJava) {
char[] ca = nameInJava.toCharArray();
StringBuffer sb = new StringBuffer();
sb.append(ca[0]);
for(int j=1;j<ca.length;j++) {
Character cha = ca[j];
if(Character.isUpperCase(cha)) {
sb.append('_');
}
sb.append(cha);
}
return sb.toString().toLowerCase();
}
**4.初步封装数据库查询和更新以节省设置参数的重复**
package com.iss.db.dao.toolkit;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TableTool extends MyTool{
/**
* <pre>
* 设置pstmt里面的第i个问号的值为传入的oo对象
* 根据oo对象的数据类型设置
* @param pstmt
* @param i sql语句中的第i个问好
* @param oo
*/
private static void pstmtSet(PreparedStatement pstmt,int i,Object oo){
try {
String clazz = oo.getClass().getName();
System.out.println("TableTool.pstmtSet() : "+clazz);
switch (clazz){
case "int":
case "java.lang.Integer":
pstmt.setInt(i, (Integer)oo);
break;
case "float":
case "java.lang.Float":
pstmt.setFloat(i, (Float)oo);
break;
case "double":
case "java.lang.Double":
pstmt.setDouble(i, (Double)oo);
break;
case "long":
case "java.lang.Long":
pstmt.setLong(i, (Long)oo);
break;
case "java.util.Date":
pstmt.setDate(i,(new java.sql.Date(((java.util.Date)oo).getTime())));
break;
case "boolean":
case "java.lang.Boolean":
pstmt.setBoolean(i, (boolean)oo);
break;
case "short":
case "java.lang.Short":
pstmt.setShort(i, (short)oo);
break;
case "java.lang.String":
pstmt.setString(i, (String)oo);
break;
default:
pstmt.setString(i, oo.toString());
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 执行有参数的更新语句
* @param sql
* @param o是若干个(0到多个)sql语句里面对应的参数
* @return
*/
public static int execUpdate(PreparedStatement pstm,Object... o){
int re=0;
try {
for(int i=1;i<=o.length;i++){
pstmtSet(pstm,i,o[i-1]);
}
re = pstm.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
return re;
}
/**
* 执行有参数的查询语句
* @param sql
* @param o是若干个(0到多个)sql语句里面对应的参数
* @return
*/
public static ResultSet execQuery(PreparedStatement pstm,Object... o) {
ResultSet rs = null;
try {
for(int i=1;o!=null&&i<=o.length;i++){
pstmtSet(pstm,i,o[i-1]);
}
rs = pstm.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
return rs;
}
/**
* 执行无参数的更新语句
* @param sql
* @return
*/
public static int execUpdate(Statement stmt ,String sql){
int re=0;
try {
re = stmt.executeUpdate(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return re;
}
/**
* 执行无参查询语句
* @param sql
* @return
*/
public static ResultSet execQuery(Statement stmt,String sql){
ResultSet rs = null;
try {
rs = stmt.executeQuery(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return rs;
}
}
- 最上层封装,实现通用的函数:
- 根据主键查询,返回javaBean(输入参数是主键赋了值的javaBean)
- 传入javaBean更新数据库里主键对应的数据项
- 传入javaBean删除数据库里主键与之对应的数据项
- 传入javaBean插入到数据库(对于mysql数据库可以返回新插入的那条数据)
- 运行含有where子句的查询删除操作
- 运行普通的查询更新有参或者无参sql语句返回结果集
TableManager .java
package com.iss.db.dao.tablemanager;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Map;
import com.iss.db.dao.connectdb.GetDBConn;
import com.iss.db.dao.connectdb.OffLineConn;
import com.iss.db.dao.dbinfo.DBConfig;
import com.iss.db.dao.tableinfo.TableInfo;
import com.iss.db.dao.toolkit.MyTool;
import com.iss.db.dao.toolkit.TableTool;
/**
* 该类定义了所有数据表的增删查该操作,除了byWhere的查询和删除操作,其余均要求传入javaBean的对象
* @author tim
*
*/
public class TableManager {
private String UPDATE;
private String INSERT;
private String SLELECT_ALL;
private Class CLAZZ;
protected TableInfo tableinfo = null;
private GetDBConn getDBConn = null;
protected PreparedStatement pstmt = null;
protected Statement stmt = null;
protected Connection conn = null;
protected ResultSet rs = null;
private void init() {
String que = "";
UPDATE = "UPDATE " + tableinfo.tableName() + " SET ";
INSERT = "INSERT INTO " + tableinfo.tableName() + " (";
for (String fil : tableinfo.updateArray()) {
INSERT += fil + " ,";
UPDATE += fil + "= ? ,";
que += "?,";
}
UPDATE = UPDATE.substring(0, UPDATE.length() - 1);
UPDATE += " WHERE " + tableinfo.pkName() + " = ?";
INSERT = INSERT.substring(0, INSERT.length() - 1);
que = que.substring(0, que.length() - 1);
INSERT += ") VALUES(" + que + ")";
SLELECT_ALL = "SELECT * FROM " + tableinfo.tableName() + " ";
getDBConn = new OffLineConn(new DBConfig());// 这里制定数据库连接
}
public TableManager() {
super();
}
public void setClazz(Class clazz) {
this.CLAZZ = clazz;
}
public TableManager(Class clazz, TableInfo tableinfo) {
super();
this.CLAZZ = clazz;
this.tableinfo = tableinfo;
init();
}
protected Connection getConn() {
conn = getDBConn.getConn();
return conn;
}
protected PreparedStatement getPstmt() {
return pstmt;
}
/**
* 传入javaBean以更新数据库
*
* @param o
* @return
*/
public boolean update(Object o) {
release();
getConn();
Map<String, Method> methods = MyTool.getMethods(CLAZZ);
Object[] args = new Object[tableinfo.updateArray().length + 1];
try {
for (int i = 0; i < args.length - 1; i++) {
args[i] = methods.get(tableinfo.updateArray()[i]).invoke(o);
}
args[args.length - 1] = methods.get(tableinfo.pkName()).invoke(o);
pstmt = conn.prepareStatement(UPDATE);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return 1 == TableTool.execUpdate(pstmt, args);
}
/**
* 传入javaBean以完成数据库插入
*
* @param o
* @return
*/
public boolean insert(Object o) {
release();
getConn();
Map<String, Method> methods = MyTool.getMethods(CLAZZ);
Object[] args = new Object[tableinfo.updateArray().length];
try {
for (int i = 0; i < args.length; i++) {
args[i] = methods.get(tableinfo.updateArray()[i]).invoke(o);
}
pstmt = conn.prepareStatement(INSERT);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return 1 == TableTool.execUpdate(pstmt, args);
}
/**
* 只对mysql数据库中主键自增的表有效
* @param o
* @return
*/
public Object insertAndRetrunNew(Object o){
release();
getConn();
Map<String, Method> methods = MyTool.getMethods(CLAZZ);
Object[] args = new Object[tableinfo.updateArray().length];
try {
for (int i = 0; i < args.length; i++) {
args[i] = methods.get(tableinfo.updateArray()[i]).invoke(o);
}
pstmt = conn.prepareStatement(INSERT,PreparedStatement.RETURN_GENERATED_KEYS);
int pk = TableTool.execUpdate(pstmt, args);
Map<String, Method> setMethods = MyTool.setMethods(CLAZZ);
setMethods.get(tableinfo.pkName()).invoke(o, pk);
return selectById(o);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* 查询并返回一个列表
* @param where
* @param args
* @return
*/
public List selectListByWhere(String where, Object... args) {
release();
getConn();
try {
pstmt = conn.prepareStatement(SLELECT_ALL + where);
rs = TableTool.execQuery(pstmt, args);
} catch (SQLException e) {
e.printStackTrace();
}
return MyTool.handlerList(rs, CLAZZ);
}
/**
* 输入一个javaBean,根据其主键删除
* @param o
* @return
*/
public boolean delateByPk(Object o) {
release();getConn();
Map<String, Method> methods = MyTool.getMethods(CLAZZ);
try {
pstmt = conn
.prepareStatement("DELETE FROM " + tableinfo.tableName() + " WHERE " + tableinfo.pkName() + " = ?");
Object pk = methods.get(tableinfo.pkName()).invoke(o);
return 1 == TableTool.execUpdate(pstmt, pk);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 输入一个javaBean根据其主键查询
* @param o
* @return
*/
public Object selectById(Object o){
release();getConn();
Map<String, Method> methods = MyTool.getMethods(CLAZZ);
Object pk="";
try {
pk = methods.get(tableinfo.pkName()).invoke(o);
} catch (Exception e) {
e.printStackTrace();
}
return selectByWhere(" WHERE " + tableinfo.pkName() + " = ?",pk);
}
/**
* 传入where字句删除数据
* @param where
* @param args
* @return
*/
public boolean deleteByWhere(String where, Object... args) {
try {
pstmt = conn.prepareStatement("DELETE FROM " + tableinfo.tableName() + " " + where);
return 1 == TableTool.execUpdate(pstmt, args);
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
/**
* 传入where子句,根据where子句查询
* @param where
* @param args
* @return
*/
public Object selectByWhere(String where, Object... args) {
release();
getConn();
try {
pstmt = conn.prepareStatement(SLELECT_ALL + where);
rs = TableTool.execQuery(pstmt, args);
} catch (SQLException e) {
e.printStackTrace();
}
return MyTool.handler(rs, CLAZZ);
}
/**
* 释放数据库连接资源
*/
public void release() {
try {
if (rs != null) {
rs.close();
rs = null;
}
if (pstmt != null) {
pstmt.close();
pstmt = null;
}
if (stmt != null) {
stmt.close();
stmt = null;
}
if (conn != null) {
conn.close();
conn = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 给一个完整查询语句,返回结果集
* @param sql
* @param args
* @return
*/
public ResultSet execQuery(String sql, Object... args) {
release();
getConn();
try {
if (args.length == 0) {
stmt = conn.createStatement();
rs = TableTool.execQuery(stmt, sql);
} else {
pstmt = conn.prepareStatement(sql);
rs = TableTool.execQuery(pstmt, args);
}
} catch (SQLException e) {
e.printStackTrace();
}
return rs;
}
/**
* 给一个完整更新语句,返回结果集
* @param sql
* @param args
* @return
*/
public int execUpdate(String sql, Object... args) {
release();
getConn();
int a = 0;
try {
if (args.length == 0) {
stmt = conn.createStatement();
a = TableTool.execUpdate(stmt, sql);
} else {
pstmt = conn.prepareStatement(sql);
a = TableTool.execUpdate(pstmt, args);
}
} catch (SQLException e) {
e.printStackTrace();
}
return a;
}
/**
* 析构方法中释放资源
*/
protected void finalized() {
release();
}
}
其余代码
DBInfo.java
package com.iss.db.dao.dbinfo;
public interface DBInfo {
public String getDriverName();
public String getUrl();
public String getUser();
public String getPwd();
}
GetConfig .java
package com.iss.db.dao.dbinfo;
/**
* 获取配置信息
*/
public interface GetConfig {
public String getByKey(String key);
}
package com.iss.db.dao.dbinfo;
import java.util.HashMap;
import java.util.Map;
/**
* GetConfig、DBInfo的一个非配置文件实现
*/
public class DBConfig implements GetConfig,DBInfo {
private final Map<String,String> dbConfig = new HashMap<String,String>(){
{
put("driver","com.mysql.jdbc.Driver");
put("host","localhost");
put("port","3306");
put("dbName","sakila");
put("user","root");
put("pwd","root");
put("url","jdbc:mysql://"+get("host")+":"+get("port")+"/"+get("dbName")+"?useUnicode=true&characterEncoding=utf8");
}
};
@Override
public String getByKey(String key) {
return dbConfig.get(key);
}
public DBConfig setByKey(String key,String value){
if(dbConfig.containsKey(key)){
dbConfig.replace(key, value);
}else{
dbConfig.put(key, value);
}
return this;
}
@Override
public String getUrl() {
return getByKey("url");
}
@Override
public String getUser() {
return getByKey("user");
}
@Override
public String getPwd() {
return getByKey("pwd");
}
@Override
public String getDriverName() {
return getByKey("driver");
}
}
TableInfo .java
package com.iss.db.dao.tableinfo;
public interface TableInfo {
public String tableName();
public String pkName();
public String[] updateArray();
}
TableDic.java
package com.iss.db.dao.tableinfo;
public class TableDic implements TableInfo {
private String tableName ;
private String pkname = "id";
private String[] array;
@Override
public String pkName() {
return pkname;
}
@Override
public String[] updateArray() {
return array;
}
public TableDic(String pk,String tableName,String...update){
super();
this.pkname = pk.toLowerCase();
this.tableName = tableName;
for(int i=0;i<update.length;i++){
update[i] = update[i].toLowerCase();
}
this.array = update;
}
@Override
public String tableName() {
return tableName;
}
}
=_=|| 本来还想改进改进,但是学了MyBatis发现MyBatis框架所拥有的功能就是我想要实现的,我就不必发明轮子了。