Hibernate多對多的雙向關聯
阿新 • • 發佈:2018-12-18
Hibernate多對多關係:可以看作是兩個一對多,比如書籍與類別,書籍可以有多個類別,類別下可以有多本書籍
既然多對多可以看作兩個一對多,那麼維護只能交給一方進行維護,比如我做級聯新增時,如果雙方都維護,就會造成資料重複
準備:
SessionFactoryUtils類:用來管理session
package com.zking.util; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; /** * 1.方便獲取session會話,用來操作資料庫 * 2.用來檢驗所有對映的配置檔案是否準確 * @author Li Jin Guo */ public class SessionFactoryUtils { private static SessionFactory sessionFactory; static { Configuration cfg = new Configuration().configure("hibernate.cfg.xml"); sessionFactory = cfg.buildSessionFactory(); } public static Session getSession() { Session session = sessionFactory.getCurrentSession(); if (session == null) { session = sessionFactory.openSession(); } return session; } public static void closeSession() { Session session = sessionFactory.getCurrentSession(); if (session != null && session.isOpen()) { session.close(); } } public static void main(String[] args) { Session session = SessionFactoryUtils.getSession(); session.beginTransaction(); System.out.println(session.isConnected()); SessionFactoryUtils.closeSession(); System.out.println(session.isConnected()); } }
Book類:
package com.study.entity; import java.util.HashSet; import java.util.Set; public class Book { private Integer bookId; private String bookName; private Float price; private Set<Category> categorys = new HashSet<Category>(); private Integer initCategorys;//懶載入控制 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 Set<Category> getCategorys() { return categorys; } public void setCategorys(Set<Category> categorys) { this.categorys = categorys; } public Integer getInitCategorys() { return initCategorys; } public void setInitCategorys(Integer initCategorys) { this.initCategorys = initCategorys; } }
Book類的對映檔案:
<?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 table="t_hibernate_book" name="com.study.entity.Book"> <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> <set table="t_hibernate_book_category" name="categorys" cascade="save-update" inverse="false"> <key column="bid"></key> <many-to-many column="cid" class="com.study.entity.Category"/> </set> </class> </hibernate-mapping>
Category類:
package com.study.entity;
import java.util.HashSet;
import java.util.Set;
public class Category {
private Integer category_Id;
private String categoryName;
private Set<Book> books = new HashSet<Book>();
private Integer initBook;
public Integer getCategory_Id() {
return category_Id;
}
public void setCategory_Id(Integer category_Id) {
this.category_Id = category_Id;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public Set<Book> getBooks() {
return books;
}
public void setBooks(Set<Book> books) {
this.books = books;
}
public Integer getInitBook() {
return initBook;
}
public void setInitBook(Integer initBook) {
this.initBook = initBook;
}
}
Category類對映檔案:
<?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 table="t_hibernate_category" name="com.study.entity.Category">
<id name="category_Id" type="java.lang.Integer" column="category_id">
<generator class="increment"></generator>
</id>
<property name="categoryName" type="java.lang.String" column="category_name"></property>
<set table="t_hibernate_book_category" name="books" cascade="save-update" inverse="true">
<key column="cid"></key>
<many-to-many column="bid" class="com.study.entity.Book"/>
</set>
</class>
</hibernate-mapping>
Book DAO層:
package com.study.dao;
import java.io.Serializable;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.study.entity.Book;
import com.study.entity.TreeNode;
import com.zking.util.SessionFactoryUtils;
public class BookDao {
public Book get(Book book) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
Book b = session.get(Book.class, book.getBookId());
if (b != null && new Integer(1).equals(book.getInitCategorys())) {
Hibernate.initialize(b.getCategorys());
}
transaction.commit();
session.close();
return b;
}
public Integer add(Book book) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
Integer n = (Integer) session.save(book);
transaction.commit();
session.close();
return n;
}
public void del(Book book) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
session.delete(book);
transaction.commit();
session.close();
}
}
Category DAO層:
package com.study.dao;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.study.entity.Book;
import com.study.entity.Category;
import com.zking.util.SessionFactoryUtils;
public class CategoryDao {
public Category get(Category category) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
Category c = session.get(Category.class, category.getCategory_Id());
if (c != null && new Integer(1).equals(category.getInitBook())) {
Hibernate.initialize(c.getBooks());
}
transaction.commit();
session.close();
return c;
}
public Integer add(Category category) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
Integer n = (Integer) session.save(category);
transaction.commit();
session.close();
return n;
}
public void del(Category category) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
Category c = session.get(Category.class, category.getCategory_Id());
for (Book b : c.getBooks()) {
//c.getBooks().remove(b);
b.getCategorys().remove(c);
}
session.delete(c);
transaction.commit();
session.close();
}
}
級聯查詢:
1.根據書籍查詢類別
@Test
public void testGet1() {
Book book = new Book();
book.setBookId(5);
book.setInitCategorys(1);
Book b = bookDao.get(book);
System.out.println(b.getBookName());
for (Category c : b.getCategorys()) {
System.out.println(c.getCategoryName());
}
}
2.根據類別查詢書籍
@Test
public void testGet2() {
Category category = new Category();
category.setCategory_Id(2);
category.setInitBook(1);
Category c = categoryDao.get(category);
System.out.println(c.getCategoryName());
for (Book b : c.getBooks()) {
System.out.println(b.getBookName());
}
}
級聯新增:
注:主控方為Book類,所以只用Book能維護關係,因此增加時值有增加書籍時才能級聯增加,反過來級聯增加類別時,就只能增加類別
而且級聯增加時增加是持久化資料不是臨時資料
@Test
public void testAdd1() {
Book book = new Book();
book.setBookName("不死不滅");
book.setPrice(45f);
Category category = new Category();
category.setCategory_Id(8);
book.getCategorys().add(this.categoryDao.get(category));
bookDao.add(book);
}
刪除:
注:這裡不是級聯刪除,級聯刪除是不推薦使用的,會因為雙向關聯關係刪除所有資料!!!
1.刪除Book的同時刪除對應關聯(主控方刪除)
public void testDel1() {
Book book = new Book();
book.setBookId(6);
this.bookDao.del(book);
}
2.刪除Category的同時刪除對應關聯(被控方刪除)
因為維護關係,如果直接刪除Category,會因為不刪除關聯資料而報外來鍵錯誤
解決:由主控方解除關聯關係,然後被控方再進行刪除
public void del(Category category) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
Category c = session.get(Category.class, category.getCategory_Id());//查詢category物件
for (Book b : c.getBooks()) {//獲取該類別對應的所有book
//c.getBooks().remove(b);
b.getCategorys().remove(c);//book解除關係
}
session.delete(c);
transaction.commit();
session.close();
}
刪除:
public void testDel2() {
Category category = new Category();
category.setCategory_Id(8);
this.categoryDao.del(category);
}