1, One to many association configuration
Database: master table, slave table, associated by foreign key
Class:
class A{
B b;
}
class B{
}
Example: order and orderItem
order entity class
package com.sjy.entity; import java.util.HashSet; import java.util.Set; public class Order { // create table t_hibernate_order // ( // order_id int primary key auto_increment, // order_no varchar(50) not null // ); private Integer orderId; private String orderNo; //Note: variable attributes must be accepted by the interface private Set<OrderItem> orderItems = new HashSet<>(); private Integer initOrderItems = 0;//0 represents lazy loading and 1 represents forced loading public Integer getInitOrderItems() { return initOrderItems; } public void setInitOrderItems(Integer initOrderItems) { this.initOrderItems = initOrderItems; } public Set<OrderItem> getOrderItems() { return orderItems; } public void setOrderItems(Set<OrderItem> 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; } }
For an order, it contains multiple order items
Therefore, the order entity class contains the attributes of the order item collection
For the order item table, it must belong to an order
package com.sjy.entity; public class OrderItem { // create table t_hibernate_order_item // ( // 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_hibernate_order(order_id) // ); 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; } }
to configure
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> <class name="com.sjy.entity.Order" table="t_hibernate_order"> <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"/> <!-- cascade:Cascade attribute configuration inverse: Is the relationship maintained by the other party? --> <set name="orderItems" cascade="save-update" inverse="true"> <key column="oid"></key> <one-to-many class="com.sjy.entity.OrderItem"/> </set> </class> </hibernate-mapping>
For an order, it belongs to the one to many tag class is the fully qualified name of the order item
The name attribute is the attribute name Key indicates the foreign key column
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> <class name="com.sjy.entity.OrderItem" table="t_hibernate_order_item"> <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 name="quantity" type="java.lang.Integer" column="quantity"/> <property name="oid" type="java.lang.Integer" column="oid"/> <!-- Repeated column in mapping for entity: com.zking.four.entity.OrderItem column: oid (should be mapped with insert="false" update="false") --> <many-to-one name="order" class="com.sjy.entity.Order" insert="false" update="false" column="oid"></many-to-one> </class> </hibernate-mapping>
Contrary to order.hbm.xml, the many-to-one tag
2, Lazy loading
orderDao
public Order get(Order order) { Session session = SessionFactoryUtil.getSession(); Transaction transaction = session.beginTransaction(); Order o = session.get(Order.class, order.getOrderId()); // In addition, if you want to query the data of associated order items, you can use forced loading if(o != null && new Integer(1).equals(order.getInitOrderItems())) { Hibernate.initialize(o.getOrderItems()); } transaction.commit(); session.close(); return o; }
orderDaoTest calls the query method
public void testGet() { Order order = new Order(); order.setOrderId(7); Order o = this.orderDao.get(order); System.out.println(o.getOrderNo()); }
The results are consistent with the database
If you want to get the order item of the order, we will write this
public void testGet() { Order order = new Order(); order.setOrderId(7); Order o = this.orderDao.get(order); System.out.println(o.getOrderNo()); System.out.println(o.getOrderItems()); }
It turns out to be such a mistake
The order item data associated with this order needs to be forcibly loaded
@Test public void testGet() { Order order = new Order(); order.setOrderId(7); order.setInitOrderItems(1); Order o = this.orderDao.get(order); System.out.println(o.getOrderNo()); System.out.println(o.getOrderItems()); }
The running result is
The results show that the order items are loaded!
Reason for lazy loading by default:
When only the data of the order table is needed, the data of the order item table will also be found. At this time, the amount of sql statements used is huge
Therefore, the default is lazy loading. When an order item is required, change the initOrderItems field of the order entity class to 1
3, One to many autocorrelation
One to many auto correlation means that the id of a piece of data is the parent id of the child data, that is, the parent in the graph_ node_ id, which is also the id of the parent node
You need to get the child node and parent node of the node at the same time. It is simple for hibernate
1.entity
package com.sjy.entity; import java.util.HashSet; import java.util.Set; public class TreeNode { private Integer nodeId; private String nodeName; private Integer treeNodeType; private Integer position; private String url; private TreeNode parent; private Set<TreeNode> children = new HashSet<TreeNode>(); private Integer initChildren = 0; public Integer getNodeId() { return nodeId; } public void setNodeId(Integer nodeId) { this.nodeId = nodeId; } public String getNodeName() { return nodeName; } public void setNodeName(String nodeName) { this.nodeName = nodeName; } public Integer getTreeNodeType() { return treeNodeType; } public void setTreeNodeType(Integer treeNodeType) { this.treeNodeType = treeNodeType; } public Integer getPosition() { return position; } public void setPosition(Integer position) { this.position = position; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public TreeNode getParent() { return parent; } public void setParent(TreeNode parent) { this.parent = parent; } public Set<TreeNode> getChildren() { return children; } public void setChildren(Set<TreeNode> children) { this.children = children; } public Integer getInitChildren() { return initChildren; } public void setInitChildren(Integer initChildren) { this.initChildren = initChildren; } // @Override // public String toString() { // return "TreeNode [nodeId=" + nodeId + ", nodeName=" + nodeName + ", treeNodeType=" + treeNodeType // + ", position=" + position + ", url=" + url + ", children=" + children + "]"; // } @Override public String toString() { return "TreeNode [nodeId=" + nodeId + ", nodeName=" + nodeName + ", treeNodeType=" + treeNodeType + ", position=" + position + ", url=" + url + "]"; } }
2. Mapping relationship (TreeNode.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.zking.two.entity.TreeNode" table="t_hibernate_sys_tree_node"> <id name="nodeId" type="java.lang.Integer" column="tree_node_id"> <generator class="increment" /> </id> <property name="nodeName" type="java.lang.String" column="tree_node_name"> </property> <property name="treeNodeType" type="java.lang.Integer" column="tree_node_type"> </property> <property name="position" type="java.lang.Integer" column="position"> </property> <property name="url" type="java.lang.String" column="url"> </property> <many-to-one name="parent" class="com.zking.two.entity.TreeNode" column="parent_node_id"/> <set name="children" cascade="save-update" inverse="true"> <key column="parent_node_id"></key> <one-to-many class="com.sjy.entity.TreeNode"/> </set> </class> </hibernate-mapping>
3.dao
public TreeNode load(TreeNode treeNode) { Session session = SessionFactoryUtil.getSession(); 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; }
4. Call method
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()); }
Console
Both parent and child nodes have been queried
4, Many to many Association
It is equivalent to two many to one. There are foreign keys of two tables in the middle table. Both tables and the middle table are one to many
1.book entity class
package com.sjy.entity; import java.io.Serializable; import java.util.HashSet; import java.util.Set; public class Book implements Serializable{ // book_id int primary key auto_increment, // book_name varchar(50) not null, // price float not null private Integer bookId; private String bookName; private Float price; private Set<Category> categories = new HashSet<Category>(); private Integer initCategories = 0; public Integer getInitCategories() { return initCategories; } public void setInitCategories(Integer initCategories) { this.initCategories = initCategories; } 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> getCategories() { return categories; } public void setCategories(Set<Category> categories) { this.categories = categories; } @Override public String toString() { return "Book [bookId=" + bookId + ", bookName=" + bookName + ", price=" + price + "]"; } public Book(Integer bookId, String bookName) { super(); this.bookId = bookId; this.bookName = bookName; } public Book() { super(); } }
category
package com.sjy.entity; import java.io.Serializable; import java.util.HashSet; import java.util.Set; public class Category implements Serializable{ // category_id int primary key auto_increment, // category_name varchar(50) not null private Integer categoryId; private String categoryName; private Set<Book> books = new HashSet<Book>(); 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 Set<Book> getBooks() { return books; } public void setBooks(Set<Book> books) { this.books = books; } @Override public String toString() { return "Category [categoryId=" + categoryId + ", categoryName=" + categoryName + "]"; } }
2. Configuration
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.sjy.entity.Book" table="t_hibernate_book"> <!-- <cache usage="read-only" region="com.zking.five.entity.Book"/> --> <id name="bookId" type="java.lang.Integer" column="book_id"> <generator class="increment" /> </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="categories" cascade="save-update" inverse="false"> <!-- one --> <key column="bid"></key> <!-- many --> <many-to-many column="cid" class="com.sjy.entity.Category"></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.sjy.entity.Category" table="t_hibernate_category"> <id name="categoryId" type="java.lang.Integer" column="category_id"> <generator class="increment" /> </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.sjy.entity.Book"></many-to-many> </set> </class> </hibernate-mapping>
The inverse attribute is reverse, which is used for data maintenance
false indicates that the data of the intermediate table is maintained by itself
true indicates that the data of the intermediate table is maintained by the opposite party
One of the two tables must be true and the other false
Table: intermediate table
name: association attribute
Key: the primary key of the current table is the foreign key of the associated table
3.bookDao
package com.sjy.dao; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import com.sjy.entity.Book; import com.sjy.entity.Category; import com.sjy.util.SessionFactoryUtil; public class BookDao /*extends BaseDao*/{ public Integer addBook(Book book) { Session session = SessionFactoryUtil.getSession(); Transaction transaction = session.beginTransaction(); Integer bid = (Integer) session.save(book); transaction.commit(); session.close(); return bid; } public Integer addCategory(Category category) { Session session = SessionFactoryUtil.getSession(); Transaction transaction = session.beginTransaction(); Integer cid = (Integer) session.save(category); transaction.commit(); session.close(); return cid; } public Category getCategory(Category category) { Session session = SessionFactoryUtil.getSession(); 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 = SessionFactoryUtil.getSession(); 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; } public void delBook(Book book) { Session session = SessionFactoryUtil.getSession(); Transaction transaction = session.beginTransaction(); session.delete(book); transaction.commit(); session.close(); } public void delCategory(Category category) { Session session = SessionFactoryUtil.getSession(); Transaction transaction = session.beginTransaction(); Category c = session.get(Category.class, category.getCategoryId()); if(c!=null) { for (Book b : c.getBooks()) { // The accused party cancels the association relationship through the main control party, and finally the accused party deletes it b.getCategories().remove(c); } } session.delete(c); transaction.commit(); session.close(); } /* * hql Explain (need to inherit BaseDao) */ /** * No code before BaseDao is used * @param book * @param pageBean * @return */ // public List<Book> list(Book book, PageBean pageBean) { // Session session = SessionFactoryUtil.getSession(); // Transaction transaction = session.beginTransaction(); // String hql = "from Book where 1 = 1"; // // if (StringUtils.isNotBlank(book.getBookName())) { // hql += " and bookName like :bookName"; // } // // Query query = session.createQuery(hql); // // if (StringUtils.isNotBlank(book.getBookName())) { // query.setParameter("bookName", book.getBookName()); // } // // if (pageBean != null && pageBean.isPagination()) { // query.setFirstResult(pageBean.getStartIndex()); // query.setMaxResults(pageBean.getRows()); // } // List<Book> list = query.list(); // transaction.commit(); // session.close(); // return list; // // } /** * Code after using BaseDao * @param book * @param pageBean * @return */ // public List<Book> list2(Book book, PageBean pageBean) { // Session session = SessionFactoryUtil.getSession(); // Transaction transaction = session.beginTransaction(); // String hql = "from Book where 1 = 1"; // Map<String, Object> map = new HashMap<String, Object>(); // // if (StringUtils.isNotBlank(book.getBookName())) { // hql += " and bookName like :bookName"; // map.put("bookName", book.getBookName()); // } // List list = super.executeQuery(session, hql, map, pageBean); // transaction.commit(); // session.close(); // return list; // } /** * Use native SQL * @param book * @param pageBean * @return */ // public List list3(Book book, PageBean pageBean) { String sql = "select b.*,o.* from t_hibernate_book b,t_hibernate_Order o"; // String sql = "select * from t_hibernate_book"; // Session session = SessionFactoryUtil.getSession(); // Transaction transaction = session.beginTransaction(); // List list = session.createSQLQuery(sql).list(); // transaction.commit(); // session.close(); // return list; // } }
4.test
package com.sjy.dao; import org.junit.Test; import com.sjy.entity.Book; import com.sjy.entity.Category; public class BookDaoTest { private BookDao bookDao = new BookDao(); @Test public void testGetBook() { Book book = new Book(); book.setBookId(8); book.setInitCategories(1); Book b = this.bookDao.getBook(book ); System.out.println(b.getBookName()); System.out.println(b.getCategories()); } /** * book.hbm.xml inverse=fasle * category.hbm.xml inverse=true * Data addition is normal * Add a new piece of data to the book table and bridge table respectively */ @Test public void test1() { Book book = new Book(); book.setBookName("bbbb"); book.setPrice(10f); Category category = new Category(); category.setCategoryId(5); // It is wrong to directly add the category object to the new book, because the category is temporary and hibernate will not manage it // book.getCategories().add(category); Category c = this.bookDao.getCategory(category); // c.getBooks().add(book); book.getCategories().add(c); this.bookDao.addBook(book); } /** * book.hbm.xml inverse=true * category.hbm.xml inverse=true * Only add book table data * Bridge table without data * Reason: neither side has maintained the relationship */ @Test public void test2() { Book book = new Book(); book.setBookName("dddd"); 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); } }
5. Console