016 多对多关联映射 单向(many-to-many)

  • 一般的设计中,多对多关联映射,需要一个中间表
  • Hibernate会自动生成中间表
  • Hibernate使用many-to-many标签来表示多对多的关联
  • 多对多的关联映射,在实体类中,跟一对多一样,也是用集合来表示的。

实例场景:

用户与他的角色(一个用户拥有多个角色,一个角色还可以属于多个用户)

Role实体类:

public class Role {

private int id;

private String name;

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;

}

}

User实体类:

public class User {

private int id;

private String name;

private Set roles;//Role对象的集合

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;

}

public Set getRoles() {

return roles;

}

public void setRoles(Set roles) {

this.roles = roles;

}

}

Role映射文件:

<hibernate-mapping>

<class name="com.wjt276.hibernate.Role" table="t_role">

<id name="id">

<generator class="native"/>

</id>

<property name="name" column="name"/>

</class>

</hibernate-mapping>

User映射文件:

<hibernate-mapping>

<class name="com.wjt276.hibernate.User" table="t_user">

<id name="id" column="id">

<generator class="native"/>

</id>

<property name="name"/>

<!--使用<set>标签映射集合(set),标签中的name值为对象属性名(集合roles),而使用table属性是用于生成第三方表名称,例:table="t_user_role",但是第三方面中的字段是自动加入的,作为外键分别指向其它表。

所以表<key>标签设置,例:<key column="userid"/>,意思是:在第三方表(t_user_role)中加入一个外键并且指向当前的映射实体类所对应的表(t_user).使用<many-to-many>来指定此映射集合所对象的类(实例类),并且使用column属性加入一个外键指向Role实体类所对应的表(t_role) -->

<set name="roles" table="t_user_role">

<key column="userid"/>

<many-to-many class="com.wjt276.hibernate.Role" column="roleid"/>

</set>

</class>

</hibernate-mapping>

导出至数据库表所生成SQL语句

create table t_role (id integer not null auto_increment, name varchar(255), primary key (id))

create table t_user (id integer not null auto_increment, name varchar(255), primary key (id))

create table t_user_role (userid integer not null, roleid integer not null, primary key (userid, roleid))

alter table t_user_role add index FK331DEE5F1FB4B2D4 (roleid), add constraint FK331DEE5F1FB4B2D4 foreign key (roleid) references t_role (id)

alter table t_user_role add index FK331DEE5F250A083E (userid), add constraint FK331DEE5F250A083E foreign key (userid) references t_user (id)

注:根据DDL语句可以看出第三方表的主键是一个复合主键(primary key (userid, roleid)),也就是说记录不可以有相同的数据。

数据库表及结构:

多对多关联映射 单向数据存储:

session = HibernateUtils.getSession();

tx = session.beginTransaction();

Role r1 = new Role();

r1.setName("数据录入人员");

session.save(r1);

Role r2 = new Role();

r2.setName("商务主管");

session.save(r2);

Role r3 = new Role();

r3.setName("大区经理");

session.save(r3);

User u1 = new User();

u1.setName("10");

Set<Role> u1Roles = new HashSet<Role>();

u1Roles.add(r1);

u1Roles.add(r2);

u1.setRoles(u1Roles);

User u2 = new User();

u2.setName("祖儿");

Set<Role> u2Roles = new HashSet<Role>();

u2Roles.add(r2);

u2Roles.add(r3);

u2.setRoles(u2Roles);

User u3 = new User();

u3.setName("成龙");

Set<Role> u3Roles = new HashSet<Role>();

u3Roles.add(r1);

u3Roles.add(r2);

u3Roles.add(r3);

u3.setRoles(u3Roles);

session.save(u1);

session.save(u2);

session.save(u3);

tx.commit();

发出SQL语句:

Hibernate: insert into t_role (name) values (?)

Hibernate: insert into t_role (name) values (?)

Hibernate: insert into t_role (name) values (?)

Hibernate: insert into t_user (name) values (?)

Hibernate: insert into t_user (name) values (?)

Hibernate: insert into t_user (name) values (?)

Hibernate: insert into t_user_role (userid, roleid) values (?, ?)

Hibernate: insert into t_user_role (userid, roleid) values (?, ?)

Hibernate: insert into t_user_role (userid, roleid) values (?, ?)

Hibernate: insert into t_user_role (userid, roleid) values (?, ?)

Hibernate: insert into t_user_role (userid, roleid) values (?, ?)

Hibernate: insert into t_user_role (userid, roleid) values (?, ?)

Hibernate: insert into t_user_role (userid, roleid) values (?, ?)

注:前三条SQL语句,添加Role记录,第三条到第六条添加User,最后7条SQL语句是在向第三方表(t_user_role)中添加多对多关系(User与Role关系)

多对多关联映射 单向数据加载:

session = HibernateUtils.getSession();

tx = session.beginTransaction();

User user = (User)session.load(User.class, 1);

System.out.println("user.name=" + user.getName());

for (Iterator<Role> iter = user.getRoles().iterator(); iter.hasNext();){

Role role = (Role) iter.next();

System.out.println(role.getName());

}

//提交事务

tx.commit();

Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_ from t_user user0_ where user0_.id=?

user.name=10

Hibernate: select roles0_.userid as userid1_, roles0_.roleid as roleid1_, role1_.id as id2_0_, role1_.name as name2_0_ from t_user_role roles0_ left outer join t_role role1_ on roles0_.roleid=role1_.id where roles0_.userid=?

商务主管

数据录入人员

时间: 2024-08-28 11:48:50

016 多对多关联映射 单向(many-to-many)的相关文章

一口一口吃掉Hibernate(六)——多对多关联映射

今天来说说hibernate中的多对多关联映射,多对多关联映射涉及到单向映射和双向映射2种. 首先举个多对多关联例子:用户User和角色Role,一个用户可以属于多个角色,一个角色可以有多个用户.这就是典型的多对多关联的例子.而单向关联映射则是只能由A端去操作B端,B端不能操作A端的数据.而双向关联映射则是A,B两端都可以操作另一端的数据. 先说单向关联映射,实体类如下: <span style="font-size:18px">/** * 学生类 * @author Lo

【SSH系列】Hibernate映射 -- 多对多关联映射

     映射原理 在数据库学习阶段,我们知道,如果实体和实体之间的关系是多对多,那么我们就抽出来第三张表,第一张表和第二张表的主键作为第三表的联合主键,结合我们的hibernate,多对多关联,无论是单向关联还是双向关联都是通过第三张表,将两个表中的主键放到第三张表中做一个关联,用第三张表来解决可能造成的数据冗余问题.今天这篇博文小编来简单的介绍一下hibernate中的多对多关联映射. 在某些系统中,一个用户可以有多个角色,一个角色也可以有多个用户,so,她们之间的关系就是多对多,多对多关联

【SSH进阶之路】Hibernate映射——多对多关联映射(八)

上篇博文[SSH进阶之路]Hibernate映射--一对多关联映射(七),我们介绍了一对多关联映射,它是多对多关联映射的基础. 多对多映射是现实生活中最常见的映射,也是最容易理解的映射.废话少说,直接开始. 映射原理 不论是单向关联还是双向关联都是通过第三张表,将两个表中的主键放到第三张做一个关联.用第三张表来解决可能会造成数据冗余的问题. 举例 一个用户(User)对多个角色(Role),一个角色对多个用户. 分类 单向的多对多关联映射(单向User--->Role) 对象模型 关系模型 实例

017 多对多关联映射 双向(many-to-many)

多对多关联映射 双向 两方都持有对象引用,修改对象模型,但数据的存储没有变化. 再修改映射文件: public class Role { private int id; private String name; private Set users;//users对象的集合 public int getUsers() { return users; } public void setUsers(int users) { this.users= users; } public int getId()

014 一对多关联映射 单向(one-to-many)

在对象模型中,一对多的关联关系,使用集合来表示. 实例场景:班级对学生:Classes(班级)和Student(学生)之间是一对多的关系. 多对一.一对多的区别: 多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向一的. 一对多关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是一指向多的. 两者使用的策略是一样的,只是各自所站的角度不同. Classes实体类: public class Classes { private int id; private Stri

Hibernate ManyToOne Mappings 多对一关联映射

Hibernate框架的使用步骤: 1.创建Hibernate的配置文件(hibernate.cfg.xml) 2.创建持久化类,即其实例需要保存到数据库中的类(Employee.java) 3.创建对象-关系映射文件(Employee.hbm.xml) 4.通过Hibernate API编写访问数据库的代码 例子:多个员工对应一个地址. 一.创建hibernate.cfg.xml 配置文件: 注意数据库名.用户名.密码是否填写正确. <?xml version="1.0" en

hibernate多对一关联映射

hibernate多对一关联映射: 实体类 (POJO) public class Student{ private int stuId; private String stuNum; private String stuName; private ClassRoom cr; } public class ClassRoom{ private int claId; private String claName; } 映射文件 <class name=" Student" tabl

hibernate之关于使用连接表实现多对一关联映射

[Hibernate]之关于使用连接表实现多对一关联映射 在我们项目使用中采用中间表最多的一般就是多对一,或者是多对多,当然一对一使用中间表也是可以的,但是这种几率通常少之又少!所以这里重点介绍多对一和一对多的采用中间表进行关联映射! 依然采用Group和Person来描述这个逻辑! Annotations配置 @Entity @Table(name="t_group") publicclass Group {     private Integer id;     private S

hibernate多对一关联映射两种形式的理解

关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 多对一单向和多对一双向关联: 单向:多对一单向是只用维护多的一方,例如一家厂商(Factory)可以生产多种产品(Product),只用在Product实体类和配置文件中配置即可.在Product实体属性类中,需要有Factory属性,而不再需要外键这个属性,因为关联外键的配置在配置文件中many-to-one. 双向:多对一双向关联需要双方都维护对方,例如班级(Class)和学生(Student)之间的关系,需要在Class实体类和