首页 > 其他分享 >Hibernate 自动进行数据封装

Hibernate 自动进行数据封装

时间:2023-02-04 11:31:51浏览次数:43  
标签:Hibernate 封装 rs entity field 自动 clz null 属性


1. 前言

Hibernate 可以构建各种复杂的 SQL 语句,但其本质都是反射机制结合映射关系完成的。

框架也仅是一款程序产品,人为编写的产物。要相信,只要你愿意,你完全可以实现自己的 JDBC 框架。

本节课和大家继续聊聊 Hibernate 是如何自动封装数据的。

2. 理想状态

程序中的数据通过 SQL 语句传递给数据库,从 IO 流的角度上理解是数据的输出。

把数据库中的数据封装成程序能识别、使用的类型,这个过程叫数据库封装。从 IO 流的角度上讲是数据的输入。

数据封装的实现还是利用反射机制。

数据封装的思路也简单。

表结构对应类结构,一行记录或说一个实体对应一个对象,字段对应属性。还是同样的配方。

即将编写实例之前,先做一个理想化的假设:

  • 表名和类名相同;
  • 表中的字段名和类中的属性名相同;
  • 实体类中没有特别复杂的数据类型。

理想状态设定便于大家由浅入深理解实现过程。

真实项目中,很难达到理想化状态 。因为 JAVA 程序和关系型数据库的命名规范有差异性,不管谁迁就谁,都会让彼此难受。

在上一节课的自定义 Session 对象中添加一个封装方法:

public class MySession<T> {
public T get(Class<T> clz, Serializable id) throws Exception {
String sql = createSql_(clz, id);
// JDBC 常规操作…… 得到结果集
ResultSet rs=this.getRs(sql);
//数据封装
T entity= this.wrap(clz, rs);
return entity;
}
/**
*构建 SQL ,具体代码参考本系列的《Hibernate 自动生成SQL语句》
*/
private String createSql(Class<T> clz, Serializable id) {
return null;
}
/**
*得到结果集,此方法就是常规的 JDBC 操作
*/
private ResultSet getRs(String sql) {
return null;
}
/**
*数据封装
*/
private T wrap(Class<T> clz,ResultSet rs) throws InstantiationException, IllegalAccessException {
return null;
}
}

关注 wrap()方法即可,直接让代码说话:

private T  wrap(Class<T> clz,ResultSet rs) throws InstantiationException, IllegalAccessException {
// 通过反射创建对象
T entity = clz.newInstance();
String attName = null;
Object value = null;
// 检查结果集中是否存在数据
if (rs.next()) {
// 属性信息
Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
// 表的字段名即类的属性名
attName = field.getName();
// 从结果集获取值
value = rs.getObject(attName);
//允许直接访问私有属性
field.setAccessible(true);
//数据封装
field.set(entity, value);
}
}
return entity;
}

上面代码没有进行类型转换相关操作,依靠 JAVA 自动类型转换完成,对于常用的基本类型,不会出多大问题。但对于较复杂的数据类型,需要编码进行强制类型转换。

下面这 2 行代码,通过打破私有属性的壁垒,直接给属性赋值。只适合用于验证、测试环境下。

field.setAccessible(true);
field.set(entity, value);

测试一下代码:

Student stu = new MySession<Student>().get(Student.class, new Integer(1));
System.out.println(stu);

在一切理想的状态下,一个简易的 JDBC 框架就开始工作了。

虽然它很薄弱,且不堪重负,但是,它是黑暗中的一道光,能指导你认识框架本质。

3. 非理想状态

再来一个非理想状态下的实现:

  • 类名与表名不同名;
  • 类中的属性名与表中的字段名有不同的命名;

整体思想和上面代码没有区别,通过属性名找到字段名,因为属性名和字段名不相同,所以需要通过属性上面的注解信息得到字段名。

让代码自己说话:

private T wrap_(Class<T> clz, ResultSet rs) throws InstantiationException, IllegalAccessException, SQLException,NoSuchMethodException, SecurityException, IllegalArgumentException,InvocationTargetException {
// 使用反射创建对象
T entity = clz.newInstance();
// 属性名
String attName = null;
// 列名
String columnName = null;
Object value = null;
Column columnAnnotaiton = null;
// 检查结果集中是否存在数据
if (rs.next()) {
// 属性信息
Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
// 属性名
attName = field.getName();
// 查看属性上面的注解
columnAnnotaiton = field.getAnnotation(Column.class);
if (columnAnnotaiton != null) {
columnName = columnAnnotaiton.name();
} else {
columnName = attName;
}
// 从结果集中获取值
value = rs.getObject(columnName);
// 属性的 set 方法名
String setMethodName = "set" + attName.substring(0, 1).toUpperCase() + attName.substring(1);
// 属性的 set 方法
Method setMethod = clz.getDeclaredMethod(setMethodName, new Class[] { field.getType() });
setMethod.invoke(entity, new Object[] { value });
}
}
return entity;
}

上面代码一样没有考虑复杂类型存在情况。

4. 小结

本节课程和大家聊了聊 Hibernate 是如何自动实现数据封装的,从实现原理上讲,还是比较容易理解的。

但是,真实环境的需求总是千变万化的,理想只存于理想中。

Hibernate 的实现和我们实现的最大区别在于,它总是能适应不同的需求,要适应不同的需求,无论是代码的设计还是编码都会有难度。

但是,千里之行,始于脚下,一步一步,终能看透所有的本质。

标签:Hibernate,封装,rs,entity,field,自动,clz,null,属性
From: https://blog.51cto.com/10zhancom/6037018

相关文章

  • app自动化遍历工具appcrawler
    monkey测试的缺点,测试太随机,功能比较深的页面可能点击不到自动遍历可以制定规则,指定页面,指定点击控件元素范围(Textview显示文字,EditText输入框,Button按钮,ImageView图片等),......
  • 18.获取天天基金基金的净值数,封装成方法
    1#爬虫2#该项目是爬取天天基金网某只基金的净值数据34#1.引入包5#网络请求6importjson78importrequests9#正则10importre11#数据......
  • 自动装配
    原来:   自动装配:autowire="byType" ......
  • win10专业版64位自动登录问题
    试一下直接使用注册表修改:1、在运行中执行regedit打开注册表;2、浏览到如下路径:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon3、在右......
  • C# adb封装类
    为了方便操作apk实现app的自动化点击封装了个adb操作了。基本上的操作都有了usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;usingSyst......
  • Promise 封装 $.ajax
    完整文档 html<inputtype="file"multipleid="filess"><buttononclick="jqueryAjax3()">上传文件ss</button><pid="filess_progress"style="width:0px;height......
  • 微信超级管家,自动好友回复、计数、自动同意、群发、好友导出、消息日志、无限多开
    微信超级管家,自动好友回复、计数、自动同意、群发、好友导出、消息日志、无限多开微信超级管家是一款大神针对微信制作的工具,它的主要功能包括了自动回复、好友计数、自动......
  • Jmeter+Maven接口自动化搭建
    1.Jmeter脚本录制/编写Jmeter脚本(不做描述)2.Maven项目配置1、创建一个Maven工程            2、在src/test目录下新建一个jmeter的目录,用来存......
  • 实车自动化测试解决方案
    ......
  • js深拷贝封装方法
    //使用递归的方式实现数组、对象的深拷贝functiondeepClone1(obj){//判断拷贝的要进行深拷贝的是数组还是对象,是数组的话进行数组拷贝,对象的话进行对象拷贝varob......