java 利用注解实现BaseDao 增删查改
Posted 酒香逢
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 利用注解实现BaseDao 增删查改相关的知识,希望对你有一定的参考价值。
第一步,编写两个注解类,用于表明实体类对应的表名及字段。
TableInfo.java 此注解用于标注表名及主键名
import static java.lang.annotation.ElementType.TYPE; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /* * TableName对应表名称 * PrimaryKey对应主键字段名 */ @Target({TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface TableInfo { public String TableName(); public String PrimaryKey(); }
ColumnInfo.java 此注解用于标注实体类字段对应表字段
import static java.lang.annotation.ElementType.FIELD; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /* * 用于标识表字段名 */ @Target({FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface ColumnInfo { String columnName(); }
第二步:编写一个实体类,并注明好注解
1 import static java.lang.annotation.ElementType.CONSTRUCTOR; 2 import static java.lang.annotation.ElementType.FIELD; 3 import static java.lang.annotation.ElementType.LOCAL_VARIABLE; 4 import static java.lang.annotation.ElementType.METHOD; 5 import static java.lang.annotation.ElementType.PARAMETER; 6 import static java.lang.annotation.ElementType.TYPE; 7 8 import java.lang.annotation.Retention; 9 import java.lang.annotation.RetentionPolicy; 10 import java.lang.annotation.Target; 11 import java.util.Date; 12 13 import annotation.ColumnInfo; 14 import annotation.TableInfo; 15 16 17 /* 18 * 19 */ 20 @TableInfo(TableName = "student", PrimaryKey = "id") 21 public class Student { 22 @ColumnInfo(columnName="id") 23 private int sid; 24 @ColumnInfo(columnName="sname") 25 private String sname; 26 @ColumnInfo(columnName="sclass") 27 private int sclass; 28 @ColumnInfo(columnName="startdate") 29 private Date startdate; 30 @ColumnInfo(columnName="stopdate") 31 private Date stopdate; 32 33 public Date getStopdate() { 34 return stopdate; 35 } 36 public void setStopdate(Date stopdate) { 37 this.stopdate = stopdate; 38 } 39 public Date getStartdate() { 40 return startdate; 41 } 42 public void setStartdate(Date startdate) { 43 this.startdate = startdate; 44 } 45 46 public int getSid() { 47 return sid; 48 } 49 public void setSid(int sid) { 50 this.sid = sid; 51 } 52 public String getSname() { 53 return sname; 54 } 55 public void setSname(String sname) { 56 this.sname = sname; 57 } 58 public int getSclass() { 59 return sclass; 60 } 61 public void setSclass(int sclass) { 62 this.sclass = sclass; 63 } 64 @Override 65 public String toString() { 66 return "Student [id=" + sid + ", sname=" + sname + ", sclass=" + sclass 67 + ", startdate=" + startdate + ", stopdate=" + stopdate + "]\n"; 68 } 69 }
第三部:编写BaseDao.java(对数据库的操作基于c3p0组件)
1 import java.lang.reflect.Field; 2 import java.lang.reflect.ParameterizedType; 3 import java.lang.reflect.Type; 4 import java.sql.ResultSet; 5 import java.sql.SQLException; 6 import java.util.ArrayList; 7 import java.util.List; 8 9 import org.apache.commons.dbutils.ResultSetHandler; 10 import org.apache.commons.dbutils.handlers.BeanHandler; 11 12 import annotation.ColumnInfo; 13 import annotation.TableInfo; 14 15 import fnz.utils.JdbcUtil2; 16 17 public class BaseDao<T> { 18 19 private Class clazz; //类的字节码文件 20 private String tableName;//表明 21 private String primaryKey;//主键 22 private Field[] fields;//所有的字段 23 public BaseDao(){ 24 Type type = this.getClass().getGenericSuperclass();//当前运行类的父类,即为“BaseDao<实体类>”,其实就是“参数化类型”ParameterizedType 25 ParameterizedType pt = (ParameterizedType)type;// 强制转换为“参数化类型” BaseDao<实体类> 26 Type types[] = pt.getActualTypeArguments(); // 获取“参数化类型”中的实体类 27 clazz = (Class)types[0]; 28 //tableName = clazz.getSimpleName();//获取类名(不带包名) 29 TableInfo tab = (TableInfo)clazz.getAnnotation(TableInfo.class); 30 tableName = tab.TableName(); 31 primaryKey = tab.PrimaryKey(); 32 fields = clazz.getDeclaredFields(); 33 } 34 35 36 /** 37 * 主键查询 38 * @param id 主键值 39 * @return 返回封装后的对象 40 * @throws SQLException 41 */ 42 public T getOne(Object id){ 43 try { 44 return JdbcUtil2.getQueryRunner().query("select * from "+tableName+" where "+ primaryKey+" = ?", new MBeanHandler<T>(clazz,mMethod.SELECT),id); 45 } catch (SQLException e) { 46 e.printStackTrace(); 47 throw new RuntimeException(e); 48 } 49 } 50 51 /** 52 * 查询全部 53 * @return 返回所有记录,封装成List<T> 54 * @throws SQLException 55 */ 56 public List<T> getAll(){ 57 try { 58 return JdbcUtil2.getQueryRunner().query("select * from "+tableName, new MBeanListHandler<T>(clazz)); 59 } catch (SQLException e) { 60 e.printStackTrace(); 61 throw new RuntimeException(e); 62 } 63 } 64 /** 65 * 保存 66 * @param t 要保存的实体对象 67 * @return 保存后的对象 68 */ 69 public T baseSave(T t){ 70 try{ 71 List<Object> params = new ArrayList<Object>(); 72 for (int i = 0; i < fields.length; i++) { 73 fields[i].setAccessible(true);//强制是有字段也可以访问 74 params.add(fields[i].get(t)); 75 } 76 //sql拼接 77 StringBuilder sql = new StringBuilder(); 78 sql.append("insert into "+tableName+"("); 79 for (int j = 0; j < fields.length; j++) { 80 String fieldName = fields[j].getAnnotation(ColumnInfo.class).columnName();//获取表字段名 81 if(j == fields.length-1){ 82 sql.append(fieldName+")"); 83 }else{ 84 sql.append(fieldName+","); 85 } 86 } 87 sql.append(" values("); 88 for (int k = 0; k < fields.length; k++) { 89 if(k == fields.length-1){ 90 sql.append("?)"); 91 }else{ 92 sql.append("?,"); 93 } 94 } 95 96 JdbcUtil2.getQueryRunner().insert(sql.toString() 97 ,new MBeanHandler<T>(clazz,mMethod.INSERT) 98 ,params.toArray()); 99 } catch (Exception e) { 100 e.printStackTrace(); 101 throw new RuntimeException(e); 102 } 103 return t; 104 } 105 106 /** 107 * 执行更新 108 * @param t 更新对象 109 * @return 110 */ 111 public T baseUpdate(T t){ 112 try{ 113 List<Object> params = new ArrayList<Object>(); 114 Object idParam = null; 115 for (int i = 0; i < fields.length; i++) { 116 fields[i].setAccessible(true);//强制是有字段也可以访问 117 if(!primaryKey.equals(fields[i].getAnnotation(ColumnInfo.class).columnName())){ 118 params.add(fields[i].get(t)); 119 }else{ 120 idParam = fields[i].get(t); 121 } 122 } 123 params.add(idParam);//id为最后一个参数 124 //sql拼接 125 StringBuilder sql = new StringBuilder(); 126 sql.append("update "+tableName+" set"); 127 String strWhere = ""; 128 for (int j = 0; j < fields.length; j++) { 129 String fieldName = fields[j].getAnnotation(ColumnInfo.class).columnName();//获取表字段名 130 if(!fieldName.equals(primaryKey)){ 131 sql.append(" "+fieldName+"=?,"); 132 }else if(fieldName.equals(primaryKey)){ 133 strWhere = " where "+primaryKey+"=?"; 134 } 135 } 136 int idx = sql.lastIndexOf(","); 137 sql = sql.replace(idx, idx+1, ""); 138 sql.append(strWhere); 139 140 JdbcUtil2.getQueryRunner().update(sql.toString(),params.toArray()); 141 } catch (Exception e) { 142 e.printStackTrace(); 143 throw new RuntimeException(e); 144 } 145 return t; 146 } 147 148 /** 149 * 根据主键删除 150 * @param id 主键id 151 * @return 152 */ 153 public Boolean baseDelete(Object id){ 154 try{ 155 JdbcUtil2.getQueryRunner().update("delete from "+tableName+" where "+primaryKey+"=?",id); 156 } catch (Exception e) { 157 e.printStackTrace(); 158 throw new RuntimeException(e); 159 } 160 return true; 161 } 162 163 } 164 165 enum mMethod{ 166 SELECT, 167 INSERT, 168 UPDATE 169 } 170 /** 171 * 自定义结果集:封装单个Bean对象 172 * @author fnz 173 * 174 * @param <T> 175 */ 176 class MBeanHandler<T> implements ResultSetHandler<T>{ 177 private mMethod method; 178 private Class<T> clazz; 179 public MBeanHandler(Class<T> clazz,mMethod method){ 180 this.clazz = clazz; 181 this.method = method; 182 } 183 184 public T handle(ResultSet rs) throws SQLException { 185 try { 186 if(this.method == mMethod.SELECT){ 187 if(rs.next()){ 188 T tobj = clazz.newInstance(); 189 Field[] fields = clazz.getDeclaredFields();//获取到所有的 190 for (Field field : fields) { 191 ColumnInfo col = field.getAnnotation(ColumnInfo.class);//获取实体类字段上的注解ColumnInfo 192 String colName = col.columnName();//得到 实体类字段 对应 表的字段名 193 //获取表字段的值 194 rs.findColumn(colName); 195 Object value = rs.getObject(colName); 196 //封装对象 197 field.setAccessible(true); 198 field.set(tobj, value); 199 } 200 return tobj; 201 } 202 }else{ 203 return null; 204 } 205 } catch (Exception e) { 206 e.printStackTrace(); 207 throw new RuntimeException(e); 208 } 209 return null; 210 } 211 } 212 /** 213 * 自定义结果集:封装多个Bean对象 214 * @author fnz 215 * 216 * @param <T> 217 */ 218 class MBeanListHandler<T> implements ResultSetHandler<List<T>>{ 219 // 保存传入的要封装的类的字节码 220 private Class<T> clazz; 221 public MBeanListHandler(Class<T> clazz) { 222 this.clazz = clazz; 223 } 224 // 封装结果集的方法 225 public List<T> handle(ResultSet rs) throws SQLException { 226 try { 227 List<T> list = new ArrayList<T>(); 228 // 向下读一行 229 while(rs.next()){ 230 T tobj = clazz.newInstance(); 231 Field[] fields = clazz.getDeclaredFields();//获取到所有的 232 for (Field field : fields) { 233 ColumnInfo col = field.getAnnotation(ColumnInfo.class);//获取实体类字段上的注解ColumnInfo 234 String colName = col.columnName();//得到 实体类字段 对应 表的字段名 235 //获取表字段的值 236 Object value = rs.getObject(colName); 237 //封装对象 238 field.setAccessible(true); 239 field.set(tobj, value); 240 } 241 list.add(tobj); 242 } 243 return list; 244 } catch (Exception e) { 245 throw new RuntimeException(e); 246 } 247 } 248 }
C3P0配置文件
<c3p0-config> <!-- 默认加载配置 --> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/test01</property> <property name="user">root</property> <property name="password">123456</property> <property name="initialPoolSize">5</property> <property name="maxPoolSize">10</property> </default-config> <!-- 指定名称加载配置 --> <named-config name="C3P0TestName"> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/test01</property> <property name="user">root</property> <property name="password">123456</property> <property name="initialPoolSize">5</property> <property name="maxPoolSize">10</property> </named-config> </c3p0-config>
JdbcUtil2.java(上面的BaseDao.java用到的工具类)
1 import java.sql.Connection; 2 import org.apache.commons.dbutils.QueryRunner; 3 4 import com.mchange.v2.c3p0.ComboPooledDataSource; 5 6 7 public class JdbcUtil2 { 8 private static ComboPooledDataSource dataSource = null; 9 static{ 10 //初始化操作 11 // 自动加载src目录下c3p0的配置文件【c3p0-config.xml】 12 dataSource = new ComboPooledDataSource();// 使用默认的配置 13 //使用c3p0-config.xml配置文件中named-config的name属性为C3P0TestName的配置 14 //dataSource = new ComboPooledDataSource("C3P0TestName"); 15 } 16 17 //获取QueryRunner对象 18 public static QueryRunner getQueryRunner(){ 19 return new QueryRunner(dataSource); 20 } 21 //获取连接 通过c3p0核心类对象获取(此例子没用到该方法) 22 public static Connection getConnection(){ 23 try { 24 return dataSource.getConnection(); 25 } catch (Exception e) { 26 e.printStackTrace(); 27 throw new RuntimeException(e); 28 } 29 } 30 }
最后:简单编写一下测试类
StudentDao继承BaseDao
1 @Test 2 public void test6(){ 3 StudentDao dao = new StudentDao(); 4 Student s = dao.getOne(1); 5 System.out.println(s); 6 }
输出结果:Student [id=1, sname=张三, sclass=1, startdate=2016-09-22 00:00:00.0, stopdate=2016-09-23]
over
以上是关于java 利用注解实现BaseDao 增删查改的主要内容,如果未能解决你的问题,请参考以下文章
java--easyUI+struts+JSP实现简单的增删查改(增)
2016/3/13 MySQL 增删查改 CRUD 用代码实现