近日工作中发现对Hibernate一些概念模糊.故望此文可以帮助我理顺思路.
写了一个简单的Demo做测试.
两个实体
public class Type { private int id; private String name; private Set books; //省略getter,setter等方法,下同 } public class Book implements Serializable { private int id; private String name; private String desc; private String price; private Date createTime; private Date updateTime; private Type type; private Set orders; } public class Order { private int id; private Date createTime; private Set books; }
关系映射文件
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="hadix.demo.hibernate.model.Book" table="book"> <id name="id"> <column name="id" sql-type="integer" length="2000000000" precision="10" not-null="true"/> <generator class="increment"/> </id> <property name="name"> <column name="name" sql-type="varchar(500)" length="2000000000" precision="10"/> </property> <property name="desc"> <column name="desc" sql-type="text" length="2000000000" precision="10"/> </property> <property name="price"> <column name="price" sql-type="numeric" length="2000000000" precision="10"/> </property> <property name="createTime"> <column name="create_time" sql-type="datetime" length="2000000000" precision="10"/> </property> <property name="updateTime"> <column name="update_time" sql-type="datetime" length="2000000000" precision="10"/> </property> <many-to-one name="type" column="type_id" class="hadix.demo.hibernate.model.Type"/> <set name="orders" lazy="true" table="book_order_link" inverse="true"> <key column="book_id"/> <many-to-many column="order_id" class="hadix.demo.hibernate.model.Order"/> </set> </class> <class name="hadix.demo.hibernate.model.Order" table="order"> <id name="id"> <column name="id" sql-type="integer" length="2000000000" precision="10" not-null="true"/> </id> <property name="createTime"> <column name="create_time" sql-type="datetime" length="2000000000" precision="10"/> </property> <set name="books" table="book_order_link" lazy="false"> <key column="order_id"/> <many-to-many column="book_id" class="hadix.demo.hibernate.model.Book"/> </set> </class> <class name="hadix.demo.hibernate.model.Type" table="type"> <id name="id"> <column name="id" sql-type="integer" length="2000000000" precision="10" not-null="true"/> </id> <property name="name"> <column name="name" sql-type="varchar(500)" length="2000000000" precision="10" not-null="true" unique="true"/> </property> <set name="books" lazy="true" inverse="true"> <key column="type_id"/> <one-to-many class="hadix.demo.hibernate.model.Book"/> </set> </class> </hibernate-mapping>
关系图
Book-Type(many-to-one)
均为双向关系
运行测试用例
@Test public void testManyToOne() { Session session = Sessions.getSession(); session.beginTransaction(); //持久态 books List<Book> books = getBooks(session); for (Book book : books) { //数据库中原本已经存放了书籍数据,但未指定类型,所以测试可以通过该断言 assertNull(book.getType()); } //瞬态 type Type type = new Type("Book_Type_1"); type.setBooks(new HashSet<Book>(books)); session.saveOrUpdate(type);//type 变为持久态 session.getTransaction().commit(); session.clear();//清除缓存避免之后取到旧数据 //重新读取书籍数据,以确保获得正确关系更新 for (Book book : getBooks(session)) { assertEquals(type, book.getType());//期望类型保存后会更新数据库中书跟类型之间的关系 } session.close(); } private List<Book> getBooks(Session session) { return session.createQuery("from Book").list(); }
结果测试没有通过第二个断言.测试结果是:java.lang.AssertionError:
expected:<Type{id=1, name='Book_Type_1'}> but was:<null>
因为在Type一端使用了inverse="true",所以在保存Type对象时并没有保存跟Book间的关系.去掉inverse="true",清除数据库中的type数据,重新执行改测试,则测试通过.
@Test public void testManyToMany() { Session session = Sessions.getSession(); session.beginTransaction(); List<Book> books = getBooks(session); HashSet<Book> bookSet = new HashSet<Book>(books); //把同一批书添加到两个订单中 Order order1 = newOrder(session, bookSet); Order order2 = newOrder(session, bookSet); session.getTransaction().commit(); //验证建立了正确的多对多关系 assertEquals(books.size(),order1.getBooks().size()); assertEquals(books.size(),order2.getBooks().size()); for (Book book : books) { assertEquals(2, book.getOrders().size()); } session.close(); } private Order newOrder(Session session, HashSet<Book> bookSet) { Order order = new Order(); order.setBooks(bookSet); session.save(order); //order对象在保存后变为"持久态" return order; }