使用 optional=false 进行一对一延迟加载,但如何使用 null 保存关联的子对象
Posted
技术标签:
【中文标题】使用 optional=false 进行一对一延迟加载,但如何使用 null 保存关联的子对象【英文标题】:One-to-one lazily load with optional=false but how to save associated subobject with null 【发布时间】:2016-06-30 11:01:04 【问题描述】:首先,让我描述一下相关的两个类:
@Entity
@Table(catalog = "db_consumer_master", name = "t_consumer")
@PrimaryKeyJoinColumn(name = "id")
public class Customer
@OneToOne(mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
public CustomerWallet getWallet()
return wallet;
public class CustomerWallet
@Id
@Column(name = "customer_id", unique = true, nullable = false)
@GeneratedValue(generator = "gen")
@GenericGenerator(name = "gen", strategy = "foreign", parameters=@Parameter(name = "property", value = "customer"))
private long customerId;
private long amount;
@OneToOne
@PrimaryKeyJoinColumn
private Customer customer;
为了开启延迟加载,只设置fetch = FetchType.LAZY是不行的,所以我添加了“optional = false”,但是现在又出现了新的问题:
我想通过调用 session.save(lawyer) 创建一个新的 Lawyer 对象。这是创建律师实例的代码sn-p:
Customer customer= new Customer();
CustomerWallet wallet = new CustomerWallet();
customer.setWallet(wallet);
调用 save(customer) 时,抛出异常:
IdentifierGenerationException: 试图从空的一对一属性分配 id
所以,我的问题是,如何在钱包对象为 null 的情况下保存此客户对象?钱包需要一个客户 ID 作为关联的共享主键。但是在客户被持久化到数据库之前,我们不会得到这个客户 ID。我是否需要在 java 而不是数据库系统中生成 ID?这种情况还有其他选择吗?
【问题讨论】:
不应该被映射为customer
?什么是生成器“gen”?我觉得应该是“洋”
您需要 CustomerWallet 类中的属性律师
我认为@PrimaryKeyJoinColumn
for field customer
in CustomerWallet
是错误的,因为它不是 CustomerWallet
类的主键
"gen" 是 id 生成器的名称。我在别处借的。
【参考方案1】:
要启用延迟加载,仅设置 fetch = FetchType.LAZY 不起作用,所以我添加了“optional = false”
optional
属性不能强制延迟加载。它在 JPA 2.0 规范中定义如下:
(可选)关联是否可选。如果设置为 false,则必须始终存在非空关系。
以下是规范中对延迟加载的说明:
(可选)关联是应该延迟加载还是必须急切获取。 EAGER 策略是对持久性提供程序运行时的要求,即必须急切地获取关联实体。 LAZY 策略是对持久性提供程序运行时的提示。
这意味着持久性提供者没有义务延迟加载关联的实体。
现在回答你的问题:
所以,我的问题是,如何保存这个钱包对象为空的客户对象?
首先正确定义映射
您在与Customer
的关联上使用PrimaryKeyJoinColumn
注释。此注解用于在 JOINED 映射策略中将子类连接到其父类。但是在您的情况下,您的实体没有继承关系。所以你必须改用 JoinColumn 注释:
@OneToOne
@JoinColumn(name = <name_of_foreign_key>) (Optional)
private Customer customer;
从Customer
类中的@OneToOne
注释中删除optional = false
。
您的foreign key
列必须允许NULL
值。否则,你会得到引用约束冲突异常。
【讨论】:
非常感谢 ujulu。数据库架构是使用 java 类中的 hibernate4-maven-plugin 生成的,因此每次生成架构时都会更改“name_of_foreign_key”。这种情况如何处理? 顺便说一下,@PrimaryKeyJoinColumn 可用于将 User 类中的 shippingAddress 映射为共享主键关联。摘自JoinColumn
是可选的,您可以从注释中删除(请参阅上面的修改后的帖子)。 PrimaryKeyJoinColumn
所关注的内容参见Hibernate documentation。顺便说一句,我没看过那本书。以上是关于使用 optional=false 进行一对一延迟加载,但如何使用 null 保存关联的子对象的主要内容,如果未能解决你的问题,请参考以下文章
@OneToOne(optional=false) 和 @JoinColumn(nullable=false) 一起使用
Mybatis 是否支持延迟加载?如果支持,它的实现原理是 什么?
Mybatis 是否支持延迟加载?如果支持,它的实现原理是 什么?
@Basic(optional = false) vs @Column(nullable = false) vs @NotNull