目录
一、介绍
二、一对多
① 实体类
②数据库表
③ 配置文件
④测试
三、一对多自关联
① 实体类
② 配置文件
③测试
四、多对多
①实体类
② 配置文件
③测试(查询)
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);
}
如何理解主被控方?删除一本书籍,并不会对它所对应的类别产生影响,只是该类别中少了
一本书,如果是类别被删除,那么还存在该类别的书籍那就不合理了,所有需要先删除该类
别的书籍再删除该类别,能直接删除的为主控方!!!
四、懒加载
@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已关闭的错误,
所以需要强制加载,根据业务需求来加载!



