【发布时间】:2015-04-11 14:37:24
【问题描述】:
Hibernate 中有规定您可以从 Criteria How to get SQL from Hibernate Criteria API (*not* for logging) 获取查询,但我想从 Hibernate saveOrUpdate 和 delete(Object) 获取更新/删除查询,所以有什么选择吗?
【问题讨论】:
Hibernate 中有规定您可以从 Criteria How to get SQL from Hibernate Criteria API (*not* for logging) 获取查询,但我想从 Hibernate saveOrUpdate 和 delete(Object) 获取更新/删除查询,所以有什么选择吗?
【问题讨论】:
正如您所提到的,可以从 Criteria、QueryDSL 或命名查询(例如使用 QueryTranslator)获取生成的 SQL 查询运行时,但不幸的是,对于内置save()、update() 等方法
获取(更准确地说是to see)生成的 SQL 的唯一方法是通过日志记录或数据库监控工具。
虽然这是最需要的功能之一,但到目前为止它还不是规范的一部分,因此它严格取决于供应商的实施(和愿望)。也就是说,Hibernate 至少目前没有提供任何方法来实现这一点。
【讨论】:
如果您想自定义 UPDATE/DELETE 语句,您可以简单地提供your ownCRUD DML 语句:
@Entity
@Table(name="CHAOS")
@SQLInsert( sql="INSERT INTO CHAOS(size, name, nickname, id) VALUES(?,upper(?),?,?)")
@SQLUpdate( sql="UPDATE CHAOS SET size = ?, name = upper(?), nickname = ? WHERE id = ?")
@SQLDelete( sql="DELETE CHAOS WHERE id = ?") @SQLDeleteAll( sql="DELETE CHAOS")
【讨论】:
据我所知,没有这样的选择。更新/保存(插入)/删除方法是懒惰地发出的。早在 10 年前,这是考虑 Hibernate 的主要功能之一。
Hibernate issues update/save/delete actions only if a select hits the database, a flush is issued or a commit happens.然后 Hibernate 遍历所有对象(及其图)以检查脏对象。出于肮脏,它会生成必要的 SQL 并尝试创建批量更改。这样可以节省连接时间并一次传输许多更改。如果您必须删除/插入/更新同一张表中的大量行,它可以大大加快数据库访问速度。
但这使得无法从此类操作接收 Hibernate 生成的 SQL,因为该操作不存在但它只是 POJO 对象中的一个标记。
如果你想要 SQL,你可以简单地做两件事。首先,您可以替换 Driver 实现并向其插入任何类型的日志记录(就像监控工具一样)。只需获取当前驱动程序实现的源代码,并在您自己的类路径中创建一个类 + 包并修改执行 + setParameter 等方法。通过这种方式,您可以查看并以编程方式使其可用 SQL 命中数据库,您还可以替换结果集实现并检查您的代码接下来多久发布一次以及各种内容。
我用它进行单元测试,效果很好。
-
第二种方法更简单。您只需进入 Hibernate 的源代码并亲自查看即可。如果 Garvin (King) 有一个特点,那就是编写可读性好的代码。只有在极少数情况下,您可以与他争论他的写作方式(对我来说,这些方法有点太长了),但除了这个非常好的阅读。因此,如果您能够获得 Hibernates 源代码(这很容易),那么值得一读。我为 Hibernate 3 使用了一周的资源,这很愉快(Eclipse 也是一本好书)。
检查代码后,您会看到在编写 SQL 之前有代表 SQL 的类,并且有 Dialect 对象和所有内容。调查它们,复制源代码在原始版本的基础上提供您自己的实现,并且您可以再次监控存储和访问,甚至操作导致最终 SQL 的所有内容,甚至在将 SQL 移交给数据库驱动程序之前获取它。
-
第一个选项适合查看所有 SQL。第二个选项非常适合了解 Hibernate 并增加您对其实际功能的控制。
【讨论】: