本例以Windows, JDK1.8, MySQL5 为基础,演示使用Hibernate5以注解的方式完成多对多的双向关系映射。

在多对多的关联上,需求创建一个中间表,中间表用来连接两个多不多关系的表,等于在中间表中保存了两个表的映射关系.

多对多的表的关系

Model

分别创建HeroHeroBook两个Model对象,在映射关系上,HeroHeroBook存在多对多映射,以Hero作为主控方。

File : Hero.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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package com.devnp.hibernate.association.mtm.model;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name = "HERO")
public class Hero {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "HERO_ID")
private Long heroId ;

@Column(name = "HERO_NAME")
private String heroName ;

@Column(name = "HERO_AGE")
private Integer heroAge ;

@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "heroes_mapping",
joinColumns = {@JoinColumn(name = "HERO_ID", nullable = false, updatable = false)},
inverseJoinColumns = { @JoinColumn(name = "HERO_BOOK_ID", nullable = false, updatable = false)})
private Set<HeroBook> heroBooks = new HashSet<HeroBook>();


public Hero() {
super();
}


public Hero(String heroName, Integer heroAge) {
super();
this.heroName = heroName;
this.heroAge = heroAge;
}


public Long getHeroId() {
return heroId;
}


public void setHeroId(Long heroId) {
this.heroId = heroId;
}


public String getHeroName() {
return heroName;
}


public void setHeroName(String heroName) {
this.heroName = heroName;
}


public Integer getHeroAge() {
return heroAge;
}


public void setHeroAge(Integer heroAge) {
this.heroAge = heroAge;
}


public Set<HeroBook> getHeroBooks() {
return heroBooks;
}


public void setHeroBooks(Set<HeroBook> heroBooks) {
this.heroBooks = heroBooks;
}

}

File : HeroBook.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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.devnp.hibernate.association.mtm.model;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name = "HERO_BOOK")
public class HeroBook {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "HERO_BOOK_ID")
private Long heroBookId ;

@Column(name = "HERO_BOOK_NAME")
private String heroBookName ;

@Column(name = "HERO_BOOK_PRICE")
private Float heroBookPrice ;

@ManyToMany(fetch = FetchType.LAZY, mappedBy="heroBooks")
private Set<Hero> heros = new HashSet<Hero>();

public HeroBook() {
super();
}

public HeroBook(String heroBookName, Float heroBookPrice) {
super();
this.heroBookName = heroBookName;
this.heroBookPrice = heroBookPrice;
}

public Long getHeroBookId() {
return heroBookId;
}

public void setHeroBookId(Long heroBookId) {
this.heroBookId = heroBookId;
}

public String getHeroBookName() {
return heroBookName;
}

public void setHeroBookName(String heroBookName) {
this.heroBookName = heroBookName;
}

public Float getHeroBookPrice() {
return heroBookPrice;
}

public void setHeroBookPrice(Float heroBookPrice) {
this.heroBookPrice = heroBookPrice;
}

public Set<Hero> getHeros() {
return heros;
}

public void setHeros(Set<Hero> heros) {
this.heros = heros;
}

}

Hibernate SessionFactory

本例以属性配置的加载,更多获取SessionFactory的方式:Hibernate5 SessionFactory 的获取

添加Hero.javaHeroBook.java
File : HibernateProUtil.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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package com.devnp.hibernate.util;

import java.util.Properties;

import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

import com.devnp.hibernate.association.mtm.model.Hero;
import com.devnp.hibernate.association.mto.model.Company;
import com.devnp.hibernate.association.mto.model.Employee;
import com.devnp.hibernate.association.otm.model.Book;
import com.devnp.hibernate.association.otm.model.Person;
import com.devnp.hibernate.association.oto.model.Student;
import com.devnp.hibernate.association.oto.model.Transcripts;

public class HibernateProUtil {

private static SessionFactory sessionFactory = buildSessionFactory();

private static SessionFactory buildSessionFactory() {
Properties properties = new Properties();
properties.put("hibernate.dialect","org.hibernate.dialect.MySQL5InnoDBDialect"); //数据库方言
properties.put("hibernate.show_sql", "true"); //是否打印SQL
properties.put("hibernate.hbm2ddl.auto","update"); //执行跟新,及如果表不存在则会自动创建表

properties.put("hibernate.format_sql", "true"); //格式化

properties.put("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
properties.put("hibernate.connection.password", "!qaz2wsx");
properties.put("hibernate.connection.url", "jdbc:mysql://localhost:3306/test");
properties.put("hibernate.connection.username", "root");

/*StandardServiceRegistryBuilder standardServiceRegistryBuilder = new StandardServiceRegistryBuilder();
standardServiceRegistryBuilder.applySettings(properties);

MetadataSources metadataSources = new MetadataSources(standardServiceRegistryBuilder.build());
metadataSources.addAnnotatedClass(Student.class);*/

StandardServiceRegistry serviceRegistry= new StandardServiceRegistryBuilder().applySettings(properties).build();

MetadataSources metadataSources = new MetadataSources(serviceRegistry);
//add for one to one
metadataSources.addAnnotatedClass(Student.class).addAnnotatedClass(Transcripts.class);

//add for one to many
metadataSources.addAnnotatedClass(Person.class).addAnnotatedClass(Book.class);

//add for many to one
metadataSources.addAnnotatedClass(Employee.class).addAnnotatedClass(Company.class);

//add for many to many
metadataSources.addAnnotatedClass(Hero.class).addAnnotatedClass(com.devnp.hibernate.association.mtm.model.HeroBook.class);

Metadata metadata = metadataSources.getMetadataBuilder().applyImplicitNamingStrategy(
ImplicitNamingStrategyJpaCompliantImpl.INSTANCE).build();

sessionFactory = metadata.getSessionFactoryBuilder().build();

return sessionFactory;
}

public static SessionFactory getSessionFactory() {
return sessionFactory;
}

public static void shutdown() {
// Close caches and connection pools
getSessionFactory().close();
}
}

测试

添加对象:
File : ManyToManyOperation.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
53
54
55
56
57
58
package com.devnp.hibernate.association.operation;

import java.util.HashSet;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.devnp.hibernate.association.mtm.model.Hero;
import com.devnp.hibernate.association.mtm.model.HeroBook;
import com.devnp.hibernate.util.HibernateProUtil;

public class ManyToManyOperation {

public static void main(String[] args) {
// TODO Auto-generated method stub
save();
}

/**
* "Guo Jin" and "Huang Rou" belong "Eagle Shooting Heroes" book
*
* "Yang Guo" belong "Eagle Shooting Heroes" and "Shooting Knight" book
*
*/
public static void save(){
SessionFactory sessionFactory = HibernateProUtil.getSessionFactory();

Session session = sessionFactory.openSession();

session.getTransaction().begin();

Hero hero1 = new Hero("Guo Jin", 33);
Hero hero2 = new Hero("Huang Rou", 25);
Hero hero3 = new Hero("Yang Guo", 22);

HeroBook book1 = new HeroBook("Eagle Shooting Heroes", 22.3F);
HeroBook book2 = new HeroBook("Shooting Knight", 23.5F);

Set<HeroBook> heroBooks = new HashSet<HeroBook>();
heroBooks.add(book1);

hero1.setHeroBooks(heroBooks);
hero2.setHeroBooks(heroBooks);

hero3.getHeroBooks().add(book1);
hero3.getHeroBooks().add(book2);

session.save(hero1);
session.save(hero2);
session.save(hero3);

session.getTransaction().commit();

HibernateProUtil.shutdown();
}

}

运行结果:

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
Hibernate: 

create table HERO (
HERO_ID bigint not null auto_increment,
HERO_AGE integer,
HERO_NAME varchar(255),
primary key (HERO_ID)
) engine=InnoDB
Hibernate:

create table HERO_BOOK (
HERO_BOOK_ID bigint not null auto_increment,
HERO_BOOK_NAME varchar(255),
HERO_BOOK_PRICE float,
primary key (HERO_BOOK_ID)
) engine=InnoDB
Hibernate:

create table heroes_mapping (
HERO_ID bigint not null,
HERO_BOOK_ID bigint not null,
primary key (HERO_ID, HERO_BOOK_ID)
) engine=InnoDB
Hibernate:

alter table heroes_mapping
add constraint FKrkhpo49wk4l3waye5i32x884m
foreign key (HERO_BOOK_ID)
references HERO_BOOK (HERO_BOOK_ID)
Hibernate:

alter table heroes_mapping
add constraint FKbf749uoxlaf3ys4suui71jx4k
foreign key (HERO_ID)
references HERO (HERO_ID)
Hibernate:
insert
into
HERO
(HERO_AGE, HERO_NAME)
values
(?, ?)
Hibernate:
insert
into
HERO_BOOK
(HERO_BOOK_NAME, HERO_BOOK_PRICE)
values
(?, ?)
Hibernate:
insert
into
HERO
(HERO_AGE, HERO_NAME)
values
(?, ?)
Hibernate:
insert
into
HERO
(HERO_AGE, HERO_NAME)
values
(?, ?)
Hibernate:
insert
into
HERO_BOOK
(HERO_BOOK_NAME, HERO_BOOK_PRICE)
values
(?, ?)
Hibernate:
insert
into
heroes_mapping
(HERO_ID, HERO_BOOK_ID)
values
(?, ?)
Hibernate:
insert
into
heroes_mapping
(HERO_ID, HERO_BOOK_ID)
values
(?, ?)
Hibernate:
insert
into
heroes_mapping
(HERO_ID, HERO_BOOK_ID)
values
(?, ?)
Hibernate:
insert
into
heroes_mapping
(HERO_ID, HERO_BOOK_ID)
values
(?, ?)

代码下载

java-hibernate-association-demo.zip