在博客站点中,我们可能须要从某一篇文章找到其所关联的作者。这就须要从文章方建立起对用户的关联,即是多对一的映射关系。

如今先看一个配置实例:我们的文章实体类

package com.zeng.model;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table; @Table(name = "t_article")
@Entity
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Lob//数据可能会很长,映射为数据库支持的“大对象”
private String content;
/**
* @ManyToOne 使用此标签建立多对一关联,此属性在“多”方使用注解在我们的“一”方属性上
* @cascade 指定级联操作,以数组方式指定,假设仅仅有一个,能够省略“{}”
* @fetch 定义抓取策略
* @optional 定义是否为必需属性,假设为必需(false),但在持久化时user = null,则会持久化失败
* @targetEntity 目标关联对象,默觉得被注解属性所在类
*/
@ManyToOne(cascade ={CascadeType.ALL},fetch = FetchType.LAZY,optional = false,targetEntity = User.class)
private User user;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}

由于这里是单向关联,所以我们无须在在User类中建立对文章的关联属性

接下来编写我们的測试类

package com.zeng.test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.zeng.model.Article;
import com.zeng.model.User; public class Test2 {
private static ApplicationContext ac;
private static SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@BeforeClass//在測试类初始化时调用此方法,完毕静态对象的初始化
public static void before(){
ac = new ClassPathXmlApplicationContext("spring-datasource.xml");
sessionFactory = (SessionFactory) ac.getBean("sessionFactory");
}
@Before//每个被注解Test方法在调用前都会调用此方法一次
public void setup(){//建立针对我们当前測试方法的的会话和事务
session = sessionFactory.openSession();
transaction = session.beginTransaction();
}
//測试级联关系映射注解配置:多对一单向关联
@Test
public void test1(){
User user = new User();
user.setName("name1");
Article article = new Article();
article.setContent("content1");
article.setUser(user);//建立级联关系
session.save(article);//注意这里我们没有保存我们的user对象
} @After//每个被注解Test方法在调用后都会调用此方法一次
public void teardown(){
transaction.commit();
session.clear();
session.close();
}
@After//在类销毁时调用一次
public void after(){
sessionFactory.close();
} }

调用上面測试方法,我们会发现,hibernate帮我们在上篇文章已建立User类的基础上,又帮我们创建了t_article数据表:

mysql> desc t_article;

+———+————–+——+—–+———+—————-+

| Field | Type | Null | Key | Default | Extra |

+———+————–+——+—–+———+—————-+

| id | int(11) | NO | PRI | NULL | auto_increment |

| content | varchar(255) | YES | | NULL | |

| user_id | int(11) | NO | MUL | NULL | |

+———+————–+——+—–+———+—————-+

3 rows in set (0.00 sec)

然后我们查看用户表和文章表。会看到:

mysql> select * from t_user;

+—-+——-+

| id | name |

+—-+——-+

| 1 | name1 |

+—-+——-+

1 row in set (0.00 sec)

mysql> select * from t_article;

+—-+———-+———+

| id | content | user_id |

+—-+———-+———+

| 1 | content1 | 1 |

+—-+———-+———+

1 row in set (0.00 sec)

能够看到。这里我们的user_id和user表的新建记录id是相应的。

看完实例,下面我们针对配置的属性进行详细分析:

1. cascade属性

属性 说明
CascadeType.MERGE 级联更新:若user属性改动了那么article对象保存/更新时同一时候改动user在数据库里的属性值
CascadeType.PERSIST 级联保存:对article对象保存时也对user里的对象也会保存。
CascadeType.REFRESH 级联刷新:获取article对象里也同一时候也又一次获取最新的user时的对象。即会又一次查询数据库里的最新数据
CascadeType.REMOVE 级联删除:对article对象删除也会使相应user的象删除
CascadeType.ALL 包括PERSIST, MERGE, REMOVE, REFRESH, DETACH等;

级联属性对于一方和多方的作用效果是不一样的。经測试发现,在多对一中,多方使用CascadeType.PERSIST无法级联保存对象,必须使用CascadeType.ALL。而级联删除既可使用CascadeType.REMOVE也可使用CascadeType.ALL

对于上述方法,假设我们没有设置级联保存,在我们保存文章对象时,用户对象自然不会持久化到数据库,这时候会报错:



org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.zeng.model.User



在我们提交事务的时候,hibernate总会flush(清理)我们的session缓存。所谓清理,是指hibernate依照持久化对象的属性变化来同步更新数据库,当发现我们的article对象引用了暂时对象user,而article.user.id = null,会推断user对象是瞬时的Transient,这个我们要持久化到数据库中的article对象发生冲突,因此会保存失败。这里我们也意在说明,关系直接的级联映射是通过用户对象标识符id来确认的。意思是说,即使article.user.其它属性全为null,但仅仅要article.user.id在数据库中有相关记录(saved)这时就能建立两者的级联关系了。

还有一方面,假设我们习惯了xxx.htm.xml的方式来配置我们的实体映射关系,那我们必定对hibernate的级联属性更加熟悉,这时我们能够通过@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})来使用hibernate内置级联属性。关于hibernate的内置级联属性常见有:

属性名 说明
save-update 级联保存(load以后假设子对象发生了更新。也会级联更新)。 但它不会级联删除
delete 级联删除, 但不具备级联保存和更新
all-delete-orphan 在解除父子关系时,自己主动删除不属于父对象的子对象, 也支持级联删除和级联保存更新。
all 级联删除, 级联更新。但解除父子关系时不会自己主动删除子对象。
delete-orphan 删除全部和当前对象解除关联关系的对象

2. @JoinColumn

它的详细值可參照下表

属性 默认值 说明
columnDefinition JPA 使用最少量 SQL 创建一个数据库表列。

假设须要使用很多其它指定选项创建列,将 columnDefinition 设置为在针对列生成 DDL 时希望 JPA 使用的 String SQL 片断。

insertable true 默认情况下,JPA 持续性提供程序假设它能够插入到全部表列中。假设该列为仅仅读,请将 insertable 设置为 false。
name 默认值 假设使用一个连接列,则 JPA 持续性提供程序假设外键列的名称是下面名称的连接:
1. 引用关系属性的名称 +“”+ 被引用的主键列的名称。
2. 引用实体的字段名称 +“
”+ 被引用的主键列的名称。

3. 假设实体中没有这种引用关系属性或字段(请參阅 @JoinTable),则连接列名称格式化为下面名称的连接:实体名称 +“_”+ 被引用的主键列的名称。这是外键列的名称。

假设连接针对“一对一”或“多对一”实体关系,则该列位于源实体的表中。假设连接针对“多对多”实体关系。则该列位于连接表(请參阅 @JoinTable)中。

4. 假设连接列名难于处理、是一个保留字、与预先存在的数据模型不兼容或作为数据库中的列名无效,请将 name 设置为所需的 String 列名。

nullable true 默认情况下,JPA 持续性提供程序假设同意全部列包括空值。假设不同意该列包括空值。请将nullable 设置为 false。

referencedColumnName 假设使用一个连接列,则 JPA 持续性提供程序假设在实体关系中,被引用的列名是被引用的主键列的名称。

假设在连接表(请參阅 @JoinTable)中使用,则被引用的键列位于拥有实体(假设连接是反向连接定义的一部分,则为反向实体)的实体表中。要指定其它列名,请将 referencedColumnName 设置为所需的 String 列名。

table JPA 持续性提供程序假设实体的全部持久字段存储到一个名称为实体类名称的数据库表中(请參阅 @Table)。假设该列与辅助表关联(请參阅 @SecondaryTable)。请将 name 设置为相应辅助表名称的 String 名称
unique false 默认情况下,JPA 持续性提供程序假设同意全部列包括反复值。假设不同意该列包括反复值,请将 unique 设置为 true。
updatable true 默认情况下,JPA 持续性提供程序假设它能够更新全部表列。

假设该列为仅仅读。则将 updatable 设置为 false

參考:http://blog.sina.com.cn/s/blog_4bc179a80100kd0k.html

hibernate5(9)注解映射[1]多对一单向关联的更多相关文章

  1. hibernate5(10)注解映射[2]一对多单向关联

    在上一篇文章里.我们从端方向一端建立关联关系,完毕了从文章到作者的关联关系建立.但在实际的博客站点中,用户肯定还须要获取自己所写的文章,这时能够建立用户(一)对文章(多)的单向关联映射. 先来看我们的 ...

  2. Hibernate,关系映射的多对一单向关联、多对一双向关联、一对一主键关联、一对一外键关联、多对多关系关联

    2018-11-10  22:27:02开始写 下图内容ORM.Hibernate介绍.hibername.cfg.xml结构: 下图内容hibernate映射文件结构介绍 下图内容hibernate ...

  3. hibernate5(12)注解映射[4]一对一外键关联

    在实际博客站点中,文章内容的数据量非常多,它会影响我们检索文章其他数据的时间,如查询公布时间.标题.类别的等. 这个时候,我们能够尝试将文章内容存在还有一张表中,然后建立起文章--文章内容的一对一映射 ...

  4. java之hibernate之关联映射之多对一单向关联

    1.在之前学习了单表的crud操作.在实际应用中,大都是多表关联操作,这篇会学习如何处理多表之间的关系. 2.考察书籍表和书籍分类表的关系.书籍表和书籍分类表之间是多对一的关系.数据库的表设计为: 3 ...

  5. Hibernate从入门到精通(十)多对多单向关联映射

    上一篇文章Hibernate从入门到精通(九)一对多双向关联映射中我们讲解了一下关于一对多关联映射的相关内容,这次我们继续多对多单向关联映射. 多对多单向关联映射 在讲解多对多单向关联映射之前,首先看 ...

  6. Hibernate从入门到精通(七)多对一单向关联映射

    上次的博文Hibernate从入门到精通(六)一对一双向关联映射中我们介绍了一下一对一双向关联映射,本次博文我们讲解一下多对一关联映射 多对一单向关联映射 多对一关联映射与一对一关联映射类似,只是在多 ...

  7. Hibernate(十)多对多单向关联映射

    上一篇文章Hibernate从入门到精通(九)一对多双向关联映射中我们讲解了一下关于一对多关联映射的 相关内容,这次我们继续多对多单向关联映射. 多对多单向关联映射 在讲解多对多单向关联映 射之前,首 ...

  8. Hibernate(七)多对一单向关联映射

    上次的博文Hibernate从入门到精通(六)一对一双向关联映射中我们介绍了一下一对一双向关联映射,本 次博文我们讲解一下多对一关联映射 多对一单向关联映射 多对一关联映射与一对一关联映射类 似,只是 ...

  9. [置顶] Hibernate从入门到精通(七)多对一单向关联映射

    上次的博文Hibernate从入门到精通(六)一对一双向关联映射中我们介绍了一下一对一双向关联映射,本次博文我们讲解一下多对一关联映射 多对一单向关联映射 多对一关联映射与一对一关联映射类似,只是在多 ...

随机推荐

  1. css 权重 特殊性

    选择器的特异性由 CSS2 规范定义如下:     !important的规则比其他的权值都大     p{color: red !important} 如果声明来自于“style”属性,而不是带有选 ...

  2. pie.htc 在IE下不起作用~~~

    一直用的IE11 然后选择其中的兼容模式来测试IE 7~10的情况. 最近由于客户要求 圆角阴影兼容IE,只能选择PIE.HTC的方案. 但是反复测试发现不起作用. 官方文档的几种说明: 1. pie ...

  3. Struts2开发文档

    struts2配置 struts2核心配置文件约束 <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts ...

  4. WPF 简易的喷泉效果

    这两天领导让我做个喷泉的效果,要把一个个UserControl从一个位置喷出,然后,最后落在最终需要在的位置. 喷泉效果说白了,就是两个步骤:1.放大,从0放大到需要的倍数:2.缩小,平移,从放大的倍 ...

  5. TFS在项目中DevOps落地进程(下)

    紧接上篇 TFS在项目中Devops落地进程(上) 再接着说TFS相关之前先插入一个番外篇,虽然跟TFS关系不大但跟DevOps关系很大,觉得有必要在此乱入一下. 番外篇--监控之Applicatio ...

  6. requests和BeautifulSoup

    一:Requests库 Requests is an elegant and simple HTTP library for Python, built for human beings. 1.安装 ...

  7. Django 入门案例开发(中)

    昨天已经描述了如何搭建Django的开发环境,今天描述业务流程,具体我们要实现一个什么样的业务: 以下的业务都是假设的(网上书店   页面做的low): 1.用户注册及登录业务: 这是一个网上书店阅读 ...

  8. java并发之同步辅助类(Semphore、CountDownLatch、CyclicBarrier、Phaser)

    线程同步辅助类,主要学习两点: 1.上述几种同步辅助类的作用以及常用的方法 2.适用场景,如果有适当的场景可以用到,那无疑是最好的 semaphore(seməˌfôr) 含义 信号量就是可以声明多把 ...

  9. mac 安装protobuf,并编译

    因公司接口协议是PB文件,需要将 PB 编译成JAVA文件,且MAC 电脑,故整理并分享MAC安装 google 下的protobuf 文件   MAC 安装protobuf 流程 1.下载 http ...

  10. c# winform treelistview的使用(treegridview)

    TreeView控件显示的内容比较单一,如果需要呈现更详细信息TreeListView是一个不错的选择. 先看效果: 首先需要引用文件System.Windows.Forms.TreeListView ...