做网站顾客提现金额后台,另类投资公司网站建设规定,企业网站类型主要包括,建设网站招聘1. 前言
本节和大家一起聊聊 Hibernate 是如何自动生成 SQL 语句的。通过本节的学习#xff0c;你将了解到#xff1a;
反射在框架中的重要性#xff1b;元数据描述对 Hibernate 的重要性。 2. 理想状态
Hibernate 是全自动的 JDBC 框架#xff0c;能自动构建 SQL 语句、…1. 前言
本节和大家一起聊聊 Hibernate 是如何自动生成 SQL 语句的。通过本节的学习你将了解到
反射在框架中的重要性元数据描述对 Hibernate 的重要性。 2. 理想状态
Hibernate 是全自动的 JDBC 框架能自动构建 SQL 语句、能自动封装数据。
做为开发者不能在使用的便利性中迷失自己应该要学会多思考Hibernate 是如何自动构建 SQL 语句的
答案本身很简单使用反射机制。
先来一个最理想化的构建实例假设实体类名和表名相同、实体类中的属性和表中的字段命名相同。
编写自己的 Session 类
public class MySessionT {public T get(Class clz,Serializable id) { String sqlcreateSql(clz,id);//其它操作…… return null;}private String createSql(Class clz, Serializable id) { return null;}
}get()方法接受 2 个参数这 2 个参数便是构建 SQL 的核心。传递给内部的 createSql()方法用来进行 SQL 语句构造。
关注 createSql() 方法中的代码
1声明变量。 // SQL 查询模板String sql select {0} from {1} where {2} {3};// 表名String tableName null;// 字段列表StringBuffer selFields new StringBuffer();// 主键字段String keyField null;2看来就是要为 SQL 查询模板中的占位符找到具体值。因为类名和表名相同所以表名很容易找到。 // 类名就是表名tableName clz.getSimpleName();3因为属性名与表中的字段名相同所以表的字段信息也很容易找到。 // 属性名就是查询的字段名找到属性等于找到字段信息Field[] fields clz.getDeclaredFields();4这里有一个较麻烦的地方怎么找到主键字段这里假设第一个属性对应的是主键字段。 Field[] fields clz.getDeclaredFields();for (int i 0; i fields.length; i) {if (i 0)keyField fields[i].getName();selFields.append(fields[i].getName()).append(,);}// 删除最后一个,selFields.deleteCharAt(selFields.length() - 1);5最后构建 SQL 。 sql MessageFormat.format(sql, new Object[] {selFields,tableName,keyField,id});测试输出大家自己去完成。 3. 非理想状态
前面假设了一种特别理想的状态。但是现实总比理想残酷。
很多情况下表名与类名、属性名和字段名都不同名主键字段对应的属性也不一定放在第一个。
这种情形下又如何构建 SQL 。此时注解就起到了作用。大家还记得常用的注解吗
TableIdColumn。
有了这 3 个注解查找表名、字段信息、主键字段就不需要再靠强制性的代码规范了。
重构 createSql() 方法中的代码。
本质上没有发生改变还是为 SQL 查询模板中的占位符找到所有具体值。
1找到表名。其本思路是如果有 Table 注解表名就是注解提供的名字如果没有注解则表名与类名相同 // 查找类上面是否有 Table 注解Table tableAnnotaion (Table) clz.getAnnotation(Table.class);if(tableAnnotaionnull) //则认为类名与表名相同tableName clz.getSimpleName();else //表名为注解中提供的值tableNametableAnnotaion.name();2找到表的所有字段信息。为了简化代码假设 Id 或 Column 注解直接标注在属性上面。即使标注在 get方法上面也不难 // 属性信息Field[] fields clz.getDeclaredFields();//是否存在 Id 注解boolean ishasIdAnnotation false;Id idAnnotationnull;Column columnAnnotation null;String fieldName null;for (Field field : fields) {// Id 注解idAnnotation field.getAnnotation(Id.class);// Column 注解columnAnnotation field.getAnnotation(Column.class);if (idAnnotation ! null) {keyField field.getName();ishasIdAnnotation true;}if (columnAnnotation null)// 有 Column 注解则从注解中取值fieldName field.getName();else//没有 Column 注解则和属性表相同fieldName columnAnnotation.name();selFields.append(fieldName).append(,);}if (!ishasIdAnnotation) {throw new Exception(Id 注解是必须的);}// 删除最后一个,selFields.deleteCharAt(selFields.length() - 1);3构建 SQL 语句。 sql MessageFormat.format(sql, new Object[] { selFields, tableName, keyField, id });测试 createSql方法在控制台可看到通过反射自动构建的 SQL 语句
select stuId,stuName,stuSex,stuPassword from student where stuId 1测试结果需要以你自己的实体类和表做参考。 4. 小结
本节给出了 2 种情形下构建 SQL 语句的实现。
一种对编码规范要求非常严格因为编码规范有很多人为因素很难保证类结构和表结构如同镜像不出现差异性。显然在这种严格的编码规范下构建 SQL 的性能消耗是最低的所以一入职场第一堂课就是培训编码规范性。
第二种情形应该是一种常态所以需要使用注解的方式标识差异性当然反射时付出的性能代价会增加。
本节没有讨论构建多表查询的实现有了这些基础相信都将不会很难。