学习反射、注解、this实现简单版JPA笔记

写在前面

核心代码是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);

    }

}

写在后面

增删改查代码民工,想进阶还是得研究研究框架的原理,光看视频还是不够,自己多敲更重要

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值