26. Hibernate 如何自动生成 SQL 语句
1. 前言
本节和大家一起聊聊 Hibernate 是如何自动生成 SQL 语句的。通过本节的学习,你将了解到:
- 反射在框架中的重要性;
- 元数据描述对 Hibernate 的重要性。
2. 理想状态
Hibernate 是全自动的 JDBC 框架,能自动构建 SQL 语句、能自动封装数据。
做为开发者,不能在使用的便利性中迷失自己,应该要学会多思考:Hibernate 是如何自动构建 SQL 语句的?
答案本身很简单:使用反射机制。
先来一个最理想化的构建实例:假设实体类名和表名相同、实体类中的属性和表中的字段命名相同。
编写自己的 Session 类:
public class MySession<T> {public T get(Class clz,Serializable id) { String sql=createSql(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 。此时,注解就起到了作用。大家还记得常用的注解吗?
- @Table;
- @Id;
- @Column。
有了这 3 个注解,查找表名、字段信息、主键字段就不需要再靠强制性的代码规范了。
重构 createSql() 方法中的代码。
本质上没有发生改变,还是为 SQL 查询模板中的占位符找到所有具体值。
(1)找到表名。其本思路是,如果有 @Table 注解,表名就是注解提供的名字,如果没有注解,则表名与类名相同;
// 查找类上面是否有 @Table 注解Table tableAnnotaion= (Table) clz.getAnnotation(Table.class);if(tableAnnotaion==null) //则认为类名与表名相同tableName = clz.getSimpleName();else //表名为注解中提供的值tableName=tableAnnotaion.name();
(2)找到表的所有字段信息。为了简化代码,假设 @Id 或 @Column 注解直接标注在属性上面。即使标注在 get()方法上面也不难;
// 属性信息Field[] fields = clz.getDeclaredFields();//是否存在 @Id 注解boolean ishasIdAnnotation = false;Id idAnnotation=null;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 的性能消耗是最低的,所以,一入职场,第一堂课就是培训编码规范性。
第二种情形应该是一种常态,所以需要使用注解的方式标识差异性,当然,反射时付出的性能代价会增加。
本节没有讨论构建多表查询的实现,有了这些基础,相信都将不会很难。
相关文章:
26. Hibernate 如何自动生成 SQL 语句
1. 前言 本节和大家一起聊聊 Hibernate 是如何自动生成 SQL 语句的。通过本节的学习,你将了解到: 反射在框架中的重要性;元数据描述对 Hibernate 的重要性。 2. 理想状态 Hibernate 是全自动的 JDBC 框架,能自动构建 SQL 语句、…...
预言机(Oracle machine)
预言机(Oracle machine)是一个在多个领域中有不同应用和解释的概念。以下是从不同角度对预言机的详细解析: 一、计算复杂度理论与可计算性理论中的预言机 在计算复杂度理论与可计算性理论中,预言机是一种抽象电脑,用…...
55、PHP实现插入排序、二分查找
题目: PHP实现插入排序 描述: 思路:选择一个带插入的元素(假设从第一个开始),分别和已经插入有顺序的元素比较,如果要插入元素比比较元素小,则位置交换 function insertSort($arr){if(!is_array($arr)) return false;//外层循环插入次数for($i1;$i<…...
[Git][分支设计规范]详细讲解
目录 0.概览1.master分支2.release分支3.develop分支4.feature分支5.hotfix分支 0.概览 以下是常用的分支和环境的搭配,可视情况而定不同的策略 分支名称适用环境master主分支生产环境release预发布分支预发布/测试环境develop开发分支开发环境feature需求开发分支本…...
c#中winfrom需要了解的
如何用代码实现label1的字体大小 方法1:在设计视图中设置 打开你的Windows Forms项目。 在设计视图中,选中你想要更改字体大小的Label控件。 在属性窗口中,找到Font属性,点击旁边的省略号(...)。 在弹出的字体对话框中&#x…...
操作系统03:调度算法和文件系统
文章目录 调度算法进程调度算法先来先服务调度算法最短作业优先调度算法高响应比优先调度算法时间片轮转调度算法最高优先级调度算法 内存页面置换算法最佳页面置换算法(OPT)先进先出置换算法(FIFO)最近最久未使用的置换算法&…...
大量中国高清地图,必须收藏!!
1、中国人口密度 2、中国干湿区 3、中国温度带和干湿状况 4、中国气温分布 5、中国高陆状况 6、国家级高新技术产业开发区 7、中国工业布局的变化 8、中国旱灾 9、中国常年河与时令河 10、中国科斯塔地貌分布图 11、中国泥石流、滑坡崩塌灾害分布 12、中国森林和主要牧区分布图…...
无线领夹麦克风哪个品牌好,2024年收音麦哪个品牌好一点
在自媒体的浪潮中,内容创作者对于高质量音频的需求日益增长,这直接推动了无线领夹麦克风的兴起。过去,创作者们可能更倾向于使用传统的有线麦克风,但随着技术的进步和市场的变化,无线领夹麦克风以其便携性和灵活性的优…...
如何解决.NET8 类库Debug时,Debug文件夹中不包含Packages中引入的文件
最近在开发中使用了.NET8 Razor类库项目,但是惊讶的发现Debug时,Debug文件夹中不包含Packages中引入的文件,本以为是非常小的问题,但是被困住了竟然足足4个小时。 其实它也本就是个非常非常小的问题…… 只需引入<CopyLocalL…...
域名安全详解
域名安全是网络安全的重要组成部分,涉及多个方面。以下是域名安全的详细介绍: 1. 域名劫持防护 域名劫持是指攻击者通过各种手段,将用户访问的域名解析到非法IP地址上。 防护措施: 使用DNSSEC(域名系统安全扩展)定期监控域名解析记录选择可靠的域名注册商和DNS服务提供…...
使用gstreamer命令行解析RTSP流
1、解析成图片: gst-launch-1.0 rtspsrc locationrtsp://xxxx protocolstcp ! rtph264depay ! h264parse ! queue ! avdec_h264 ! videoconvert ! videorate ! videoscale ! videoconvert ! capsfilter capsvideo/x-raw,formatI420,width640,height480,framerate30…...
如何基于离线包中“事件热点”进行二次开发
720漫游支持基于作品离线包中的自定义按钮/热点-事件进行二次开发来实现与自己业务相关的扩展功能。 开发者可以基于离线包二次开发自定义设置点击热点图标需要执行什么操作?比如打开实时监控画面弹窗,调用自己后台的数据并弹窗显示等。 操作流程&…...
使用继电器实现门电路(1)常用门电路的简化实现
非门INC 常闭x1 反向输入信号 与门AND 常开x1 当A和B都为1时,O才为1,否则O为0。 或门OR 常开x1 当A和B中任意一个为1时,O为1,只有当A和B都为0时,O才为0。 或非门NOR 当A和B中任意一个为1时,O为0&…...
程序员常用单词分类
程序员在编程、软件开发、系统维护等工作中,会频繁使用到一系列特定的单词和术语。这些单词可以根据其功能、用途或所属领域进行分类。以下是一些常见的分类及其示例单词: 1. 数据类型与变量 数据类型:整型(Integer)…...
c语言11天笔记
函数的概述 函数:实现一定功能的,独立的代码模块。我们的函数一定是先定义,后使用。 使用函数的优势: 1. 我们可以通过函数提供功能给别人使用。当然我们也可以使用别人提供的函数,减少代码量。 2. 借助函数可以减…...
【C++刷题】优选算法——贪心第三辑
坏了的计算器 int brokenCalc(int startValue, int target) {int step 0;while (target > startValue) {if (target % 2 0) target / 2;else target 1;step;}return step startValue - target; }合并区间 区间问题,先排序 vector<vector<int>>…...
9.2 grafana 上导入模板看图并讲解告警
本节重点介绍 : 添加到prometheus采集配置中grafana 上导入process-exporter dashboard重点指标讲解 添加到prometheus采集配置中 - job_name: process-exporterhonor_timestamps: truescrape_interval: 15sscrape_timeout: 10smetrics_path: /metricsscheme: httpstatic_con…...
python实现自动回复消息
本文使用创作助手。 下面是一个使用uiautomation库实现自动回复QQ消息的示例代码: import time import uiautomation as autodef auto_reply():# 打开QQauto.uiautomationhelper.ShellExecute(r"C:\Program Files (x86)\Tencent\QQ\Bin\QQScLauncher.exe&quo…...
Mysql 脚本转换为drawio ER 脚本
Navicat 导出数据库脚本 通过代码转换脚本 import java.io.BufferedReader; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern;/*** SQL 脚本转换为 drawio ER 脚本*/ pu…...
基于babylonjs的小游戏 跳一跳
源码地址...
Excel文件压缩难?这4个方法让文件秒变小,传输再也不卡壳!
在数据驱动的办公场景中,Excel文件的"臃肿"问题越来越普遍。比如财务部门每月导出的销售报表,因包含近百张动态图表和历史数据,文件大小可能达到几十MB;市场调研团队收集的问卷数据,若未做图片压缩ÿ…...
生物学家转型AI科学家的核心能力迁移
在生命科学领域深耕多年的生物学家,正以惊人的速度涌入AI研究前沿。这种跨界迁移并非偶然,其背后隐藏着两类学科间深刻的思维共鸣与方法论互补——而软件测试从业者,恰恰能从这种转型中获得关键启示。一、复杂系统解析能力的无缝转化生物学家…...
2026届必备的降AI率网站解析与推荐
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 可从以下方面入手,来有效降低文本被AIGC检测出的概率:一点࿰…...
深度解析WeChatMsg:个人数据主权时代的技术革命与架构设计
深度解析WeChatMsg:个人数据主权时代的技术革命与架构设计 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/W…...
合宙ESP32-C3用PlatformIO调试,别再为USB CDC和DIO配置头疼了
合宙ESP32-C3 PlatformIO调试实战:USB CDC与DIO配置全解析 第一次接触合宙ESP32-C3的开发板时,我被它简洁的设计和亲民的价格所吸引。但当我兴冲冲地打开PlatformIO准备大展拳脚时,却接连遇到了串口无法识别、程序下载失败等一系列问题。经过…...
终极指南:Everything Claude Code JPA模式的AI驱动最佳实践 [特殊字符]
终极指南:Everything Claude Code JPA模式的AI驱动最佳实践 🚀 【免费下载链接】everything-claude-code The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, …...
Python 批量导出数据库数据至 Excel 文件页
简介 langchain专门用于构建LLM大语言模型,其中提供了大量的prompt模板,和组件,通过chain(链)的方式将流程连接起来,操作简单,开发便捷。 环境配置 安装langchain框架 pip install langchain langchain-community 其中…...
FireRedASR Pro功能体验:支持MP3/M4A/FLAC等全格式音频
FireRedASR Pro功能体验:支持MP3/M4A/FLAC等全格式音频 1. 音频识别新体验:告别格式转换烦恼 作为一名经常需要处理会议录音的技术博主,我深知音频格式兼容性带来的痛苦。上周我收到了三份不同格式的采访录音:市场部发来的MP3、…...
别再踩坑了!SQL Server数据类型那点事儿,看懂这篇少背三个锅蹬
从0构建WAV文件:读懂计算机文件的本质 虽然接触计算机有一段时间了,但是我的视野一直局限于一个较小的范围之内,往往只能看到于算法竞赛相关的内容,计算机各种文件在我看来十分复杂,认为构建他们并能达到目的是一件困难…...
Ruoyi框架一键改包工具:快速定制化你的项目基础配置
1. Ruoyi框架一键改包工具是什么? 如果你用过Ruoyi框架开发项目,肯定遇到过这样的烦恼:每次新建项目都要手动修改groupId、artifactId、包名这些基础配置,不仅麻烦还容易出错。我刚开始用Ruoyi时,光是改这些配置就要花…...
