Hibernate的多对多

本文详细介绍了Hibernate中的多对多关联映射,包括创建表结构、实体、映射配置,并探讨了多对多关系的级联保存、删除以及其他相关操作。在多对多关系中,通常一方放弃外键维护权,如角色对于用户的关联。文章还通过实例展示了如何进行级联操作以及如何对多对多关系进行增删改查。
摘要由CSDN通过智能技术生成

1. Hibernate多对多的关联映射案例

1.1 创建表结构

用户表的建表语句:

CREATE TABLE `sys_user` (
	`user_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '用户id',
	`user_code` varchar(32) NOT NULL COMMENT '用户账号',
	`user_name` varchar(64) NOT NULL COMMENT '用户名称',
	`user_password` varchar(32) NOT NULL COMMENT '用户密码',
	`user_state` char(1) NOT NULL COMMENT '1:正常,0:暂停',
	PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

角色表的建表语句:

CREATE TABLE `sys_role` (
	`role_id` bigint(32) NOT NULL AUTO_INCREMENT,
	`role_name` varchar(32) NOT NULL COMMENT '角色名称',
	`role_memo` varchar(128) DEFAULT NULL COMMENT '备注',
	PRIMARY KEY (`role_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

用户角色表的建表语句:

CREATE TABLE `sys_user_role` (
	`role_id` bigint(32) NOT NULL COMMENT '角色id',
	`user_id` bigint(32) NOT NULL COMMENT '用户id',
	PRIMARY KEY (`role_id`,`user_id`),
	KEY `FK_user_role_user_id` (`user_id`),
	CONSTRAINT `FK_user_role_role_id` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`role_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
	CONSTRAINT `FK_user_role_user_id` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

1.2 创建实体

用户的JavaBean代码如下:

public class User {
	private Long user_id;
	private String user_code;
	private String user_name;
	private String user_password;
	private String user_state;
	
	private Set<Role> roles = new HashSet<Role>();
	
	//省略getter和setter方法
}

角色的JavaBean代码如下:

public class Role {
	private Long role_id;
	private String role_name;
	private String role_memo;
	
	private Set<User> users = new HashSet<User>();

	//省略getter和setter方法
}

1.3 创建映射

用户的映射配置文件如下:

<hibernate-mapping>
	<class name="com.joker.domain.User" table="sys_user">
		<id name="user_id" column="user_id">
			<generator class="native"/>
		</id>
		<property name="user_code" column="user_code"/>
		<property name="user_name" column="user_name"/>
		<property name="user_password" column="user_password"/>
		<property name="user_state" column="user_state"/>
		
		<!-- 关联对象的映射的配置 -->
		<!-- 
					set标签:
						* name:关联的另一方的集合的属性名称
						* table:中间表的名称
					key标签:
						* column:当前对象在中间表中的外键的名称
				 	many-to-many标签:
						* class:关联的另一方的类的全路径
						* column:关联的另一方在中间表中的外键名称
				-->
		<set name="roles" table="sys_user_role">
			<key column="user_id"/>
			<many-to-many class="com.joker.domain.Role" column="role_id"/>
		</set>
	</class>
</hibernate-mapping>

角色的映射配置文件如下:

<hibernate-mapping>
	<class name="com.joker.domain.Role" table="sys_role">
		<id name="role_id" column="role_id">
			<generator class="native"/>
		</id>
		<property name="role_name" column="role_name"/>
		<property name="role_memo" column="role_memo"/>
		
		<!-- 关联对象的映射的配置 -->
		<!-- 
					set标签:
						* name:关联的另一方的集合的属性名称
						* table:中间表的名称
					key标签:
						* column:当前对象在中间表中的外键的名称
				 	many-to-many标签:
						* class:关联的另一方的类的全路径
						* column:关联的另一方在中间表中的外键名称
				-->
		<set name="users" table="sys_user_role" inverse="true">
			<key column="role_id"/>
			<many-to-many class="com.joker.domain.User" column="user_id"/>
		</set>
	</class>
</hibernate-mapping>

1.4 将映射添加到配置文件

<mapping resource="com/joker/domain/User.hbm.xml"/>
<mapping resource="com/joker/domain/Role.hbm.xml"/>

1.5 编写测试类

public void test1(){
	Configuration configuration = new Configuration().configure();
	SessionFactory sessionFactory = configuration.buildSessionFactory();
	Session session = sessionFactory.openSession();
	Transaction transaction = session.beginTransaction();
	
	User user1 = new User();
	user1.setUser_name("张三");
	User user2 = new User();
	user2.setUser_name("李四");

	Role role1 = new Role();
	role1.setRole_name("前台");
	Role role2 = new Role();
	role2.setRole_name("人事");
	Role role3 = new Role();
	role3.setRole_name("助理");
	
	//如果多对多建立了双向关联,一定要有一方放弃外键维护权
	user1.getRoles().add(role1);
	user1.getRoles().add(role3);
	user2.getRoles().add(role2);
	user2.getRoles().add(role3);
	role1.getUsers().add(user1);
	role2.getUsers().add(user3);
	role3.getUsers().add(user1);
	role3.getUsers().add(user2);
	
	session.save(user1);
	session.save(user2);
	session.save(rolel);
	session.save(role2);
	session.save(role3);
	
	transaction.commit();
	session.close();
	sessionFactory.close();
}

在多对多的保存操作中,如果进行了双向维护关系,就必须有一方放弃外键维护权。一般由被动方放弃,用户主动选择角色,角色是被选择的,所以一般角色要放弃外键维护权。

将数据保存到数据库了以后,那么多对多会有哪些相关的操作呢?下面将详细介绍多对多的相关的操作。

2. Hibernate多对多的相关操作

2.1 级联保存或更新

之前的博文已经介绍过一对多的级联保存了,那么多对多也是一样的。如果只保存单独的一方是不可以的,还是需要保存双方的。如果就想保存一方就需要设置级联操作了。同样要看保存的主控方是哪一端,就需要在那一端进行配置。

  1. 保存用户级联角色
    保存的主控方是用户,需要在用户一端配置:
    <set name="roles" table="sys_user_role" cascade="save-update">
    	<key column="user_id"/>
    	<many-to-many class="com.joker.domain.Role" column="role_id"/>
    </set>
    
    然后编写测试代码,代码如下:
    public void test2(){
    	Configuration configuration = new Configuration().configure();
    	SessionFactory sessionFactory = configuration.buildSessionFactory();
    	Session session = sessionFactory.openSession();
    	Transaction transaction = session.beginTransaction();
    	
    	User user1 = new User();
    	user1.setUser_name("张三");
    	User user2 = new User();
    	user2.setUser_name("李四");
    
    	Role role1 = new Role();
    	role1.setRole_name("前台");
    	Role role2 = new Role();
    	role2.setRole_name("人事");
    	Role role3 = new Role();
    	role3.setRole_name("助理");
    	
    	//如果多对多建立了双向关联,一定要有一方放弃外键维护权
    	user1.getRoles().add(role1);
    	user1.getRoles().add(role3);
    	user2.getRoles().add(role2);
    	user2.getRoles().add(role3);
    	role1.getUsers().add(user1);
    	role2.getUsers().add(user3);
    	role3.getUsers().add(user1);
    	role3.getUsers().add(user2);
    	
    	session.save(user1);
    	session.save(user2);
    	//session.save(rolel);
    	//session.save(role2);
    	//session.save(role3);
    	
    	transaction.commit();
    	session.close();
    	sessionFactory.close();
    }
    
  2. 保存角色级联用户
    保存的主控方是角色,需要在角色一端配置:
    <set name="users" table="sys_user_role" cascade="save-update" inverse="true">
    	<key column="role_id"/>
    	<many-to-many class="com.joker.domain.User" column="user_id"/>
    </set>
    
    然后编写测试代码,代码如下:
    public void test3(){
    	Configuration configuration = new Configuration().configure();
    	SessionFactory sessionFactory = configuration.buildSessionFactory();
    	Session session = sessionFactory.openSession();
    	Transaction transaction = session.beginTransaction();
    	
    	User user1 = new User();
    	user1.setUser_name("张三");
    	User user2 = new User();
    	user2.setUser_name("李四");
    
    	Role role1 = new Role();
    	role1.setRole_name("前台");
    	Role role2 = new Role();
    	role2.setRole_name("人事");
    	Role role3 = new Role();
    	role3.setRole_name("助理");
    	
    	//如果多对多建立了双向关联,一定要有一方放弃外键维护权
    	user1.getRoles().add(role1);
    	user1.getRoles().add(role3);
    	user2.getRoles().add(role2);
    	user2.getRoles().add(role3);
    	role1.getUsers().add(user1);
    	role2.getUsers().add(user3);
    	role3.getUsers().add(user1);
    	role3.getUsers().add(user2);
    	
    	//session.save(user1);
    	//session.save(user2);
    	session.save(rolel);
    	session.save(role2);
    	session.save(role3);
    	
    	transaction.commit();
    	session.close();
    	sessionFactory.close();
    }
    

级联保存说完了,那么我们来看下级联删除的操作,但是在多对多中级联删除是不会使用的,因为我们不会有这类的需求,比如删除用户,将用户关联的角色一起删除,或者删除角色的时候将用户删除掉。这是不合理的。但是级联删除的功能Hibernate已经提供了该功能。所以我们只需要了解即可。

2.2 级联删除

  1. 删除用户级联角色
    主控方是用户,所以需要在用户一端配置:
    <set name="roles" table="sys_user_role" cascade="delete">
    	<key column="user_id"/>
    	<many-to-many class="com.joker.domain.Role" column="role_id"/>
    </set>
    
    然后编写测试代码,代码如下:
    public void test4(){
    	Configuration configuration = new Configuration().configure();
    	SessionFactory sessionFactory = configuration.buildSessionFactory();
    	Session session = sessionFactory.openSession();
    	Transaction transaction = session.beginTransaction();
    	
    	User user = session.get(User.class, 1l);
    	session.delete(user);
    	
    	transaction.commit();
    	session.close();
    	sessionFactory.close();
    }
    
  2. 删除角色级联用户
    主控方是角色,所以需要在角色一端配置:
    <set name="users" table="sys_user_role" cascade="delete" inverse="true">
    	<key column="role_id"/>
    	<many-to-many class="com.joker.domain.User" column="user_id"/>
    </set>
    
    然后编写测试代码,代码如下:
    public void test5(){
    	Configuration configuration = new Configuration().configure();
    	SessionFactory sessionFactory = configuration.buildSessionFactory();
    	Session session = sessionFactory.openSession();
    	Transaction transaction = session.beginTransaction();
    
    	Role role = session.get(Role.class, 1l);
    	session.delete(role);
    	
    	transaction.commit();
    	session.close();
    	sessionFactory.close();
    }
    

多对多的级联老王就介绍到这了,但是级联并不是主要的操作,我们其实更多的会去使用多对多的一些其他的操作,比如给某个用户选择一个新的角色,或者为某个用户改选已经选好的新角色,或者为某个用户移除某个角色。这些操作是我们以后开发中经常使用的。所以老王就来介绍下如何完成类似的相关的操作。

2.3 多对多的其他操作

其实多对多的关系主要是靠中间表来维护的,那么在Hibernate中多对多主要是靠关联的集合来维护的,所以我们只需要关心如何操作关联的集合即可。那么我们来看下面的几个示例:

  1. 删除某个用户的角色
    public void test6(){
    	Configuration configuration = new Configuration().configure();
    	SessionFactory sessionFactory = configuration.buildSessionFactory();
    	Session session = sessionFactory.openSession();
    	Transaction transaction = session.beginTransaction();
    
    	User user = session.get(User.class, 2l);
    	Role role = session.get(Role.class, 1l);
    	
    	// 操作集合,相当于操作中间表
    	user.getRoles().remove(role);
    	
    	transaction.commit();
    	session.close();
    	sessionFactory.close();
    }
    
  2. 将某个用户的角色改选
    public void test6(){
    	Configuration configuration = new Configuration().configure();
    	SessionFactory sessionFactory = configuration.buildSessionFactory();
    	Session session = sessionFactory.openSession();
    	Transaction transaction = session.beginTransaction();
    
    	User user = session.get(User.class, 2l);
    	Role role1 = session.get(Role.class, 1l);
    	Role role3 = session.get(Role.class, 3l);
    	
    	user.getRoles().remove(role1);
    	user.getRoles().add(role3);
    	
    	transaction.commit();
    	session.close();
    	sessionFactory.close();
    }
    
  3. 给某个用户添加新角色
    public void test6(){
    	Configuration configuration = new Configuration().configure();
    	SessionFactory sessionFactory = configuration.buildSessionFactory();
    	Session session = sessionFactory.openSession();
    	Transaction transaction = session.beginTransaction();
    
    	User user = session.get(User.class, 1l);
    	Role role = session.get(Role.class, 2l);
    	
    	user.getRoles().add(role);
    	
    	transaction.commit();
    	session.close();
    	sessionFactory.close();
    }
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hibernate 多对多关联是指两个实体之间存在多对多的关系。在 Hibernate 中,可以通过使用`@ManyToMany`注解来实现多对多关联。 首先,需要定义两个实体类,假设为`EntityA`和`EntityB`,它们之间存在多对多的关系。 ```java @Entity public class EntityA { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // other fields and mappings @ManyToMany @JoinTable( name = "a_b", joinColumns = @JoinColumn(name = "a_id"), inverseJoinColumns = @JoinColumn(name = "b_id") ) private Set<EntityB> entityBs = new HashSet<>(); // getters and setters } @Entity public class EntityB { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // other fields and mappings @ManyToMany(mappedBy = "entityBs") private Set<EntityA> entityAs = new HashSet<>(); // getters and setters } ``` 在上述代码中,`EntityA`类中使用了`@ManyToMany`注解来表示与`EntityB`的多对多关联。通过`@JoinTable`注解来指定关联表的名称和两个实体之间的外键列。`joinColumns`指定了对应`EntityA`的外键列名,`inverseJoinColumns`指定了对应`EntityB`的外键列名。 在`EntityB`类中,使用了`@ManyToMany(mappedBy = "entityBs")`注解来指定与`EntityA`的关联关系。通过`mappedBy`属性指定了`EntityA`中关联字段的名称。 这样,`EntityA`和`EntityB`之间就建立了多对多的关联。可以通过在代码中操作`entityAs`和`entityBs`集合来实现多对多关联的操作。 同时,还需要在 Hibernate 的配置文件中配置相关的映射信息,以及其他必要的配置。 以上就是 Hibernate 中实现多对多关联的基本步骤,希望能对你有所帮助!如有更多问题,请继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值