java 利用注解实现BaseDao 增删查改

时间:2023-03-09 21:55:22
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();
}

第二步:编写一个实体类,并注明好注解

 import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Date; import annotation.ColumnInfo;
import annotation.TableInfo; /*
*
*/
@TableInfo(TableName = "student", PrimaryKey = "id")
public class Student {
@ColumnInfo(columnName="id")
private int sid;
@ColumnInfo(columnName="sname")
private String sname;
@ColumnInfo(columnName="sclass")
private int sclass;
@ColumnInfo(columnName="startdate")
private Date startdate;
@ColumnInfo(columnName="stopdate")
private Date stopdate; public Date getStopdate() {
return stopdate;
}
public void setStopdate(Date stopdate) {
this.stopdate = stopdate;
}
public Date getStartdate() {
return startdate;
}
public void setStartdate(Date startdate) {
this.startdate = startdate;
} public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public int getSclass() {
return sclass;
}
public void setSclass(int sclass) {
this.sclass = sclass;
}
@Override
public String toString() {
return "Student [id=" + sid + ", sname=" + sname + ", sclass=" + sclass
+ ", startdate=" + startdate + ", stopdate=" + stopdate + "]\n";
}
}

第三部:编写BaseDao.java(对数据库的操作基于c3p0组件)

 import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List; import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanHandler; import annotation.ColumnInfo;
import annotation.TableInfo; import fnz.utils.JdbcUtil2; public class BaseDao<T> { private Class clazz; //类的字节码文件
private String tableName;//表明
private String primaryKey;//主键
private Field[] fields;//所有的字段
public BaseDao(){
Type type = this.getClass().getGenericSuperclass();//当前运行类的父类,即为“BaseDao<实体类>”,其实就是“参数化类型”ParameterizedType
ParameterizedType pt = (ParameterizedType)type;// 强制转换为“参数化类型” BaseDao<实体类>
Type types[] = pt.getActualTypeArguments(); // 获取“参数化类型”中的实体类
clazz = (Class)types[0];
//tableName = clazz.getSimpleName();//获取类名(不带包名)
TableInfo tab = (TableInfo)clazz.getAnnotation(TableInfo.class);
tableName = tab.TableName();
primaryKey = tab.PrimaryKey();
fields = clazz.getDeclaredFields();
} /**
* 主键查询
* @param id 主键值
* @return 返回封装后的对象
* @throws SQLException
*/
public T getOne(Object id){
try {
return JdbcUtil2.getQueryRunner().query("select * from "+tableName+" where "+ primaryKey+" = ?", new MBeanHandler<T>(clazz,mMethod.SELECT),id);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
} /**
* 查询全部
* @return 返回所有记录,封装成List<T>
* @throws SQLException
*/
public List<T> getAll(){
try {
return JdbcUtil2.getQueryRunner().query("select * from "+tableName, new MBeanListHandler<T>(clazz));
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 保存
* @param t 要保存的实体对象
* @return 保存后的对象
*/
public T baseSave(T t){
try{
List<Object> params = new ArrayList<Object>();
for (int i = 0; i < fields.length; i++) {
fields[i].setAccessible(true);//强制是有字段也可以访问
params.add(fields[i].get(t));
}
//sql拼接
StringBuilder sql = new StringBuilder();
sql.append("insert into "+tableName+"(");
for (int j = 0; j < fields.length; j++) {
String fieldName = fields[j].getAnnotation(ColumnInfo.class).columnName();//获取表字段名
if(j == fields.length-1){
sql.append(fieldName+")");
}else{
sql.append(fieldName+",");
}
}
sql.append(" values(");
for (int k = 0; k < fields.length; k++) {
if(k == fields.length-1){
sql.append("?)");
}else{
sql.append("?,");
}
} JdbcUtil2.getQueryRunner().insert(sql.toString()
,new MBeanHandler<T>(clazz,mMethod.INSERT)
,params.toArray());
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return t;
} /**
* 执行更新
* @param t 更新对象
* @return
*/
public T baseUpdate(T t){
try{
List<Object> params = new ArrayList<Object>();
Object idParam = null;
for (int i = 0; i < fields.length; i++) {
fields[i].setAccessible(true);//强制是有字段也可以访问
if(!primaryKey.equals(fields[i].getAnnotation(ColumnInfo.class).columnName())){
params.add(fields[i].get(t));
}else{
idParam = fields[i].get(t);
}
}
params.add(idParam);//id为最后一个参数
//sql拼接
StringBuilder sql = new StringBuilder();
sql.append("update "+tableName+" set");
String strWhere = "";
for (int j = 0; j < fields.length; j++) {
String fieldName = fields[j].getAnnotation(ColumnInfo.class).columnName();//获取表字段名
if(!fieldName.equals(primaryKey)){
sql.append(" "+fieldName+"=?,");
}else if(fieldName.equals(primaryKey)){
strWhere = " where "+primaryKey+"=?";
}
}
int idx = sql.lastIndexOf(",");
sql = sql.replace(idx, idx+1, "");
sql.append(strWhere); JdbcUtil2.getQueryRunner().update(sql.toString(),params.toArray());
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return t;
} /**
* 根据主键删除
* @param id 主键id
* @return
*/
public Boolean baseDelete(Object id){
try{
JdbcUtil2.getQueryRunner().update("delete from "+tableName+" where "+primaryKey+"=?",id);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return true;
} } enum mMethod{
SELECT,
INSERT,
UPDATE
}
/**
* 自定义结果集:封装单个Bean对象
* @author fnz
*
* @param <T>
*/
class MBeanHandler<T> implements ResultSetHandler<T>{
private mMethod method;
private Class<T> clazz;
public MBeanHandler(Class<T> clazz,mMethod method){
this.clazz = clazz;
this.method = method;
} public T handle(ResultSet rs) throws SQLException {
try {
if(this.method == mMethod.SELECT){
if(rs.next()){
T tobj = clazz.newInstance();
Field[] fields = clazz.getDeclaredFields();//获取到所有的
for (Field field : fields) {
ColumnInfo col = field.getAnnotation(ColumnInfo.class);//获取实体类字段上的注解ColumnInfo
String colName = col.columnName();//得到 实体类字段 对应 表的字段名
//获取表字段的值
rs.findColumn(colName);
Object value = rs.getObject(colName);
//封装对象
field.setAccessible(true);
field.set(tobj, value);
}
return tobj;
}
}else{
return null;
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return null;
}
}
/**
* 自定义结果集:封装多个Bean对象
* @author fnz
*
* @param <T>
*/
class MBeanListHandler<T> implements ResultSetHandler<List<T>>{
// 保存传入的要封装的类的字节码
private Class<T> clazz;
public MBeanListHandler(Class<T> clazz) {
this.clazz = clazz;
}
// 封装结果集的方法
public List<T> handle(ResultSet rs) throws SQLException {
try {
List<T> list = new ArrayList<T>();
// 向下读一行
while(rs.next()){
T tobj = clazz.newInstance();
Field[] fields = clazz.getDeclaredFields();//获取到所有的
for (Field field : fields) {
ColumnInfo col = field.getAnnotation(ColumnInfo.class);//获取实体类字段上的注解ColumnInfo
String colName = col.columnName();//得到 实体类字段 对应 表的字段名
//获取表字段的值
Object value = rs.getObject(colName);
//封装对象
field.setAccessible(true);
field.set(tobj, value);
}
list.add(tobj);
}
return list;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

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用到的工具类)

 import java.sql.Connection;
import org.apache.commons.dbutils.QueryRunner; import com.mchange.v2.c3p0.ComboPooledDataSource; public class JdbcUtil2 {
private static ComboPooledDataSource dataSource = null;
static{
//初始化操作
// 自动加载src目录下c3p0的配置文件【c3p0-config.xml】
dataSource = new ComboPooledDataSource();// 使用默认的配置
//使用c3p0-config.xml配置文件中named-config的name属性为C3P0TestName的配置
//dataSource = new ComboPooledDataSource("C3P0TestName");
} //获取QueryRunner对象
public static QueryRunner getQueryRunner(){
return new QueryRunner(dataSource);
}
//获取连接 通过c3p0核心类对象获取(此例子没用到该方法)
public static Connection getConnection(){
try {
return dataSource.getConnection();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}

最后:简单编写一下测试类

StudentDao继承BaseDao

   @Test
public void test6(){
StudentDao dao = new StudentDao();
Student s = dao.getOne(1);
System.out.println(s);
}

输出结果:Student [id=1, sname=张三, sclass=1, startdate=2016-09-22 00:00:00.0, stopdate=2016-09-23]

over