`
hadix
  • 浏览: 25733 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Hibernate many-to-many,many-to-one,inverse测试

阅读更多

近日工作中发现对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-Order(many-to-many)

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数据,重新执行改测试,则测试通过.

 

接下来的测试验证book和order的多对多关系
	@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;
	}
 
前面的测试,中注释中标示了一些对象状态转换,下图描述了Hibernate对象状态转换


 
总结
问题:1.Hibernate对象状态转换是隐式的,没经验的用户会比较困惑,在大规模的系统中也很容易出现错误.
2.Hibernate的异常信息是很令人困惑的,写这个demo的过程中,曾出现过一些异常.经检查是由于缺少javassit.jar,但是异常信息却完全与之无关,十分诡异.系统调试经常需要花费很多时间,也未必能找到根本问题.
3.Hibernate的文档描述不明确,inverse和cascade的语义本应十分明确,但是文档描述却不够明确.

我不喜欢这样的工具.作为工具它太复杂了,这种复杂度使学习曲线陡峭,系统调试困难.不适用于我目前的工作.

(第一次写,基本没什么养分..好在让自己重新温习了一下hibernate开发环境配置,明确一下inverse的作用)
  • 大小: 14.7 KB
  • 大小: 18.6 KB
分享到:
评论

相关推荐

    Hibernate one-to-many / many-to-one关系映射

    "Hibernate one-to-many / many-to-one关系映射"是两个基本的关系类型,用于表示实体间的关联。在这个主题中,我们将深入探讨这两种关系映射的原理、配置和实际应用。 一、一对一(one-to-one)与一对多(one-to-...

    Hibernate Mapping Many-to-One 实例 内附源代码及附件下载

    本实例将详细讲解如何在Hibernate中实现Many-to-One关系映射,这是一种常见的数据库关联,表示一个实体可以与多个其他实体相关联。 在Many-to-One关系中,通常一个实体(如部门)可以有多个相关实体(如员工),而...

    hibernate学习5之one-to-many双向关联.docx

    在配置双向一对多关联时,我们通常在"多"一端(这里是`Student`)的集合属性上使用`&lt;many-to-one&gt;`标签,将`Classes`对象映射到数据库中的外键。同时,在"一"端(`Classes`)使用`&lt;set&gt;`标签,表示班级可以包含多个...

    Hibernate-one-to-many

    同时,`Account.hbm.xml`中的`many-to-one`元素将`column`属性设置为`FID`,表示通过`FID`字段关联到`User`实体。 #### 测试场景解释 在测试场景中,我们创建了一个`User`对象和一个`Account`对象,并在`User`对象...

    hibernate 全面学习->hibernate 关联映射学习

    本篇文章将全面探讨Hibernate的关联映射学习,包括一对一(One-to-One)、一对多(One-to-Many)、多对一(Many-to-One)以及多对多(Many-to-Many)四种关系映射。 首先,一对一关联映射(One-to-One)是两个实体...

    NHibernate One-to-Many一对多映射-xxlinux_com

    在数据库世界中,一对多(One-to-Many)关系是一种常见的关联类型,其中一个表(父表)可以与多个其他表(子表)相关联。在NHibernate中,配置这种映射关系对于理解和使用ORM至关重要。 一对多关系意味着一个实体...

    hibernate inverse和cascade的详细讲解

    与`inverse`不同,`cascade`属性可以应用于所有涉及到关联的元素,如`&lt;many-to-one&gt;`、`&lt;one-to-one&gt;`、`&lt;any&gt;`、`&lt;set&gt;`、`&lt;bag&gt;`、`&lt;idbag&gt;`、`&lt;list&gt;`和`&lt;array&gt;`。 - **Cascade 的作用** - **定义**:`cascade...

    hibernate中one2many映射

    对于"订单"实体的映射文件(Order.hbm.xml),需要定义一个对"用户"的引用,通常使用`&lt;many-to-one&gt;`元素: ```xml &lt;!-- Order.hbm.xml --&gt; &lt;many-to-one name="user" column="USER_ID" class=...

    Hibernate性能调优

    `many-to-one`关联是另一个重要的关联类型,在Hibernate中,它通常用来表示外键存储方向。 - **定义**:`many-to-one`关联意味着多个实体可以指向同一个实体。 - **示例**:如学生与教师之间的关联。 - **注意点**...

    hibernate的关联映射

    关联映射主要包括四种类型:一对一(One-to-One)、一对多(One-to-Many)、多对一(Many-to-One)和多对多(Many-to-Many)。下面我们将逐一探讨这些关联映射的配置方法。 1. **一对一关联映射** - **主键关联**...

    hibernate中many2many映射

    在Java持久化框架Hibernate中,Many-to-Many(多对多)映射是一种常见的关联关系类型,用于表示两个实体类之间复杂的关系。在本场景中,我们探讨的是如何在Hibernate中配置Many-to-Many映射,并使用MySQL数据库来...

    hibernate-one-to-many

    &lt;many-to-one name="department" class="com.example.Department" column="DEPARTMENT_ID" /&gt; ``` 如果使用注解,上述关系已经在实体类中定义。 ### 3. 操作一对多关系 在实际应用中,我们可以通过Hibernate提供...

    Hibernate中cascade与inverse属性详解

    在深入讲解这两个属性之前,我们首先需要理解 Hibernate 中的一些基本概念,如 one-to-many 和 many-to-one 关系、对象的状态以及 Session 缓存。 一、one-to-many 和 many-to-one 关系 在示例中,`class` 表(班级...

    Hibernate关联关系hbm.xml中的相关属性

    在hbm.xml文件中,我们可以使用`&lt;many-to-one&gt;`, `&lt;one-to-many&gt;`, 和 `&lt;many-to-many&gt;`标签来定义这些关联。下面将详细介绍这三个标签及其相关属性。 首先,我们来看`&lt;many-to-one&gt;`标签,它表示多对一的关系。...

    hibernate多对多双向关联

    多对多双向关联 &lt;br&gt;注意映射规则: &lt;set name="roles" table="t_user_role"&gt;&lt;br&gt; &lt;key column="userid"/&gt;&lt;br&gt; &lt;many-to-many class="com.bjsxt.hibernate.Role" column="roleid"/&gt;&lt;br&gt; &lt;/set&gt;&lt;br&gt;&lt;br&gt;table...

    hibernate表关联关系

    ### Hibernate表关联关系详解 ...综上所述,无论是`many-to-many`还是`one-to-one`关联关系,在Hibernate中都可以通过相应的配置文件来实现。正确地理解和配置这些关联关系对于构建高效、可扩展的应用程序至关重要。

    Hibernate一对多(多对一)双向关联(annotation/xml)

    在Java的持久化框架Hibernate中,一对多(Many-to-One)和多对一(One-to-Many)的关系映射是数据库关系模型中的常见关联类型。本文将深入探讨这两种关联方式在使用Hibernate时的配置,包括基于注解(Annotation)和...

    hibrenate xml 配置 映射

    这使用`&lt;many-to-one&gt;`标签。 ```xml &lt;many-to-one name="address" class="com.example.Address" column="address_id"/&gt; ``` #### 2.1.7 多对一连接表单向关联 与上述相同,但通过连接表进行关联。 #### 2.1.8 多...

Global site tag (gtag.js) - Google Analytics