写在前面
核心代码是BaseDao,放在文章最后,简单实现了add和update方法,能力有限还有很多待优化的地方
知识点:
1、this和双亲委派机制
BaseDao是通过反射获取子类的class
利用子类class获取父类泛型以及参数的类型
2、反射
通过反射获取参数的类型结合传参的实体类(user)拼接sql利用jdbcTemplate操作数据库
3、注解
自定义table注解,在实体类配置注解(t_user)
实体类可以和数据库表不同名了
BaseDao通过反射获取注解表名,拼接在sql里面
maven配置
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
</dependency>
自定义注解
@Retention(RetentionPolicy.RUNTIME)//元注解保证运行时保留
@Target(ElementType.TYPE)
public @interface Table {
String value();
}
实体类
@Data
@Table("t_user")
public class User {
private int id;
private String name;
private Integer age;
public User(int id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
}
Dao层
public class UserDao extends BaseDao<User> {//java传参都会有隐藏参数this,双亲委派会把子类自身(this)传给父类
@Override
public void add(User bean) {
super.add(bean);
}
@Override
public void update(User bean) {
super.update(bean);
}
@Override
public void addOrUpdate(User bean) {
super.addOrUpdate(bean);
}
}
测试类
public class UserDaoTest {
public static void main(String[] args) {
UserDao userDao = new UserDao();
User user = new User(26,"88abbb", 88);
//userDao.add(user);
//userDao.update(user);
userDao.addOrUpdate(user);
}
}
核心代码BaseDao
package com.answer.szjpa;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
public class BaseDao<T> {
private static BasicDataSource datasource;
// 静态代码块,设置连接数据库的参数
static {
datasource = new BasicDataSource();
datasource.setDriverClassName("com.mysql.jdbc.Driver");
datasource.setUrl("jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8");
datasource.setUsername("root");
datasource.setPassword("abcd");
}
// 得到jdbcTemplate
private JdbcTemplate jdbcTemplate = new JdbcTemplate(datasource);
// DAO操作的对象
private Class<T> beanClass;
/**
* 构造器
* 初始化时完成对实际类型参数的获取,比如BaseDao<User>插入User,那么beanClass就是user.class
*/
public BaseDao() {
beanClass = (Class<T>) ((ParameterizedType) this.getClass()//this就是子类自身,获取父类泛型以及参数泛型,这里是user的结构
.getGenericSuperclass())
.getActualTypeArguments()[0];//父类的参数类型user的结构
}
public void addOrUpdate(T bean){
Field[] declaredFields = beanClass.getDeclaredFields();
declaredFields[0].setAccessible(true);
try {
if ((int)declaredFields[0].get(bean) != 0){//user字段传入user(bean)对象获取字段的值
update(bean);
}else {
add(bean);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public void add(T bean) {
// 得到User对象的所有字段
Field[] declaredFields = beanClass.getDeclaredFields();
// 拼接sql语句,表名直接用POJO的类名,所以创建表时,请注意写成User,而不是t_user
StringBuilder addsql = new StringBuilder().append("insert into ")
// .append(beanClass.getSimpleName())
.append(beanClass.getAnnotation(Table.class).value())
.append(" values(");
for (int i = 0; i < declaredFields.length; i++) {
addsql.append("?");
if (i < declaredFields.length - 1) {
addsql.append(",");
}
}
addsql.append(")");
// 获得bean字段的值(要插入的记录)
ArrayList<Object> paramList = new ArrayList<>();
try {
for (Field declaredField : declaredFields) {
declaredField.setAccessible(true);
Object o = declaredField.get(bean);
paramList.add(o);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
int size = paramList.size();
Object[] params = paramList.toArray(new Object[size]);
// 传入sql语句模板和模板所需的参数,插入User
int num = jdbcTemplate.update(addsql.toString(), params);
System.out.println(num);
}
public void update(T bean) {
// 得到User对象的所有字段
Field[] declaredFields = beanClass.getDeclaredFields();
// 拼接sql语句,表名直接用POJO的类名,所以创建表时,请注意写成User,而不是t_user
StringBuilder updatesql = new StringBuilder().append("update ")
.append(beanClass.getAnnotation(Table.class).value())
.append(" set ");
for (int i = 0; i < declaredFields.length; i++) {
declaredFields[i].setAccessible(true);
if (!"id".equals(declaredFields[i].getName())){
updatesql.append(declaredFields[i].getName()).append(" = ?");
if (i < declaredFields.length - 1) {
updatesql.append(",");
}
}
}
updatesql.append(" where id =?");
// 获得bean字段的值(要插入的记录)
ArrayList<Object> paramList = new ArrayList<>();
try {
for (int i = 0; i < declaredFields.length; i++) {
declaredFields[i].setAccessible(true);
Object o = declaredFields[i].get(bean);
if (!"id".equals(declaredFields[i].getName())){
paramList.add(o);
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
try {
paramList.add(declaredFields[0].get(bean));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
int size = paramList.size();
Object[] params = paramList.toArray(new Object[size]);
// 传入sql语句模板和模板所需的参数,插入User
int num = jdbcTemplate.update(updatesql.toString(), params);
System.out.println(updatesql.toString());
System.out.println(num);
}
}
写在后面
增删改查代码民工,想进阶还是得研究研究框架的原理,光看视频还是不够,自己多敲更重要