栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Hibernate关联关系

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Hibernate关联关系

目录

一、介绍

二、一对多

① 实体类

②数据库表

③ 配置文件

④测试

三、一对多自关联

① 实体类

② 配置文件

③测试

 四、多对多

①实体类

② 配置文件

③测试(查询)

inverse属性讲解

 多对多删除

四、懒加载


前言:入门已经学习了如何通过操作对象控制数据,但是仅仅只是单一独立的一张表。表与表之间

还存在主外键的依赖关系!Clazz(班级类)中有一个学生集合属性,通过读取到Clazz班级,就能使

得属于这个班级的学生数据都赋值到该集合中!!!如果放到以前就是要连表查询。

一、介绍

主要还是通过配置文件来建立依赖关系,不仅仅给该表的属性和实体类相互映射,也能使得不同表

(不同实体类)之间的关系也映射出来!

一下多种关系的核心配置,也是Hibernate的配置文件需要配置才能正常使用




	
		




		root
		root123
		jdbc:mysql://127.0.0.1:3306/zwf?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT&useSSL=true
		com.mysql.cj.jdbc.Driver
		org.hibernate.dialect.MySQLDialect
		
 
		
		thread
 
		
		true
		true
		
		
 
		


 
		
 		 
 		 

		
		 
 
		
		 
 		 
	

二、一对多

例子:一个订单下面会有许多订单项,这就是一个典型的一对多关系。一个班级有多个学生!

① 实体类

Order.java

package com.zwf.po;
import java.util.HashSet;
import java.util.Set;
public class Order {
	private Integer orderId;
	private String orderNo;
	
	//注意:变量属性一定用接口进行接受
	private Set orderItems = new HashSet<>();
	
	private Integer initOrderItems = 0;//0代表懒加载,1代表强制加载
	
	public Integer getInitOrderItems() {
		return initOrderItems;
	}
	public void setInitOrderItems(Integer initOrderItems) {
		this.initOrderItems = initOrderItems;
	}
	public Set getOrderItems() {
		return orderItems;
	}
	public void setOrderItems(Set orderItems) {
		this.orderItems = orderItems;
	}
	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;
	}
}

Orderitem.java

package com.zwf.po;
public class OrderItem {
	private Integer orderItemId;
	private Integer productId;
	private Integer quantity;
	private Integer oid;
	
	private Order order;
	public Order getOrder() {
		return order;
	}
	public void setOrder(Order order) {
		this.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;
	}
}

②数据库表

③ 配置文件

Order.hbm.xml





	
		
	
	
	
	
	
	
		 
		
	

 OrderItem.hbm.xml





	
		
	
	
	
	
	
	
	
	
	

④测试

SessionFactory.java(工具类)

package com.zwf.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class SessionFactoryUtil {
	static SessionFactory sessionFactory;
	static {
		Configuration configure = new Configuration().configure("hibernate.cfg.xml");
		sessionFactory = configure.buildSessionFactory();
	}
	public static Session getSession() {
		Session session = sessionFactory.getCurrentSession();
		if(session == null) {
			session = sessionFactory.openSession();
		}
		return session;
	}
	public static void main(String[] args) {
		Session session = SessionFactoryUtil.getSession();
//		Calling method 'isConnected' is not valid without an active transaction (Current status: NOT_ACTIVE)
		session.beginTransaction();
		System.out.println(session.isConnected());
		session.close();
		System.out.println(session.isConnected());
	}
}

OrderDao.java

package com.zwf.dao;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.zwf.po.Order;
import com.zwf.po.OrderItem;
import com.zwf.util.SessionFactoryUtil;
public class OrderDao {
	//查询
	public Order get(Order order) {
		Session session = SessionFactoryUtil.getSession();
		Transaction transaction = session.beginTransaction();
		Order o = session.get(Order.class, order.getOrderId());
//		并且想要查询出关联的订单项的数据是,采用强制加载
		if(o != null && new Integer(1).equals(order.getInitOrderItems())) {
			Hibernate.initialize(o.getOrderItems());
		}
		transaction.commit();
		session.close();
		return o;
	}

	//查询所有
	public List list() {
		Session session = SessionFactoryUtil.getSession();
		Transaction transaction = session.beginTransaction();
		List list = session.createQuery("from Order").list();
		for (Order o: list) {
			Hibernate.initialize(o.getOrderItems());
		}
		transaction.commit();
		session.close();
		return list;
	}

	//删除
	public void delete(Order order) {
		Session session = SessionFactoryUtil.getSession();
		Transaction transaction = session.beginTransaction();
		
		Order o = session.get(Order.class, order.getOrderId());
		for(OrderItem oi:o.getOrderItems()) {
			session.delete(oi);
		}
		session.delete(o);
		
		transaction.commit();
		session.close();
	}
}

大家肯定注意到了有提到懒加载,之后会讲解。

get()和list()唯一的区别是get()需要查询到订单的订单项需要将订单的InitOrderItems属性设置为1。

三、一对多自关联 ① 实体类

TreeVo.java

package com.zwf.Vo;

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

public class TreeVO {
	private int nodeId;
	private String nodeName;
	private int TreeNodeType;
	private int position;
	private String url;
	
	private TreeVO parent;
	private Set children = new HashSet();
	
	public int getNodeId() {
		return nodeId;
	}
	public void setNodeId(int nodeId) {
		this.nodeId = nodeId;
	}
	public String getNodeName() {
		return nodeName;
	}
	public void setNodeName(String nodeName) {
		this.nodeName = nodeName;
	}
	public int getTreeNodeType() {
		return TreeNodeType;
	}
	public void setTreeNodeType(int treeNodeType) {
		TreeNodeType = treeNodeType;
	}
	public int getPosition() {
		return position;
	}
	public void setPosition(int position) {
		this.position = position;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public TreeVO getParent() {
		return parent;
	}
	public void setParent(TreeVO parent) {
		this.parent = parent;
	}
	public Set getChildren() {
		return children;
	}
	public void setChildren(Set children) {
		this.children = children;
	}
	@Override
	public String toString() {
		return "TreeVO [nodeId=" + nodeId + ", nodeName=" + nodeName + ", TreeNodeType=" + TreeNodeType + ", position="
				+ position + ", url=" + url + ", parent=" + parent + ", children=" + children + "]";
	}
	
	
	
}

② 配置文件

TreeVo.hbm.xml


		
			
		
		
		
		
		
		
		
		
		
		
		
		
		
			
			
		
	

③测试
public TreeNode load(TreeNode treeNode) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		TreeNode t = session.load(TreeNode.class, treeNode.getNodeId());
		if(t != null && new Integer(1).equals(treeNode.getInitChildren())) {
			Hibernate.initialize(t.getChildren());
			Hibernate.initialize(t.getParent());
		}
		transaction.commit();
		session.close();
		return t;
	}


@Test
	public void testLoad() {
		TreeNode treeNode = new TreeNode();
		treeNode.setNodeId(6);
		treeNode.setInitChildren(1);
		
		TreeNode t = this.treeNodeDao.load(treeNode);
		System.out.println(t);
		System.out.println(t.getParent());
		System.out.println(t.getChildren());
	}

 四、多对多

案例:一本书籍有多种类别,一个类别也有多本书。

如果书籍表中有类别这个字段,那么要保存每一本数的对应的类别将是一件复杂的事情。这里就会

产生一张中间表。

①实体类

Book.java

package com.zwf.Po;

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

public class Book {
	private int bookId;
	private String bookName;
	private float price;
	
	private Set Categorys = new HashSet();

	public int getBookId() {
		return bookId;
	}

	public void setBookId(int 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 Set getCategorys() {
		return Categorys;
	}

	public void setCategorys(Set categorys) {
		Categorys = categorys;
	}
	
}

Category.java

package com.zwf.Po;

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

public class Category {
	private int categoryId;
	private String categoryName;
	
	Set books = new HashSet();

	public int getCategoryId() {
		return categoryId;
	}

	public void setCategoryId(int categoryId) {
		this.categoryId = categoryId;
	}

	public String getCategoryName() {
		return categoryName;
	}

	public void setCategoryName(String categoryName) {
		this.categoryName = categoryName;
	}

	public Set getBooks() {
		return books;
	}

	public void setBooks(Set books) {
		this.books = books;
	}
	
	
	
}
② 配置文件

		
			
		
		
		
		
		
		
		
			
			
			
			
		
	

		
			
		
		
		
		
		
			
			
		
	

注意:key对应的column不要填反,这里填的是当前类所映射的表的主键,所对应的桥接表中的外

③测试(查询)
public Category getCategory(Category category) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		Category c = session.get(Category.class, category.getCategoryId());
		transaction.commit();
		session.close();
		return c;
	}
	
	public Book getBook(Book book) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		Book b = session.get(Book.class, book.getBookId());
		if (b != null && new Integer(1).equals(book.getInitCategories())) {
			Hibernate.initialize(b.getCategories());
		}
		transaction.commit();
		session.close();
		return b;
	}


@Test
	public void testGetBook() {
		Book book = new Book();
		book.setBookId(1);
		book.setInitCategories(1);
		Book b = this.bookDao.getBook(book );
		System.out.println(b.getBookName());
		System.out.println(b.getCategories());
	}

inverse属性讲解
	@Test
	public void test1() {
		Book book = new Book();
		book.setBookName("b");
		book.setPrice(10f);
		Category category = new Category();
		category.setCategoryId(5);
//		直接将category对象加入到新建的book中是错误的,因为此时的category是临时态的,hibernate是不会管理的
//		book.getCategories().add(category);
		Category c = this.bookDao.getCategory(category);
		
//		c.getBooks().add(book);
		book.getCategories().add(c);
		this.bookDao.addBook(book);
	}

	
	@Test
	public void test2() {
		Book book = new Book();
		book.setBookName("c");
		book.setPrice(10f);
		Category category = new Category();
		category.setCategoryId(5);
		Category c = this.bookDao.getCategory(category);
		
		book.getCategories().add(c);
		this.bookDao.addBook(book);
//		c.getBooks().add(book);
	}
	
	
	@Test
	public void test3() {
		Category category = new Category();
		category.setCategoryName("7");
		Book book = new Book();
		book.setBookId(6);
		Book b = bookDao.getBook(book);
		category.getBooks().add(b);
		this.bookDao.addCategory(category);
		
	}

 多对多删除
public void delBook(Book book) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		session.delete(book);
		transaction.commit();
		session.close();
	}
	
	public void delCategory(Category category) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		Category c = session.get(Category.class, category.getCategoryId());
		if(c!=null) {
			for (Book b : c.getBooks()) {
//				通过在被控方通过主控方来解除关联关系,最后被控方再做删除
				b.getCategories().remove(c);
			}
		}
		session.delete(c);
		transaction.commit();
		session.close();
	}




	@Test
	public void test4() {
		Book book = new Book();
		book.setBookId(3);
		this.bookDao.delBook(book);
	}
	
	@Test
	public void test5() {
		Category category = new Category();
		category.setCategoryId(1);
		this.bookDao.delCategory(category);
	}

如何理解主被控方?删除一本书籍,并不会对它所对应的类别产生影响,只是该类别中少了

一本书,如果是类别被删除,那么还存在该类别的书籍那就不合理了,所有需要先删除该类

别的书籍再删除该类别,能直接删除的为主控方!!!

四、懒加载

Hibernate默认是采用懒加载的,我们需要查询订单时通过懒加载加载出来,对应的订单项并没有

加载。如果数据量大,不采用懒加载会影响性能!为提供性能优化而产生的加载方式。

但是懒加载只能加载单表的数据对象,再加载关联表的数据对象时会产生session已关闭的错误,

所以需要强制加载,根据业务需求来加载!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/337018.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号