hibernate一对多,多对多

关联

什么是关联(association)
关联指的是类之间的引用关系。如果类A与类B关联,那么被引用的类B将被定义为类A的属性

 public class A{
        private B b = new B;
        public A(){}
     }

关联的分类:
关联可以分为一对一、一对多/多对一、多对多关联
没有固定对象
关联有方向

  • 一对一:比如一对一家教

  • 一对多: 比如平常学校里的教学老师与学生的关系

  • 多对一:比如一个人有很多种角色,但本质上还是这个人

  • 多对多:可以理解为多个人对多种事物的看法

一对多实例

代码

首先看需要哪些类/包
在这里插入图片描述
数据库脚本

-- 订单表(主表)
create table t_order_hb
(
  order_id int primary key auto_increment,  
  order_no varchar(50) not null             
);


-- 订单项表(从表)
create table t_order_item_hb
(
  order_item_id int primary key auto_increment,
  product_id int not null,
  quantity int not null,
  oid int not null,
  foreign key(oid) references t_order_hb(order_id)
);

第一步
配置需要的jar包依赖以及工具类
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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.solar</groupId>
  <artifactId>hibernate</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>maven Maven Webapp</name>
  <url>http://maven.apache.org</url>
  
  
 <properties>
  	<servlet.version>4.0.1</servlet.version>
  	<junit.version>3.8.1</junit.version>
  	<mysql.version>5.1.44</mysql.version>
  	<jstl.version>1.2</jstl.version>
  	<standard.version>1.1.2</standard.version>
  	<tomcat.version>8.5.38</tomcat.version>
  	<hibernate.version>5.2.12.Final</hibernate.version>
  	
  </properties>
  
  
  
  <dependencies>
  <!-- hibernate -->
	<dependency>
	    <groupId>org.hibernate</groupId>
	    <artifactId>hibernate-core</artifactId>
	    <version>${hibernate.version}</version>
	</dependency>
  
  <!-- tomcat-jsp-api -->
    <dependency>
	    <groupId>org.apache.tomcat</groupId>
	    <artifactId>tomcat-jsp-api</artifactId>
	    <version>${tomcat.version}</version>
	</dependency>
  
  <!-- standard -->
  	<dependency>
	    <groupId>taglibs</groupId>
	    <artifactId>standard</artifactId>
	    <version>${standard.version}</version>
	</dependency>
  
  
  <!-- jstl -->
  	<dependency>
	    <groupId>javax.servlet</groupId>
	    <artifactId>jstl</artifactId>
	    <version>${jstl.version}</version>
	</dependency>
  
    <!-- junit -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
      <scope>provided</scope>
    </dependency>
    
    <!-- servlet -->
    
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>${servlet.version}</version>
      <scope>provided</scope>
    </dependency>
    
    <!-- mysql -->
    
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql.version}</version>
    </dependency>
    
  </dependencies>
  <build>
    <finalName>maven</finalName>
    <plugins>
    	<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-compiler-plugin</artifactId>
			<version>3.7.0</version>
			<configuration>
				<source>1.8</source>
				<target>1.8</target>
				<encoding>UTF-8</encoding>
			</configuration>
		</plugin>
    </plugins>
  </build>
</project>

SessionFactoryUtils工具类

package com.solar.util;

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

public class SessionFactoryUtils {

	private static final String 
			HIBERNATE_CONFIG_FILE="hibernate.cfg.xml";
	
	private static ThreadLocal<Session> threadLocal=
			new ThreadLocal<Session>();
	
	//创建数据库的会话工厂
	private static SessionFactory sessionFactory;
	
	//读取hibernate核心配置
	private static Configuration configuration;
	
	static {
		try {
			configuration=new Configuration();
			configuration.configure(HIBERNATE_CONFIG_FILE);
			//创建Session会话工厂
			sessionFactory=configuration.buildSessionFactory();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static Session openSession() {
		Session session = threadLocal.get();
		if(null==session) {
			session=sessionFactory.openSession();
			threadLocal.set(session);
		}
		return session;
	}
	
	public static void closeSession() {
		Session session = threadLocal.get();
		if(null!=session) {
			if(session.isOpen())
				session.close();
			threadLocal.set(null);
		}
	}
	
	public static void main(String[] args) {
		Session session = SessionFactoryUtils.openSession();
		System.out.println("Session状态:"+session.isOpen());
		System.out.println("Session会话已打开");
		SessionFactoryUtils.closeSession();
		System.out.println("Session会话已关闭");
	}
}

第二步
两个实体类
Order

package com.solar.entity;

import java.io.Serializable;
import java.util.HashSet;
/**
 * 数据库订单表的实体类
 * @author SOLAR
 *202081408:39:18
 */
import java.util.Set;
public class Order implements Serializable{
	private Integer orderId;
	private String orderNo;
	
	//建立实体类之间的关联关系(一对多所以使用集合来存储)
	private Set<OrderItem> items=new HashSet<OrderItem>();
	
	
	
	public Set<OrderItem> getItems() {
		return items;
	}
	public void setItems(Set<OrderItem> items) {
		this.items = items;
	}
	public Integer getOrderId() {
		return orderId;
	}
	public void setOrderId(Integer orderId) {
		this.orderId = orderId;
	}
	public String getOrderNo() {
		return orderNo;
	}
	public void setOrderNo(String orderNo) {
		this.orderNo = orderNo;
	}
	public Order() {}
	public Order(Integer orderId, String orderNo) {
		super();
		this.orderId = orderId;
		this.orderNo = orderNo;
	}
	
	public Order(Integer orderId, String orderNo, Set<OrderItem> items) {
		super();
		this.orderId = orderId;
		this.orderNo = orderNo;
		this.items = items;
	}
	@Override
	public String toString() {
		return "Order [orderId=" + orderId + ", orderNo=" + orderNo + ", items=" + items + "]";
	}
	
	
}

OrderItem

package com.solar.entity;

import java.io.Serializable;

public class OrderItem implements Serializable {
	private Integer orderItemId;
	private Integer productId;
	private Integer quantity;
	private Integer oid;
	private Order order;
	public Integer getOrderItemId() {
		return orderItemId;
	}
	public void setOrderItemId(Integer orderItemId) {
		this.orderItemId = orderItemId;
	}
	public Integer getProductId() {
		return productId;
	}
	public void setProductId(Integer productId) {
		this.productId = productId;
	}
	public Integer getQuantity() {
		return quantity;
	}
	public void setQuantity(Integer quantity) {
		this.quantity = quantity;
	}
	public Integer getOid() {
		return oid;
	}
	public void setOid(Integer oid) {
		this.oid = oid;
	}
	public Order getOrder() {
		return order;
	}
	public void setOrder(Order order) {
		this.order = order;
	}
	@Override
	public String toString() {
		return "OrderItem [orderItemId=" + orderItemId + ", productId=" + productId + ", quantity=" + quantity
				+ ", oid=" + oid + ", order=" + order + "]";
	}
	
	
}

第三步
配置hibernate核心配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		<!-- 数据库相关配置 -->
			<!-- 连接账户名称 -->
				<property name="connection.username">root</property>
			<!-- 连接密码 -->
				<property name="connection.password"></property>
			<!-- 连接的绝对路径 -->
				<property name="connection.url">
					jdbc:mysql://localhost/peach?useUnicode=true&amp;characterEncoding=UTF-8&amp;userSSL=false
				</property>
			<!-- 驱动的绝对路径 -->
				<property name="connection.driver_class">
					com.mysql.jdbc.Driver
				</property>
			<!-- 数据库方言-->
				<property name="dialect">
					org.hibernate.dialect.MySQLDialect
				</property>
		<!-- 调试相关配置  -->
			<!-- hibernate运行过程是否展示自动生成的代码 -->
				<property name="show_sql">true</property>
			<!-- 是否规范化输出sql代码 -->
				<property name="format">true</property>
		<!-- 实体映射相关配置 -->
			<mapping resource="com/solar/entity/Order.hbm.xml"/>
			<mapping resource="com/solar/entity/OrderItem.hbm.xml"/>
	</session-factory>
</hibernate-configuration>

第四步
配置两个实体类相对的映射文件
Order.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<!-- 
		name:实体类的全路径名
		table:实体类对应的数据库表名称
	 -->
	<class name="com.solar.entity.Order" table="t_order_hb">
		<!-- id:用于设置数据库结构中主键列的生成方式
			name:实体类中属性名称
			type:java中的数据类型
			colunm:数据库表字段名称
		 -->
		<id name="orderId" type="java.lang.Integer" column="order_id">
			<generator class="increment"></generator>
		</id>
		<property name="orderNo" type="java.lang.String" column="order_no"></property>
		<!-- 建立映射的关联关系 (尽量不用)-->
		<!-- name:当前映射文件实体类的集合属性名
			cascade:标明级联操作
			inverse:是否执行级联操作
		-->
		<set name="items" cascade="save-update" inverse="true" >
			<!-- colnum:指向用什么字段关联从表 -->
			<key column="oid"></key>
			<!-- class:从表的实体类全路径名 -->
			<one-to-many class="com.solar.entity.OrderItem"/>
		</set>
	</class>
</hibernate-mapping>

OrderItem.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<!-- 
		name:实体类的全路径名
		table:实体类对应的数据库表名称
	 -->
	<class name="com.solar.entity.OrderItem" table="t_order_item_hb">
		<!-- id:用于设置数据库结构中主键列的生成方式
			name:实体类中属性名称
			type:java中的数据类型
			colunm:数据库表字段名称
		 -->
		<id name="orderItemId" type="java.lang.Integer" column="order_item_id">
			<generator class="increment"></generator>
		</id>
		<property name="productId" type="java.lang.Integer" column="product_id"></property>
		<property name="quantity" type="java.lang.Integer" column="quantity"></property>
		<property insert="false" update="false" name="oid" type="java.lang.Integer" column="oid"></property>
		
		<!-- 建立关联关系 -->
		<many-to-one name="order"
			cascade="save-update"
			column="oid"
			class="com.solar.entity.Order">
		</many-to-one>
	</class>
</hibernate-mapping>

第五步
测试dao方法是否成功运行

package com.solar.dao;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.solar.entity.Order;
import com.solar.entity.OrderItem;

public class OrderDaoTest {
	Order order=null;
	OrderItem orderItem=null;
	OrderDao od=new OrderDao();
	
	@Before
	public void setUp() throws Exception {
		order=new Order();
		
	}


	@Test
	public void testAddOrder() {
		order.setOrderNo("p20200724");
		for (int i = 0; i < 3; i++) {
			orderItem=new OrderItem();
			orderItem.setProductId(i+1);
			orderItem.setQuantity(i+2);
			orderItem.setOrder(order);
			order.getItems().add(orderItem);
		}
		od.addOrder(order);
		
	}

}

效果展示

控制台显示
在这里插入图片描述
数据库
根据上面填的数据可以看到数据库被增加了数据
订单表(t_order_hb)
在这里插入图片描述
订单项表(t_order_item_hb)
订单的id是2
所有这里订单项对应的三条数据的oid都是2
在这里插入图片描述
一般级联项目在真实项目中是不用的

多对多实例

映射多对多关联关系(看作两个一对多)
多对多关系一定要定义一个主控方
多对多删除需要主控方直接删除然后被控方先通过主控方解除多对多关系再删除被控方
禁用级联删除
下面的案例是一本书对应多个类别,一个类别对应多本书的之间的映射关系
首先
使用到的数据库脚本

-- 书本类别表
create table t_category_hb
(
   category_id int primary key auto_increment,
   category_name varchar(50) not null
);

-- 书本表
create table t_book_hb
(
   book_id int primary key auto_increment,
   book_name varchar(50) not null,
   price float not null
);


-- 桥接表
-- 定义三个列,其实只要两个列
-- 一个类别对应多本书,一本书对应多个类别
CREATE TABLE t_book_category_hb
(
  bcid INT PRIMARY KEY AUTO_INCREMENT,  
  bid INT NOT NULL,
  cid INT NOT NULL,
  FOREIGN KEY(bid) REFERENCES t_book_hb(book_id),
  FOREIGN KEY(cid) REFERENCES t_category_hb(category_id)
);


插入数据

insert into t_book_hb(book_id, book_name, price) values(1,'西游记',50);
insert into t_book_hb(book_id, book_name, price) values(2,'红楼梦',50);
insert into t_book_hb(book_id, book_name, price) values(3,'水浒',50);
insert into t_book_hb(book_id, book_name, price) values(4,'三国演义',50);


insert into t_category_hb(category_id, category_name) values(1,'古典');
insert into t_category_hb(category_id, category_name) values(2,'神话');
insert into t_category_hb(category_id, category_name) values(3,'历史');


insert into t_book_category_hb(bid, cid) values(1,1);
insert into t_book_category_hb(bid, cid) values(1,2);
insert into t_book_category_hb(bid, cid) values(2,1);
insert into t_book_category_hb(bid, cid) values(3,1);
insert into t_book_category_hb(bid, cid) values(3,3);
insert into t_book_category_hb(bid, cid) values(4,1);
insert into t_book_category_hb(bid, cid) values(4,3);

数据库表效果
在这里插入图片描述
实体类
Book

package com.solar.entity;

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

public class Book implements Serializable{
	private Integer bookId;
	private String bookName;
	private Float price;
	
	Set<Category> categories=new HashSet<Category>();
	
	public Set<Category> getCategories() {
		return categories;
	}
	public void setCategories(Set<Category> categories) {
		this.categories = categories;
	}
	public Integer getBookId() {
		return bookId;
	}
	public void setBookId(Integer bookId) {
		this.bookId = bookId;
	}
	public String getBookName() {
		return bookName;
	}
	public void setBookName(String bookName) {
		this.bookName = bookName;
	}
	public Float getPrice() {
		return price;
	}
	public void setPrice(Float price) {
		this.price = price;
	}
	public Book() {
		
	}
	public Book(Integer bookId, String bookName, Float price) {
		
		this.bookId = bookId;
		this.bookName = bookName;
		this.price = price;
	}
	@Override
	public String toString() {
		return "Book [bookId=" + bookId + ", bookName=" + bookName + ", price=" + price + ", categories=" + categories
				+ "]";
	}
	
}

Category

package com.solar.entity;

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

public class Category implements Serializable {
	private Integer categoryId;
	private String categoryName;
	
	Set<Book> books=new HashSet<Book>();
	
	
	public Set<Book> getBooks() {
		return books;
	}
	public void setBooks(Set<Book> books) {
		this.books = books;
	}
	public Integer getCategoryId() {
		return categoryId;
	}
	public void setCategoryId(Integer categoryId) {
		this.categoryId = categoryId;
	}
	public String getCategoryName() {
		return categoryName;
	}
	public void setCategoryName(String categoryName) {
		this.categoryName = categoryName;
	}
	public Category() {
		
	}
	public Category(Integer categoryId, String categoryName) {
		
		this.categoryId = categoryId;
		this.categoryName = categoryName;
	}
	@Override
	public String toString() {
		return "Category [categoryId=" + categoryId + ", categoryName=" + categoryName + ", books=" + books + "]";
	}
	
}

对应的映射文件
Book.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
   <class name="com.solar.entity.Book" table="t_book_hb">
     <id name="bookId" type="java.lang.Integer" column="book_id">
      <generator class="increment"></generator>
    </id>
     <property   name="bookName"   type="java.lang.String"   column="book_name"></property>
     <property   name="price"      type="java.lang.Float"    column="price"></property>
    <!-- 多对多映射关系 -->
    <!--
         name:一方包含多方的属性对象名称 指向多方
         cascade:级联操作   save-update/none/all=delete+save-update
         inverse:是否是主控方  false表示对方不是主控方
                 true表示对方是主控方 由对方来维护中间表
         table:表示中间表的名称
       -->
    <set name="categories"
         cascade="save-update"
         inverse="false"
         table="t_book_category_hb"
         >
         <!--column:指向己方在中间表的外键字段 -->
         <key column="bid"></key>
            <!-- class:对方实例的完整路径
                 column:对方在中间表中的外键字段
             -->
          <many-to-many 
             class="com.solar.entity.Category"
             column="cid">
          </many-to-many>
    </set>
   </class>
</hibernate-mapping>

Category.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
   <class name="com.solar.entity.Category" table="t_category_hb">
     <id name="categoryId" type="java.lang.Integer" column="category_id">
      <generator class="increment"></generator>
    </id>
     <property   name="categoryName"   type="java.lang.String"   column="category_name"></property>
     <set name="books"
         cascade="save-update"
         inverse="true"
         table="t_book_category_hb">
         <key column="cid"></key>
          <many-to-many 
             class="com.solar.entity.Book"
             column="bid">
          </many-to-many>
    </set>
   </class>
</hibernate-mapping>

dao方法
BookDao

package com.solar.dao;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.solar.entity.Book;
import com.solar.util.SessionFactoryUtils;
/**
 * 书籍的dao方法
 * @author Administrator
 *
 */
public class BookDao {
	public  void  addBook(Book book) {
		  Session session = SessionFactoryUtils.openSession();
		  Transaction ts = session.beginTransaction();
	      session.save(book);
		  ts.commit();
	      SessionFactoryUtils.closeSession();
	  }	
}

CategoryDao

package com.solar.dao;

import org.hibernate.Session;
import org.hibernate.Transaction;
import com.solar.entity.Category;
import com.solar.util.SessionFactoryUtils;

/**
 * Category的dao方法
 *  @author solar
 *  
 */
public class CategoryDao {

  public  Category  getCategoryById(Category category) {
	  Session session = SessionFactoryUtils.openSession();
	  Transaction ts = session.beginTransaction();
	  //根据对象和id获取
	  Category c = session.get(Category.class,category.getCategoryId());
	  
	  ts.commit();
      SessionFactoryUtils.closeSession();
      return  c;//返回查询后的结果集
  }
}

测试dao方法
BookDao测试

package com.solar.dao;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

import com.solar.entity.Book;
import com.solar.entity.Category;

public class BookDaoTest {
	BookDao bookDao=new BookDao();
	Book book=null;
	@Before
	public void setUp() throws Exception {
		book=new Book();
	}

	@Test
	public void testAddBook() {
		book.setBookName("格林童话");
		book.setPrice(100f);
		
		Category  category=new Category();
		category.setCategoryName("童话");
		
		Category  category1=new Category();
		category1.setCategoryName("散文");
		
	    book.getCategories().add(category);
	    book.getCategories().add(category1);
		
	    category.getBooks().add(book);
	    category1.getBooks().add(book);
	    
	    bookDao.addBook(book);  
	}

}

CategoryDao测试

package com.solar.dao;

import com.solar.entity.Book;
import com.solar.entity.Category;
import junit.framework.TestCase;

public class CategoryDaoTest extends TestCase {
     
	CategoryDao  categoryDao=null;
	BookDao      bookDao=new BookDao();
	
	
	protected void setUp() throws Exception {
	   categoryDao=new CategoryDao();
	}

	public void testGetCategoryById() {
	   Book  book=new Book();
	   book.setBookName("猫和老鼠");
	   book.setPrice(100f);
	   
	   Category   category=new Category();
	   category.setCategoryId(2);
	   Category c = categoryDao.getCategoryById(category);
	   
	   book.getCategories().add(c);
	   bookDao.addBook(book);
	
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值