栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Hibernate和Spring-具有从同一个父对象继承的多个成员的实体导致JDBCException,@ Transactional怪异

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Hibernate和Spring-具有从同一个父对象继承的多个成员的实体导致JDBCException,@ Transactional怪异

唯一的问题是:

base
应该用
@MappedSuperClass
代替
@Entity
。此后-并提供pom-
无论
@Transactional
测试方法有无,它都可以正常工作。我把它放在github上。您可以浏览或克隆并运行它

git clone git://github.com/zzantozz/testbed tmpcd tmpmvn clean test -pl stackoverflow/7809543-hibernate-spring-jpa

我认为在蒸馏时,您可以找出造成问题的原因。有时候,当您完全迷路时,将项目的一个分支(如果您在git中)或在一个单独的目录中创建一个副本(如果您负担了SVN的工作)并开始破解是很有帮助的在您完全将其归结为引起问题的代码/配置之前,这不会有问题。

更新:
了解曙光。第一个问题:取决于测试是否为@Transactional,其行为不同的原因是测试事务与您的

DataGenerator
事务不同。在测试中,事务将在测试结束时回滚。在中
DataGenerator
,它已提交。更重要的是,在测试中不会刷新EntityManager,因为这通常仅在提交时发生。
flush()
是什么导致SQL发出到数据库,这就是您的错误出处。如果您使用EntityManager注入测试并调用
flush()
在测试方法的最后,您将在@Transactional测试中看到与现在在非@Transactional测试中看到的行为相同的行为。当您进行事务回滚以保持数据库干净时,这是测试的相当标准的价格。

第二个问题:因为base是一个实体,而不仅仅是包含一些我最初想到的公共字段的超类,所以您正在处理继承映射。(基于注释的继承在单独的Hibernate注释参考中介绍。)无论您是否意识到,您都隐式选择了“单个表”继承策略。无论是好是坏,它都是映射继承的JPA默认设置。这意味着base,ChildTypeA和ChildTypeB的所有字段都包含在base表中。如果您拒绝记录日志以进行调试,则会看到Hibernate正在生成此表结构:

create table base (DTYPE varchar(31) not null, id bigint generated by default as identity (start with 1), primary key (id))create table Container (id bigint generated by default as identity (start with 1), primary key (id))create table Container_base (Container_id bigint not null, childrenB_id bigint not null, childrenA_id bigint not null, primary key (Container_id, childrenA_id), unique (childrenB_id), unique (childrenA_id))

您的麻烦来自Container_base。如果仔细看,您会发现该表中的条目必须同时具有ChildTypeA主键
ChildTypeB主键。这不能准确反映您的对象模型,它们是两个不相关的集合。我不确定为什么Hibernate会这样做。我的猜测是,它只看到两个(隐式)联接表映射(即一对多关系的两个联接表),它们具有相同的表名并将它们组合在一起。这看起来像是向我报告错误的候选人。无论如何,至少有两种方法可以解决此问题:

  1. 通过添加到base 切换到每类表继承策略
    @Inheritance(strategy = InheritanceType.JOINED)
    。这将为base,ChildTypeA和ChildTypeB创建单独的表。然后,由于没有歧义,联接表将自行进行排序。
  2. 明确名称中使用,例如在集装箱上的映射的连接表
    @JoinTable(name = "containerChildA")
    @JoinTable(name = "containerChildB")
    适当的。这将创建您需要的两个单独的联接表,但将base,ChildTypeA和ChildTypeB都保留在同一表中。


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/394450.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号