Hibernate关联关系之多对多关联关系的CRUD操作

备注:本文有参考hibernate多对多关系配置--增删改查

==========================================================

==========================================================

1.项目结构:

========================

2.pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.lin</groupId>
  <artifactId>Hibernate_ManyToMany</artifactId>
  <version>0.0.1-SNAPSHOT</version>

<dependencies>
		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>3.6.10.Final</version>
		</dependency>
		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-entitymanager</artifactId>
		    <version>3.6.10.Final</version>
		</dependency>

		<!-- MySQL驱动包 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.41</version>
		</dependency>
		
		<!-- slf4j -->
		<dependency>
		    <groupId>org.slf4j</groupId>
		    <artifactId>slf4j-nop</artifactId>
		    <version>1.7.25</version>
		    <scope>test</scope>
		</dependency>
		
		
		<!-- jstl、servlet-api、junit -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit-dep</artifactId>
			<version>4.10</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

</project>

========================

3.实体类和映射文件

Person.java

package com.lin.domain;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
/**
 * 人 实体类
 * */
public class Person implements Serializable {
	private static final long serialVersionUID = 1L;
	
	private Long personId;
	private String personName;
	private String password;
	
	//一个人可以有多个地址,一个地址可以对应多个人。所以 人跟地址 是多对多的关联关系。
	private Set<Address> addresss = new HashSet<Address>(0);
	
	public Person() {
		super();
	}
	public Person(Long personId, String personName, String password) {
		super();
		this.personId = personId;
		this.personName = personName;
		this.password = password;
	}
	
	public Long getPersonId() {
		return personId;
	}
	public void setPersonId(Long personId) {
		this.personId = personId;
	}
	public String getPersonName() {
		return personName;
	}
	public void setPersonName(String personName) {
		this.personName = personName;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public Set<Address> getAddresss() {
		return addresss;
	}
	public void setAddresss(Set<Address> addresss) {
		this.addresss = addresss;
	}
	
	@Override
	public String toString() {
		return "Person [personId=" + personId + ", personName=" + personName
				+ ", password=" + password + "]";
	}
	
}

Person.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.lin.domain">
	
	<!-- name指定持久化类的类名,table指定数据表的表名 -->
	<class name="Person" table="table_person">
		<id name="personId" column="person_id">
			<generator class="native"/>
		</id>
		<property name="personName" column="person_name"></property>
		<property name="password" column="password"></property>
		
		<!--映射集合属性,关联到持久化类,table="table_person_address"指定了中间表的名字-->
		<set name="addresss" table="table_person_address" inverse="true">
			<key>
				<!--column属性指定中间表中关联当前实体类的列名-->
				<column name="person_id"/>
			</key>
			<!--column属性指定中间表中关联本实体的外键-->
			<many-to-many class="Address" column="address_id"/>
		</set>
		
	</class>
	
</hibernate-mapping>

Address.java

package com.lin.domain;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public class Address implements Serializable{
	private static final long serialVersionUID = 1L;

	private Long addressId;
	private String addressInfo;
	
	//一个地址可以对应多个人,一个人可以有多个地址。所以 地址跟人 是多对多的关联关系。
	private Set<Person> persons = new HashSet<Person>(0);

	public Address() {
		super();
	}
	public Address(Long addressId, String addressInfo) {
		super();
		this.addressId = addressId;
		this.addressInfo = addressInfo;
	}
	
	public Long getAddressId() {
		return addressId;
	}
	public void setAddressId(Long addressId) {
		this.addressId = addressId;
	}
	public String getAddressInfo() {
		return addressInfo;
	}
	public void setAddressInfo(String addressInfo) {
		this.addressInfo = addressInfo;
	}
	public Set<Person> getPersons() {
		return persons;
	}
	public void setPersons(Set<Person> persons) {
		this.persons = persons;
	}
	
	@Override
	public String toString() {
		return "Address [addressId=" + addressId + ", addressInfo="
				+ addressInfo + "]";
	}
	
}

Address.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.lin.domain">
	
	<!-- name指定持久化类的类名,table指定数据表的表名 -->
	<class name="Address" table="table_address">
		<id name="addressId" column="address_id">
			<generator class="native"/>
		</id>
		<property name="addressInfo" column="address_info"></property>
		
		<!--映射集合属性,关联到持久化类,table="table_person_address"指定了双向多对多映射中间表的名字-->
		<set name="persons" table="table_person_address">
			<key>
				<!--column属性指定中间表中关联当前实体类的列名-->
				<column name="address_id"/>
			</key>
			<!--column属性指定中间表中关联本实体的外键-->
			<many-to-many class="Person" column="person_id"/>
		</set>
		
	</class>
	
</hibernate-mapping>

========================

4.Hibernate配置文件hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<!-- 
	Hibernate配置文件包含了连接持久层与映射文件所需的基本信息。
	(Hibernate配置文件主要用来配置数据库连接以及Hibernate运行时所需的各个属性的值。)

 -->
	
<hibernate-configuration>

	<session-factory>
		<!-- 数据库连接设置 -->
		<!-- 配置数据库JDBC驱动 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<!-- 配置数据库连接URL -->
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property>
		<!-- 配置数据库用户名 -->
		<property name="hibernate.connection.username">root</property>
		<!-- 配置数据库密码 -->
		<property name="hibernate.connection.password">000000</property>
		<!-- 配置JDBC内置连接池 -->
		<property name="connection.pool_size">1</property>
		<!-- 配置数据库方言 -->
		<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
		<!-- 配置Hibernate采用何种方式生成DDL语句 -->
		<!-- update表示检测实体类的映射配置和数据库的表结构是否一致 -->
		<property name="hibernate.hbm2ddl.auto">update</property>		
		<!-- 输出运行时生成的SQL语句 -->
		<property name="show_sql">true</property>
		
		<!-- 列出所有的映射文件 -->
		<mapping resource="hibernate/mappings/Person.hbm.xml" />
		<mapping resource="hibernate/mappings/Address.hbm.xml" />
	</session-factory>

</hibernate-configuration>

========================

5.Hibernate工具类

package com.lin.utils;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

	private static SessionFactory sessionFactory;
	private static Configuration configuration;
	//创建线程局部变量threadLocal,用来保存Hibernate的Session
	private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
	
	//使用静态代码块初始化Hibernate
	static{
		try{
			//如果不指定hibernate的配置文件位置,那么它会默认到classpath路径下查找名为hibernate.cfg.xml的文件
			Configuration cfg = new Configuration().configure("/hibernate/hibernate.cfg.xml");
			//创建SessionFactory
			sessionFactory = cfg.buildSessionFactory();
		}catch(Throwable ex){
			throw new ExceptionInInitializerError(ex);
		}
	}
	
	//获得SessionFactory
	public static SessionFactory getSessionFactory(){
		return sessionFactory;
	}
	
	
	//获得ThreadLocal对象管理的Session实例
	public static Session getSession() throws HibernateException {
		Session session = (Session)threadLocal.get();
		if(session == null || session.isOpen()){
			if(sessionFactory == null){
				rebuildSessionFactory();
			}
			//通过SessionFactory对象创建Session对象
			session = (sessionFactory != null)?sessionFactory.openSession():null;
			//将新打开的Session实例保存到线程局部变量threadLocal中
			threadLocal.set(session);
		}
		
		return session;
	}
	
	//关闭Session实例
	public static void closeSession() throws HibernateException {
		//从线程局部变量threadLocal中获取之前存入的Session实例
		Session session = (Session)threadLocal.get();
		threadLocal.set(null);
		if(session != null){
			session.close();
		}
	}
	
	
	//重建SessionFactory
	public static void rebuildSessionFactory() {
		try{
			configuration.configure("/hibernate/hibernate.cfg.xml");
			sessionFactory = configuration.buildSessionFactory();
		}catch(Exception e){
			System.out.println("Error Creating SessionFactory ");
			e.printStackTrace();
		}
	}
	
	
	//关闭缓存和连接池
	public static void shutdown(){
		getSessionFactory().close();
	}
	
	public static void main(String[] args){
		HibernateUtil.getSession();
	}
}

========================

6.测试类

①保存操作

/**
	 * 保存操作
	 * */
	@Test
	public void saveTest(){
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		Person person1 = new Person();
		person1.setPersonName("林1");
		person1.setPassword("111111");
		
		Person person2 = new Person();
		person2.setPersonName("林2");
		person2.setPassword("222222");
		
		Address address1 = new Address();
		address1.setAddressInfo("地址1");
		
		Address address2 = new Address();
		address2.setAddressInfo("地址2");
		
		Address address3 = new Address();
		address3.setAddressInfo("地址3");
		
		//注意,这里是双向关联,所以人要添加地址,地址也要关联人
		person1.getAddresss().add(address1);
		person1.getAddresss().add(address2);
		
		person2.getAddresss().add(address2);
		person2.getAddresss().add(address3);
		
		address1.getPersons().add(person1);
		address2.getPersons().add(person1);
		address2.getPersons().add(person2);
		address3.getPersons().add(person2);
		
		
		//地址或人,谁先保存都可以
		session.save(address1);
		session.save(address2);
		session.save(address3);
		
		session.save(person1);
		session.save(person2);
		
		tx.commit();
		session.close();
	}

测试结果:

②CRUD测试操作

package com.lin.test;

import java.util.Set;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.lin.domain.Address;
import com.lin.domain.Person;
import com.lin.utils.HibernateUtil;

/**
 * 多对多关联关系的CRUD操作
 * */
public class HibernateManyToManyTest {

	/**
	 * 保存操作。
	 * */
	@Test
	public void saveTest(){
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		Person person1 = new Person();
		person1.setPersonName("林1");
		person1.setPassword("111111");
		
		Person person2 = new Person();
		person2.setPersonName("林2");
		person2.setPassword("222222");
		
		Address address1 = new Address();
		address1.setAddressInfo("地址1");
		
		Address address2 = new Address();
		address2.setAddressInfo("地址2");
		
		Address address3 = new Address();
		address3.setAddressInfo("地址3");
		
		//注意,这里是双向关联,所以人要添加地址,地址也要关联人
		person1.getAddresss().add(address1);
		person1.getAddresss().add(address2);
		
		person2.getAddresss().add(address2);
		person2.getAddresss().add(address3);
		
		address1.getPersons().add(person1);
		address2.getPersons().add(person1);
		address2.getPersons().add(person2);
		address3.getPersons().add(person2);
		
		
		//地址或人,谁先保存都可以
		session.save(address1);
		session.save(address2);
		session.save(address3);
		
		session.save(person1);
		session.save(person2);
		
		tx.commit();
		session.close();
	}
	
	/**
	 * 删除操作 。
	 * */
	@Test
	public void deleteTest(){
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		Person person = (Person) session.get(Person.class, 1L);
		//如果有关联关系,那么需先将关联关系删掉才行
		Set<Address> addresss = person.getAddresss();
		for(Address address: addresss){
			address.getPersons().remove(person);
		}
		
		session.delete(person);
		
		tx.commit();
		session.close();
	}
	
	/**
	 * 更新操作。
	 * 更新本张表。
	 * */
	@Test
	public void updateTest(){
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		Person person = (Person) session.get(Person.class, 2L);
		person.setPersonName("小林111");
		
		session.update(person);
		
		tx.commit();
		session.close();
	}
	
	/**
	 * 更新操作。
	 * 更新关联表。
	 * */
	@Test
	public void updateTest2(){
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		Person person = (Person) session.get(Person.class, 2L);
		//下面的这个地址跟这个人是没有关联关系的,但是我执行更新操作后还是可以正常更新地址数据
//		Address address = (Address) session.get(Address.class, 1L);
//		address.setAddressInfo("泉州111");
		Address address = (Address) session.get(Address.class, 2L);
		address.setAddressInfo("泉州222");
		person.getAddresss().add(address);
		
		session.update(person);
		
		tx.commit();
		session.close();
	}
	
	/**
	 * 查询操作。
	 * */
	@Test
	public void selectTest(){
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		Person person = (Person) session.get(Person.class, 2L);
		System.out.println(person);
		
		Set<Address> addresss = person.getAddresss();
		System.out.println(addresss);
		
		tx.commit();
		session.close();
	}
}

总结:从双向的一对多,到双向的一对一、再到双向的多对多。最关键的就是实体类与数据表的映射关系xxx.hbm.xml。然后最最重要的还是双向的一对多关联映射超详细的Hibernate关联关系之双向的一对多关联关系的CRUD操作————学习至黑马程序员视频教程,这篇博文是从视屏教程上面照着代码敲出来的,这个好好理解一下应该问题就不大了。剩下的两个一对一, 多对多,这个是我自己经过百度、参看书上的内容以及参考上面提到的博文做出的测试,里面功能上大概都有涉及到,但是不管从知识点还是注解上都相对没有那么详细。所以一些写的不对的地方欢迎大神指教。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值