1.技术栈:Java+mysql+反射+自定义注解+泛型+jdbc
2.持久层框架:是与数据库交互的一层称为持久层(dao),完成orm操作。
3.o:(Object对象)r:(relative关系)m:(mapping映射)
实体类==数据库表 属性==表的字段 实体类对象==一条记录 集合==表中多条记录
4.手撕持久层框架:自己编写持久层框架,可以完成无需写SQL语句即可完成对单表的CRUD操作。
5.目的:巩固上面得到知识点。
1.创建一个Maven的Java工程
idea--2024
2.引入依赖jar
<!--连接数据库依赖--> <dependency> <groupId>repMaven.mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> <!--德鲁伊依赖:监控和统计 :Druid提供了丰富的监控和统计功能 防SQL注入 :Druid内置了防SQL注入的功能,可以有效地防止潜在的安全风险。 高性能 :Druid经过精心优化,具有出色的性能。--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.8</version> </dependency> <!--lombok:可以使用注解--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> </dependency>
3.创建数据源的属性文件
#配置数据源信息 driverClassName=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai username=root password=root
4.创建DbUtil工具类
public class DbUtil { // 数据源对象 protected static DataSource dataSource; // 静态代码块--只会执行一次 static { try { // 创建一个属性对象 Properties properties=new Properties(); // 加载属性文件 InputStream resourceAsStream = DbUtil.class.getClassLoader().getResourceAsStream("db.properties"); properties.load(resourceAsStream); // 获取连接池对象 dataSource= DruidDataSourceFactory.createDataSource(properties); }catch (Exception e){ System.out.println("加载属性文件失败"); e.printStackTrace(); } } //获取连接对象 public static Connection getConnection() throws Exception{ Connection connection=dataSource.getConnection(); return connection; } // 释放资源 public static void closeAll(Connection connection,PreparedStatement preparedStatement,ResultSet resultSet){ if(resultSet!=null){ try { resultSet.close(); }catch (SQLException e){ throw new RuntimeException(e); } } if(preparedStatement!=null){ try { preparedStatement.close(); }catch (SQLException e){ throw new RuntimeException(e); } } if(connection!=null){ try { connection.close(); }catch (SQLException e){ throw new RuntimeException(e); } } } }
5.通用的添加功能
//T表示泛型标识type public class BaseDao<T> { // 通用添加功能 T:表示各个实体类对象 // 添加SQL:insert into 表名(列名。。。) values(值。。。) public int insert(T t) throws Exception { // 1.创建一个SQL字符串 StringBuffer sql = new StringBuffer("insert into "); // 2.获取实体类的反射类:对象名.getClass() Class<?> aClass = t.getClass(); // 3.获取表名 表名==实体类 String simpleName = aClass.getSimpleName();//实体类的名称 // 如果表名和实体类名称不一致就需要通过自定义注解获取数据库的真实表名 TableName annotation = aClass.getAnnotation(TableName.class); // 判断通过注解拿到的表名是否为空,如果不为空则放入simpleName中 if(annotation!=null){ simpleName=annotation.value(); } // 把表名拼在insert into后 sql.append(simpleName); // 4.获取所有列名 列名==属性名 // 创建一个集合存放列名:因为列名是多个,统一泛型string List<String> columnName=new ArrayList<String>(); // 创建一个集合存放列值:因为类值的类型有可能是int,string,boolean...类型,所以泛型是Object List<Object> values=new ArrayList<Object>(); // 5.获取所有的属性对象 Field[] declaredFields = aClass.getDeclaredFields(); for (Field f:declaredFields){ String name = f.getName();//获取所有的属性名 // 获取属性上的注解:如果列名和实体类中属性名称不一致就需要通过自定义注解获取数据库的真实列名 TableField annotation1 = f.getAnnotation(TableField.class); TableFieldId annotation2 = f.getAnnotation(TableFieldId.class); // 判断一下id上的注解是否存在,存在则跳过,因为id是自增的 if (annotation2!=null){ continue; } // 判断属性上的注解,如果不为空则放入 if (annotation1!=null){ name=annotation1.value(); } // 允许访问私有属性 f.setAccessible(true); // 把拿到列名放入列名集合中 columnName.add(name); // 获取列值 Object value = f.get(t); // 把拿到的列值放入集合中 values.add("'"+value+"'"); } // 把拿到的列名中括号替换成小括号 String replace = columnName.toString().replace("[", "(").replace("]", ")"); // 把拿到的列值中括号替换成小括号 String replace1 = values.toString().replace("[", "(").replace("]", ")"); // 把列名拼入到insert into 表名后 sql.append(replace+" values "+replace1); // 6.执行SQL语句 Connection conn = DbUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql.toString()); int i = ps.executeUpdate(); return i; }
6.自定义注解
7.通用的修改功能
//T表示泛型标识type public class BaseDao<T> { // 通用的修改功能 // 修改SQL:update 表名 set 列名=值... where 主键=值 public int update(T t) throws Exception { // 1.创建SQL语句 StringBuffer update = new StringBuffer("update "); // 2.获取表名 表名==实体类 Class<?> aClass = t.getClass(); String simpleName = aClass.getSimpleName();//表名 // 表名和实体类名不一致的情况需要通过注解获取数据库表名 TableName annotation = aClass.getAnnotation(TableName.class); // 判断表名是否为空 if (annotation!=null){ simpleName=annotation.value(); } // 拼接SQL update.append(simpleName+" set "); // 定义where String where=" where "; // 3.获取所有列名 Field[] declaredFields = aClass.getDeclaredFields(); for (Field f:declaredFields){ // 拿到所有属性名 String name = f.getName(); // 列名和属性名不一致的情况 TableField TableField = f.getAnnotation(TableField.class); TableFieldId TableFieldId = f.getAnnotation(TableFieldId.class); f.setAccessible(true); Object value = f.get(t); if (TableFieldId!=null){ String value1 = TableFieldId.value(); where+=value1+"='"+value+"'"; continue; } if (TableField!=null){ name=TableField.value(); } update.append(name+"='"+value+"',"); } // 把最后一个逗号删除 update.deleteCharAt(update.length()-1).addend(where); // 4.执行sql语句 Connection con=DbUtil.getConnection(); PreparedStatement pre=con.prepareStatement(update.toString()); int i = pre.executeUpdate(); return 1; } }
8.通用的删除功能
//T表示泛型标识type public class BaseDao<T> { // 通用删除功能 // 删除SQL:delete from 表名 where 主键=值 private Class<T> clazz; public BaseDao(){ // this表示子类Dao对象 Class<? extends BaseDao> aClass = this.getClass(); // 获取当前子类的父类的反射类 ParameterizedType genericSuperclass = (ParameterizedType) aClass.getGenericSuperclass(); System.out.println(genericSuperclass); // 获取该反射类中的泛型类型 Type actualTypeArgument = genericSuperclass.getActualTypeArguments()[0]; clazz= (Class) actualTypeArgument; } public int delete(Object id) throws Exception { // 1.创建SQL语句 StringBuffer deleteFrom = new StringBuffer("delete from "); // 2.获取表名 String simpleName = clazz.getSimpleName(); // 表名和实体类不一致的情况 TableName annotation = clazz.getAnnotation(TableName.class); if (annotation!=null){ simpleName=annotation.value(); } // 拼接到SQL中 deleteFrom.append(simpleName+" where "); // 3.获取所有属性值 Field[] declaredFields = clazz.getDeclaredFields(); for (Field f:declaredFields){ // 通过注解拿到id TableFieldId FieldId = f.getAnnotation(TableFieldId.class); if (FieldId!=null){ deleteFrom.append(FieldId.value()+"="+id); } break; } // 4.执行SQL语句 Connection con = DbUtil.getConnection(); PreparedStatement pre = con.prepareStatement(deleteFrom.toString()); int i = pre.executeUpdate(); return i; } }