天天看点

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