第一步,编写两个注解类,用于表明实体类对应的表名及字段。
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