每个用户注册信息就对应一个登录信息,双方是相互依存的,由于主键共享,如果有任意表的一条记录被删除或者新增,那么另一张表也会删除对应的记录或者新增一条记录。而且一对一不管是save还是update都必须手工维护双向关系。
在一对一中,关联关系的对象默认都是使用延迟加载,<many-to-one>默认的属性是lazy="proxy",此时默认是会延迟加载的.在指定了lazy="true"之后,需要动态字节码增强才能实现延迟加载。
在这里不管是加载USER还是LOGIN都应该是延迟加载彼此关联对象,在实际业务需求上两者也没有关系的。
对于延迟加载,Hibernate无法知道什么时候会调用到延迟加载的属性/字段的get方法,所以对于延迟加载的属性/字段,Hibernate会通过建立代理Proxy来包装(Wrapper)一下。
代理可能会根据实体本身建立,也可以是根据一个集合建立,如果是根据一个集合建立,延迟加载一般都能成功,如果是根据实体建立,null是不能建立代理的,如果能够确定代理类一定存在,那延迟加载就能成功,相关的映射放置的是代理类,如果不能确定映射的属性是否存在,那就会去数据库中进行查询,这就导致的延迟失败。比如查询自身对象时查完之后,没有加载关联对象,然后当需要用到关联属性的时候,Hibernate又会去数据库查询,但是这时候session已经关闭,因为如果是currentsession的话在第一次查询后commit就关闭了(如果是web项目配置了spring的一请求一事务就不会报错),所以会报:org.hibernate.LazyInitializationException: could not initialize proxy - no Session异常,外键定义可以让Hibernate知道映射的属性是否存在,也可以通过JPA的optional=false属性来告诉hibernate这个对象肯定是有值的,映射的属性一定存在。那么这个时候fetch = FetchType.LAZY这个属性就生效了,就可以达到延迟加载的效果。
/**
* @author Chou
* @since 2012-07-07
* ...用户注册信息实体
*
*/
@Entity
@Table(name = "TAB_USER_INFO")
@SequenceGenerator(name = "seq", sequenceName = "SEQ_USER_INFO", allocationSize = 1)
public class User {
private Long id;
private String username;
private Boolean sex;
private String telephone;
private String email;
private Login login;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq")
public Long getId() {
return id;
}
......
@OneToOne(mappedBy = "user", fetch = FetchType.LAZY, optional = false, cascade = {CascadeType.REMOVE})
@Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
public Login getLogin() {
return login;
}
public void setLogin(Login login) {
this.login = login;
}
}
/**
* @author Chou
* @since 2012-07-07
* ...登录帐号表实体
*
*/
@Entity
@Table(name = "TAB_LOGIN_INFO")
public class Login {
private Long id;
private String loginName;
private String loginPwd;
private User user;
@Id
@GeneratedValue(generator = "sharePK")
@GenericGenerator(name = "sharePK", strategy = "foreign", parameters = @Parameter(name = "property", value = "user"))
public Long getId() {
return id;
}
......
@OneToOne(fetch = FetchType.LAZY, optional = false, cascade = {CascadeType.REMOVE})
@Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
@PrimaryKeyJoinColumn
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
SaveOrUpdate和merge方法的级联设置
对于这两个方法有什么不同,先去我的《Hibernate4之Session一级缓存》这个帖子看看。
上面代码设置级联保存或者更新的时候为什么不用CascadeType.MERGE,而是用org.hibernate.annotations.CascadeType.SAVE_UPDATE呢?
研究一下代码,@OneToMany来自JPA,它期望一个JPA级联—javax.persistence.CascadeType。然而,当使用Hibernate session保存它时,org.hibernate.engine.Cascade将做如下的检查:
if ( style.doCascade( action ) ) {
cascadeProperty(
persister.getPropertyValue( parent, i, entityMode ),
types[i],
style,
anything,
false
);
}
Hibernate的保存过程将引起一个ACTION_SAVE_UPDATE动作,但是JPA将传递一个ACTION_PERSIST和ACTION_MERGE,这与Hibernate的要求不匹配,并引起级联的执行失败。
还有一种方法就是用CascadeType.ALL也可以解决此问题。但是这也意味着所有操作都会有级联效应,并不能满足所有程序的需求。
分享到:
相关推荐
本篇主要探讨的是Hibernate中的一对一(OneToOne)关系映射,特别是唯一外键关联(UniDirectional and Bidirectional Association)的情况。我们将深入理解这种关联方式的配置、实现以及它在实际应用中的价值。 1. ...
在Java的持久化框架Hibernate中,一对一(One-to-One)关联映射是常见的关系映射方式之一,尤其在处理两个实体之间存在唯一对应关系时非常有用。本篇将重点讲解如何实现一对一主键关联映射的单向关联,并通过一个...
在Java的持久化框架Hibernate中,一对一(One-to-One)关系是对象之间的关联类型之一,它代表了两个实体之间存在唯一的对应关系。本篇将详细讲解如何使用Hibernate实现一对一唯一外键(Unique Foreign Key)关联映射...
总之,Hibernate的多对多关联映射是解决复杂关系数据库设计的关键技术之一。通过合理的配置和使用,开发者可以轻松管理实体之间的多对多关系,提高开发效率。理解并熟练掌握这部分知识对于提升Java企业级应用开发...
在Hibernate中,一对一关联的配置主要通过注解或XML配置文件完成。对于双向关联,我们需要在两个实体类中分别设置相应的属性和关联注解。 在实体类A中,我们将添加一个类型为B的属性,并使用`@OneToOne`注解来指定...
在" Hibernate教程07_关系映射之一对一双向主键关联"中,我们将学习如何设置这种关联。首先,我们需要创建两个实体类,例如`Employee`和`Department`。在每个类中,我们都需要定义主键字段,并用`@Id`注解标记。然后...
这种关联关系可以是单向的,也可以是双向的,而这里的"hibernate关联关系之一对一双向关联"着重讨论的是后者。双向关联意味着两个实体类都可以直接访问对方,提供了更方便的数据操作。 在Hibernate中,一对一双向...
在Java的持久化框架Hibernate中,一对一(One-to-One)关联是对象关系映射(ORM)中的一个重要概念,用于表示两个实体之间一对一的关系。在这个场景下,我们将讨论一种特殊的一对一关联方式——唯一外键关联(Single...
在Java的持久化框架Hibernate中,一对一(One-to-One)关联映射是常见的关系数据库模型映射方式之一。本文将详细解析如何实现一对一唯一外键(Uniquely Foreign Key,UFK)关联映射,特别是在单向关联的情况下的具体...
下面将详细介绍Hibernate中的多对一关联关系以及如何实现这一关系。 1. **多对一关联的配置**: - 在实体类中,使用`@ManyToOne`注解来声明一个字段作为多对一的关联字段。这个注解通常用于父类的引用,例如: ``...
4. Hibernate 一对多外键单向关联: 在这种关联中,一个实体类(如 Department)可以有多个实体类(如 Employee)与其关联,而 Employee 并不知道这个关联。配置上,会在 Employee 实体类中使用 `many-to-one` 元素...
本篇文章主要探讨的是Hibernate中的一对多关联映射,这是一种常见的对象关系映射(ORM)配置,用于表示一个实体与多个其他实体之间的关系。 在关系型数据库中,一对多关联是指一个表(父表)中的记录可以对应另一个...
本篇将详细探讨 Hibernate 之中的一对一关联映射,这是一种常见的关系数据库设计模式,在实际开发中经常被用到。 一对一关联映射在Hibernate中表示两个实体类之间存在一对一的关系,也就是说,每个实体类的对象只...
10. **最佳实践**:如避免过多的中间表查询,合理设计关联关系,以及在不必要时选择一对一或一对多替代多对多等。 总结来说,理解并能正确使用Hibernate中的多对多双向关联是Java开发中的重要技能,涉及到实体设计...
本教程“传智播客hibernate教程_保存多对一关联关系的更进一步分析”深入探讨了如何在Hibernate中处理多对一的关联关系。这种关联意味着一个实体(多方)可以与多个其他实体(一方)相关联,而每个其他实体只与一个...
**标题详解:**“Hibernate教程04_关系映射之一对一单向外键关联” 在Hibernate框架中,关系映射是数据库表之间的关联在对象模型中的体现。本教程重点讲解了一对一(One-to-One)单向外键关联的实现方法。在数据库...
在Java的持久化框架Hibernate中,关联映射是核心概念之一,它允许对象之间的关系在数据库层面得以体现。本文将详细解析四种基本的关联类型:一对一(OneToOne)、多对多(ManyToMany)、一对多(OneToMany)和多对一...
在Java的持久化框架Hibernate中,一对一(One-to-One)关联映射是常见的关系映射方式之一,尤其在处理数据库中的唯一外键关联时。这种映射方式允许在一个实体类中引用另一个实体类的唯一实例,形成一对一的关系。在...
一对一关联是数据库设计中最常见的关联类型之一,它指的是两个实体之间存在一种一对一的关系。在Hibernate中,一对一关联可以被进一步细分为单向关联和双向关联,以及基于主键关联和基于外键关联。 #### 单向关联 ...