应用实例:
@JsonIgnore
@ManyToOne(cascade={CascadeType.MERGE})@JoinColumn(name = "from_id")private User sender;
User.class 被控
@JsonIgnore @OneToMany(mappedBy = "sender", fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) @OrderBy(value = "id DESC") private Set<Warning> handleWarnings = new HashSet<Warning>();
一对多联级保存:
@OneToMany(mappedBy = "notice", fetch=FetchType.EAGER, cascade = {CascadeType.ALL}) private Set<NoticeGage> gages = new HashSet<NoticeGage>();
@JsonIgnore @ManyToOne @JoinColumn(name = "notice_id") private Notice notice;
Notice notice = new Notice(NoticeTypeEnum.PLEDGE_START, contractService.getAll().get(0),userService.getById(9).getData()); notice.getGages().add(new NoticeGage(notice, gageService.getById(1),50)); noticeService.save(notice);
@JsonIgnore @ManyToMany(fetch = FetchType.LAZY, mappedBy = "receivers") private Set<Warning> receiveWarnings = new HashSet<Warning>();
@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY) @JoinTable(name = "warning_user", joinColumns = {@JoinColumn(name = "warning_id")}, inverseJoinColumns = {@JoinColumn(name = "user_id")}) private Set<User> receivers = new HashSet<User>();
异常处理:
错误一
org.hibernate.AnnotationException: Collection has neither generic type or OneToMany.targetEntity() defined: com.hibernate.SubStation. bays解决方法
org.hibernate.AnnotationException: Collection has neither generic type or OneToMany.targetEntity() defined: org.svse.org.model.Order. orderItems
错误二
org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: com.hibernate.Bay.group in com.hibernate.SubStation.bays错误三
node to traverse cannot be null!
================================================================================================
转自:http://blog.csdn.net/maoyeqiu/article/details/50397078
使用注解的Hibernate one-to-one映射
几种支持的技术
使用主键的关系
join列使用 @JoinColumn注解声明,这很像@Column注解。它有很多参数指定列名,这个参数声明了将要join的目标实体的列。如果没有@JoinColumn在拥有端进行声明的话,它是默认增加的。它的名字将会连接拥有端_(下划线)和被拥有端的主键列。在双向的关系中,一边(仅仅一边)必须要作为拥有者,拥有者负责关联列的更新。为了声明另一边不负责这个关系,可以使用mappedBy。mappedBy指的是关联的拥有者端的属性的名字
上边的属性声明了它依赖于拥有实体的映射关系
运行结果:
@JoinTable注解用在Employee实体类中,被声明为一个新的表EMPLOYEE_ACCOUNT将会创建两个列EMPLOYEE_ID(EMPLOYEE表的主键)和ACCOUNT_ID(ACCOUNT表的主键),测试上述的实体将会产生下边的SQL结果
在Account实体的那一边,依旧根据拥有者边的映射关系
测试上边实体的映射关系
我们在Hibernate中有三种类型的one to one 映射关系
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
注解版关系映射Many-to-Many,Many-to-One:
摘自:
hibernate注解版关联映射 详解
属性介绍:
1.多对一:
@ManyToOne表示一个多对一的映射,该注解标注的属性通常是数据库表的外键
optional:是否允许该字段为null,该属性应该根据数据库表的外键约束来确定,默认为true
fetch:表示抓取策略,默认为FetchType.EAGER
cascade:表示默认的级联操作策略,可以指定为ALL,PERSIST,MERGE,REFRESH和REMOVE中的若干组合,默认为无级联操作
targetEntity:表示该属性关联的实体类型.该属性通常不必指定,ORM框架根据属性类型自动判断targetEntity.
示例:
@ManyToOne表示一个多对一的映射,该注解标注的属性通常是数据库表的外键
optional:是否允许该字段为null,该属性应该根据数据库表的外键约束来确定,默认为true
fetch:表示抓取策略,默认为FetchType.EAGER
cascade:表示默认的级联操作策略,可以指定为ALL,PERSIST,MERGE,REFRESH和REMOVE中的若干组合,默认为无级联操作
targetEntity:表示该属性关联的实体类型.该属性通常不必指定,ORM框架根据属性类型自动判断targetEntity.
示例:
@ManyToOne表示一个多对一的映射,该注解标注的属性通常是数据库表的外键
optional:是否允许该字段为null,该属性应该根据数据库表的外键约束来确定,默认为true
fetch:表示抓取策略,默认为FetchType.EAGER
cascade:表示默认的级联操作策略,可以指定为ALL,PERSIST,MERGE,REFRESH和REMOVE中的若干组合,默认为无级联操作
targetEntity:表示该属性关联的实体类型.该属性通常不必指定,ORM框架根据属性类型自动判断targetEntity.
示例:
2.JoinColumn
@JoinColumn和@Column类似,介量描述的不是一个简单字段,而一一个关联字段,例如.描述一个@ManyToOne的字段.
name:该字段的名称.由于@JoinColumn描述的是一个关联字段,如ManyToOne,则默认的名称由其关联的实体决定.
例如,实体Order有一个user属性来关联实体User,则Order的user属性为一个外键,
其默认的名称为实体User的名称+下划线+实体User的主键名称
示例:见@ManyToOne
3.一对多:
@OneToMany描述一个一对多的关联,该属性应该为集体类型,在数据库中并没有实际字段.
fetch:表示抓取策略,默认为FetchType.LAZY,因为关联的多个对象通常不必从数据库预先读取到内存
cascade:表示级联操作策略,对于OneToMany类型的关联非常重要,通常该实体更新或删除时,其关联的实体也应当被更新删除
例如:实体User和Order是OneToMany的关系,则实体User被删除时,其关联的实体Order也应该被全部删除
示例:
@OneToMany描述一个一对多的关联,该属性应该为集体类型,在数据库中并没有实际字段.
fetch:表示抓取策略,默认为FetchType.LAZY,因为关联的多个对象通常不必从数据库预先读取到内存
cascade:表示级联操作策略,对于OneToMany类型的关联非常重要,通常该实体更新或删除时,其关联的实体也应当被更新删除
例如:实体User和Order是OneToMany的关系,则实体User被删除时,其关联的实体Order也应该被全部删除
示例:
4.One-to-One
@OneToOne描述一个一对一的关联
fetch:表示抓取策略,默认为FetchType.LAZY
cascade:表示级联操作策略
示例:
@OneToOne描述一个一对一的关联
fetch:表示抓取策略,默认为FetchType.LAZY
cascade:表示级联操作策略
示例:
5.Many-to-Many
@ManyToMany 描述一个多对多的关联.多对多关联上是两个一对多关联,但是在ManyToMany描述中,中间表是由ORM框架自动处理
targetEntity:表示多对多关联的另一个实体类的全名,例如:package.Book.class
mappedBy:表示多对多关联的另一个实体类的对应集合属性名称
示例:
User实体表示用户,Book实体表示书籍,为了描述用户收藏的书籍,可以在User和Book之间建立ManyToMany关联@ManyToMany 描述一个多对多的关联.多对多关联上是两个一对多关联,但是在ManyToMany描述中,中间表是由ORM框架自动处理
targetEntity:表示多对多关联的另一个实体类的全名,例如:package.Book.class
mappedBy:表示多对多关联的另一个实体类的对应集合属性名称
示例:
User实体表示用户,Book实体表示书籍,为了描述用户收藏的书籍,可以在User和Book之间建立ManyToMany关联
两个实体间相互关联的属性必须标记为@ManyToMany,并相互指定targetEntity属性,
需要注意的是,有且只有一个实体的@ManyToMany注解需要指定mappedBy属性,指向targetEntity的集合属性名称
利用ORM工具自动生成的表除了User和Book表外,还自动生成了一个User_Book表,用于实现多对多关联
再接再厉,解决第三个问题:本来想排一下序,怎么也这么难啊。难也得搞定是吧^_^,前面以为orderBy按字段来呢,结果一个文档,原来是被关联实体中一个属性,哎,细心还是好啊。 再补充一点:orderby的方式对list是有效的,set和map用mapkey 。
两个实体间相互关联的属性必须标记为@ManyToMany,并相互指定targetEntity属性,
需要注意的是,有且只有一个实体的@ManyToMany注解需要指定mappedBy属性,指向targetEntity的集合属性名称
利用ORM工具自动生成的表除了User和Book表外,还自动生成了一个User_Book表,用于实现多对多关联
。。。。。。(详见原文:http://blog.csdn.net/superdog007/article/details/8534443)
摘自:
深入理解Hibernate表与表之间的关联,搞懂cascade、inverse、lazy等属性,和注解版Hibernate实例
1.搞定Hibernate表与表之间的关联,搞懂cascade、inverse、lazy等属性
2个类,书(Book),类别(BookType)
public class Book {
private Long id;
private BookType type;
}
public class BookType {
private Long id;
}
好了,我们开始
情况一
它们相互不关联
情况二
/**
* @hibernate.many-to-one column="col_booktype_id"
*/
public BookType getType() {
return type;
}
也就是说,一个类有多本书,比如有很多书是历史类别,很多其他书是数学类别,非常好理解
那么:
BookType bookType = new BookType();
Book book1 = new Book();
book1.setType(bookType);
Book book2 = new Book();
book2.setType(bookType);
bookService.save(book1);
bookService.save(book2);
先创建一个 “书本类” 的实例,再创建 2本书,都是属于这本书,保存这2本书,结果出错。为什么?因为没有把BookTpye保存,所以那2本书的类别字段就不能保存了。这时cascade登场了——
cascade有2个级别 cascade=“save-update” cascade=“delete” 我们先来看 cascade=“save-update”
/**
* @hibernate.many-to-one column="col_booktype_id" cascade=“save-update”
*/
public BookType getType() {
return type;
}
这时,在保存book1的时候自动能把booktype也保存掉,在保存book2的时候,发现booktype已经存在了,于是去更新了booktype,总之要级联过去。
所以说,其实这个功能是比较偷懒的功能,呵呵。
好了,现在我们来看看 cascade=“delete”
假设上述已经都保存完毕,那么把book1删除,OK……接着删除book2,这时,它会先去删除booktype,再删除book2,可见就是这个意思。Hibernate会认为,你历史类的书都没了,我还要历史这个类干嘛用?于是都删了。
情况三
那么现在我们有一个新的需求了,要通过booktype去得到book,比如 getBooks(“历史”) 返回一个book的Set,在没有Hibernate这些框架的时代,我们要先去 booktype表,找历史的那个id,再拿这个Id去book中,把这些book给找出来,当然,有了Hibernate,其实内部也是这么执行的,只 是大大简化了我们的编码量。好!那么这个当然是属于 one-to-many了,我们在BookType中这么去设置
<set name="books" lazy="false" inverse="true" cascade="all">
<key column="col_booktype_id"></key>
<one-to-many class="hdu.management.library528.entity.Book"/>
</set>
我们一个个属性来讲解,这里的set其实没有对应数据库的任何表和任何字段,首先这点大家要明确。
lazy 当设置为true的时候——我们得到一个 历史类 ,并没有把这个类里的书全部读出来,而是当用的时候才去读
当设置为false的时候,我们得到一个历史类,里面已经把books都封装好了,全部读出来了
很好理解吧?lazy就是懒惰的意思嘛。这里有点需要注意,一般我们在用spring进行事务操作的时候,当lazy=“true”的时候很容易会出错。解决办法:
一、如果不考虑效率的话,大家可以干脆把 lazy=“false”
二、可以去参考下 openSessionInView这个spring的拦截器
好了,我们讲重点吧,首先来看cascade="all" 这个其实不用理解的很难,和many-to-one是一样的,我们这么理解,cascade是写在哪个类里的?答:booktype。它在对哪个类进行声 明?答:这里是对book进行声明。 好了,那么意思就是,我们在删除booktype和更新添加的时候,需不需要对book也进行操作的意思。
比如,在情况二中,我们是无法对booktype进行删除的,因为有外键关联它,那么在这里我们设置了one-to-many后,OK了,当我们删除booktype的时候,会先把相关的book全部删除,接着把booktype给删除。
最后讲讲重点 inverse="true" 我在刚刚接触Hibernate的时候,对inverse、cascade这两个东西最为头痛,现在cascade已经理解的非常清楚了吧?那么我来总结inverse
第一、概念,指定要不要当自己来维护关系。(其实根本不用去理解)
第二、在one-to-many的时候,设置inverse=“true” 当然是在 one这个地方设置
第三、在many-to-many的时候,随便在哪端先设置inverse=“true”,另一个地方设置inverse=“false”
第四、别问我:“那我不这么设置行不行,换个方法设置下看看”,取消念头,回到第二和第三条。
情况四
现在又有了新的要求,刚才一直是 一个书本类下面有很多书,那么在现实中,一本书它也有可能是属于很多类别的,比如它既是历史类的又是属于地理类的。这个时候就要用many-to- many了。前面的关系中,我们用的是2张表来维护相互之间的关系,当多对多的时候,就需要在构建出一张表来维护了。
这里我们构建出一个 书本——书本类 这样一张表 ,里面有2个字段,书本ID,书本类ID,在映射到Oracle中是自动转换成联合主键的,没有重复。
/** *//**
* @hibernate.set table="lib_book_booktype" lazy="false" cascade="all" inverse="true"
*
* @hibernate.collection-key column="col_book_id"
* @hibernate.collection-many-to-many column="col_booktype_id" class="hdu.management.library528.entity.BookType"
*/
public Set getBookTypes() ...{
return bookTypes;
}
/** *//**
* @hibernate.set table="lib_book_booktype" lazy="false" cascade="all"
*
* @hibernate.collection-key column="col_booktype_id"
* @hibernate.collection-many-to-many column="col_book_id" class="hdu.management.library528.entity.Book"
*/
public Set getBooks() ...{
return books;
}
注意:不要忘记 private Set books = new HashSet();
设置和上面一样,意思也一样,唯一不同的就是多了个 table,column自然也要指向那个table了,这是设置之后,其实book和booktype这2张表图了个安宁,什么外键都没有了,只是他们的关系表在控制它们两个了。
我们继续针对,在多对多中,inverse的问题,这里我们把 book 的inverse=true booktype的inverse=false 当我们做这样的操作时
book1.getBookTypes().add(bookType1);
book1.getBookTypes().add(bookType2);
book1.getBookTypes().add(bookType3);
bookService.saveOrUpdate(book1);
会发现 book1 保存了,bookType1、2、3也保存了,但是他们的关系却没有保存,为什么?因为 book 把关系的inverse=true了,踢给别人去处理了,所以它不来理会关系的处理。所以,我们就要对 booktype这么操作才可以处理关系。当然如果,2端我们都去设置 inverse=false的话,都可以操作了,至于说效率方面的考虑,呵呵……先就不用管了。
2.hibernate之级联cascade和关系维持inverse
hibernate的关联关系,重点在理解级联cascade和inverse
1、cascade一般用在级联保存,级联更新,级联删除上
1.1cascade注解有两种,一种是基于hibernate注解
org.hibernate.annotations.Cascade
org.hibernate.annotations.CascadeType
支持一下级联
ALL, PERSIST//级联持久化,调用session.persist()时会触发级联事件 MERGE//级联保存或者更新,jpa规范 hibernate为了支持jsr220 后面添加的,调用session.merge()时触发级联 REMOVE,//级联删除,jpa规范同上,调用session.delete()时触发 REFRESH, DELETE,//级联删除,session.delete()触发 SAVE_UPDATE,//级联保存或者更新session.save(),session.update(),session.saveOrUpdate(); REPLICATE,
配置示例
- @Cascade(value={org.hibernate.annotations.CascadeType.ALL})
- private StudentInfo studentInfo ;
- @Cascade(value={org.hibernate.annotations.CascadeType.ALL})
- private StudentInfo studentInfo ;
1.2第二种注解是基于jpa规范,也就是apache jsr220规范,也是ejb3的持久层规范
javax.persistence.CascadeType
ALL,
PERSIST,调用session.persist()时触发 MERGE,调用session.merge()触发 REMOVE,调用session.delete()触发 REFRESH, DETACH
配置示例
- @ManyToOne(cascade={CascadeType.MERGE})
- @JoinColumn(name = "teacher_id")
- private Teacher teacher;
- @ManyToOne(cascade={CascadeType.MERGE})
- @JoinColumn(name = "teacher_id")
- private Teacher teacher;
1.3级联一般用在OneToOne和OneToMany上,这也是hibernate官方的推荐,有时候我们在开发中也用在 ManyToOne,ManyToMany上,只是想在测试上少写点代码而已,在持久化一个实体的时候级联持久其他关联实体,
如下:teacher和student是ManyToMany,加上了cascade注解,便于测试
- @Test
- public void addStudentToTeacher(){
- Student student1 = new Student("张三",20,20072733L);
- Student student2 = new Student("李四",20,20072734L);
- Student student3 = new Student("王五",20,20072735L);
- Teacher teacher = new Teacher("张老师");
- teacher.getStudents().add(student3);
- teacher.getStudents().add(student2);
- teacher.getStudents().add(student1);
- this.teacherDao.save(teacher);
- }
- @Test
- public void addStudentToTeacher(){
- Student student1 = new Student("张三",20,20072733L);
- Student student2 = new Student("李四",20,20072734L);
- Student student3 = new Student("王五",20,20072735L);
- Teacher teacher = new Teacher("张老师");
- teacher.getStudents().add(student3);
- teacher.getStudents().add(student2);
- teacher.getStudents().add(student1);
- this.teacherDao.save(teacher);
- }
2、inverse,英文意思是反向,反转。在这里可以理解为控制反转,也就是说实体间的关系由谁控制,所以inverse用在实体关联上。如OneToOne,OneToMany,ManyToMany
在OneToMany中,如果不指定inverse,那么hibernate会去找默认的表来维持关系。
例如用老师和课程两个实体来说明,假设teacher和course是OneToMany的关系,
配置如下:
//通过外键teacher_id关联teacher,inverse通过mappedBy来设置
- @ManyToOne(cascade={CascadeType.MERGE})
- @JoinColumn(name = "teacher_id")
- private Teacher teacher;
- @OneToMany(mappedBy="teacher",fetch=FetchType.LAZY,cascade={CascadeType.MERGE,CascadeType.REMOVE})
- private Set<Course> courses = new HashSet<Course>();
- @ManyToOne(cascade={CascadeType.MERGE})
- @JoinColumn(name = "teacher_id")
- private Teacher teacher;
- @OneToMany(mappedBy="teacher",fetch=FetchType.LAZY,cascade={CascadeType.MERGE,CascadeType.REMOVE})
- private Set<Course> courses = new HashSet<Course>();
在这里指定teacher的属性courses的关系由关联实体Course的teacher属性维持,如果不配置,则会去找关联表teacher_course来维持关系。OneToOne和ManyToMany大同小异,这里不再累述!
4.Hibernate注解版,多对一,一对多关系映射
:双向一对多关系,一是关系维护端(owner side),多是关系被维护端(inverse side)。在关系被维护端需要通过@JoinColumn建立外键列指向关系维护端的主键列。
@OneToMany and @ManyToMany 关系的默认FetchType 是 LAZY;
@OneToOne and @ManyToOne 关系的默认 FetchType是EAGER;
即reference为集合的fetch type 是Lazy, 看上去还是比较有道理的。但是如果记不清的话,可以根据自己的需要统统声明一下。毕竟这些默认设置和Hibernate是不同的。
。。。。。。(详见原文:http://blog.csdn.net/he90227/article/details/38228467)
hibernate中基于annotation(注解)的many2many双向
简单的多对多映射关系
Admin.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
package
org.zttc.itat.model;
import
java.util.Set;
import
javax.persistence.Entity;
import
javax.persistence.GeneratedValue;
import
javax.persistence.Id;
import
javax.persistence.ManyToMany;
import
javax.persistence.Table;
@Entity
@Table
(name=
"t_admin"
)
public
class
Admin {
private
int
id;
private
String name;
private
Set<Role> roles;
@Id
@GeneratedValue
public
int
getId() {
return
id;
}
public
void
setId(
int
id) {
this
.id = id;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
@ManyToMany
(mappedBy=
"admins"
)
public
Set<Role> getRoles() {
return
roles;
}
public
void
setRoles(Set<Role> roles) {
this
.roles = roles;
}
}
|
Role.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
package
org.zttc.itat.model;
import
java.util.HashSet;
import
java.util.Set;
import
javax.persistence.Entity;
import
javax.persistence.GeneratedValue;
import
javax.persistence.Id;
import
javax.persistence.JoinColumn;
import
javax.persistence.JoinTable;
import
javax.persistence.ManyToMany;
import
javax.persistence.Table;
@Entity
@Table
(name=
"t_role"
)
public
class
Role {
private
int
id;
private
String name;
private
Set<Admin> admins;
public
Role() {
admins =
new
HashSet<Admin>();
}
public
void
add(Admin admin) {
admins.add(admin);
}
@Id
@GeneratedValue
public
int
getId() {
return
id;
}
public
void
setId(
int
id) {
this
.id = id;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
@ManyToMany
@JoinTable
(name=
"t_role_admin"
,joinColumns={
@JoinColumn
(name=
"rid"
)},
inverseJoinColumns={
@JoinColumn
(name=
"aid"
)})
public
Set<Admin> getAdmins() {
return
admins;
}
public
void
setAdmins(Set<Admin> admins) {
this
.admins = admins;
}
}
|
原文链接:http://www.656463.com/article/zimQ7n.htm
关系/对象映射 多对多关系(@ManyToMany 注释)【重新认识】
查了好多资料
old:
原文链接:http://blog.csdn.net/gabriel80/article/details/4260923