Hibernate3 学习(七)

9容器映射

容器常用来储存对象,这边来了解一下如何将容器的关系映像至表格。

91 Set

关于Set的特性,您可以先参考 HashSetTreeSet 这两篇文件的介绍,这边先介绍当Set中包括的对象为非实体(Entiy)时的映射方式,简单的说,也就是所包括的对象没有对象识别(Identity),只是纯綷的值型态(Value type)对象)。

假设您有一个User类别,当中除了名称属性之外,另一个就是使用者的电子邮件地址,同一个使用者可能有多个不同的邮件地址,所以在User类别中使用 Set对象来加以记录,在这边使用String来记录每一笔邮件地址,为了不允许重复的邮件地址记录,所以使用Set对象,User类别如下:

User.java

package onlyfun.caterpillar;

import java.util.Set;

 

public class User {

    private Integer id;

    private String name;

    private Set emails;

 

    // 必须要有一个预设的建构方法

    // 以使得Hibernate可以使用Constructor.newInstance()建立对象

    public User() {

    }

 

    public Integer getId() {

        return id;

    }

 

    public void setId(Integer id) {

        this.id = id;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public Set getEmails() {

        return emails;

    }

 

    public void setEmails(Set emails) {

        this.emails = emails;

    }

   

    public void addEmail(String email) {

        this.emails.add(email);

    }

   

    public void removeEmail(String email) {

        this.emails.remove(email);

    }

}

要映像Set容器,您可以使用另一个表格来储存Set容器中的数据,例如您可以分别建立useremail表格:

CREATE TABLE user (

    id INT(11) NOT NULL auto_increment PRIMARY KEY,

    name VARCHAR(100) NOT NULL default ''

 );

 

CREATE TABLE email (

    id INT(11) NOT NULL,

    address VARCHAR(100) NOT NULL

);

接着定义映像文件,使用<set>标签来定义Set映像:

User.hbm.xml

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping

    PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping>

    <class name="onlyfun.caterpillar.User" table="user">

        <id name="id" column="id" type="java.lang.Integer">

            <generator class="native"/>

        </id>

 

        <property name="name" column="name" type="java.lang.String"/>        

        <set name="emails" table="email">

            <key column="id"/>

            <element type="java.lang.String"

                     column="address"/>

        </set>

    </class>

</hibernate-mapping>

假设您如下储存对象:

User user1 = new User();

user1.setEmails(new HashSet());

user1.setName("caterpillar");

user1.addEmail("caterpillar.onlyfun@gmail.com");

user1.addEmail("caterpillar.onlyfun@yahoo.com");

       

User user2 = new User();

user2.setEmails(new HashSet());

user2.setName("momor");

user2.addEmail("momor@gmail.com");

 

Session session = sessionFactory.openSession();

Transaction tx = session.beginTransaction();           

session.save(user1);

session.save(user2);

tx.commit();

session.close();

则数据库中的表格储存内容将如下:

mysql> select * from user;

+----+----------------+

| id | name           |

+----+----------------+

|  1 | caterpillar    |

|  2 | momor          |

+----+----------------+

2 rows in set (0.00 sec)

 

mysql> select * from email;

+----+-------------------------------------------+

| id | address                                   |

+----+-------------------------------------------+

|  1 | caterpillar.onlyfun@yahoo.com             |

|  1 | caterpillar.onlyfun@gmail.com             |

|  2 | momor@gmail.com                           |

+----+-------------------------------------------+

3 rows in set (0.00 sec)

注意到:在Set的功能说明中,并没有用到EmailEmail..hbm.Xml文件和Email.java。在User.hbm.xml文件中声明的

        <set name="emails" table="email">

            <key column="id"/>

            <element type="java.lang.String"

                     column="address"/>

        </set>

Setkeyemailid,元素为address 于是更新的时候便对应的进行操作;

 

 

92 List

关于List的特性,可以先看一下[ArrayList][LinkedList]这两篇文件。

List是有序的结构,所以在储存List容器中的对象时,要一并储存其顺序信息,例如若您设计了以下的类别:

User.java

package onlyfun.caterpillar;

 

import java.util.List;

 

public class User {

    private Integer id;

    private String name;

    private List items;

 

    // 必须要有一个预设的建构方法

    // 以使得Hibernate可以使用Constructor.newInstance()建立对象

    public User() {

    }

 

    public Integer getId() {

        return id;

    }

 

    public void setId(Integer id) {

        this.id = id;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public List getItems() {

        return items;

    }

 

    public void setItems(List items) {

        this.items = items;

    }

 

    public void addItem(String item) {

        items.add(item);

    }

   

    public void removeItem(String item) {

        items.remove(item);

    }

}

在设计表格时,使用一个item表格来记录List容器信息,item表格必须包括索引信息,例如您可以如下建立useritem表格:

CREATE TABLE user (

    id INT(11) NOT NULL auto_increment PRIMARY KEY,

    name VARCHAR(100) NOT NULL default ''

);

 

CREATE TABLE item (

    id INT(11) NOT NULL,

    position INT(11) NOT NULL,

    name VARCHAR(100) NOT NULL default ''

);

其中position字段要用来储存List的索引信息,可以使用<list>卷标如下定义映像文件:

User.hbm.xml      

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping

    PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping>

 

    <class name="onlyfun.caterpillar.User" table="user">

        <id name="id" column="id" type="java.lang.Integer">

            <generator class="native"/>

        </id>

        <property name="name" column="name" type="java.lang.String"/>         

        <list name="items" table="item">

            <key column="id"/>

            <index column="position"/>

            <element type="java.lang.String" column="name"/>

        </list>

    </class>

</hibernate-mapping>

假设您如下储存对象:

User user1 = new User();

user1.setItems(new ArrayList());

user1.setName("caterpillar");

user1.addItem("DC");

user1.addItem("CF Card");

       

User user2 = new User();

user2.setItems(new ArrayList());

user2.setName("momor");

user2.addItem("comics");

 

Session session = sessionFactory.openSession();

Transaction tx = session.beginTransaction();           

session.save(user1);

session.save(user2);

tx.commit();

session.close();

则数据库中的储存状况如下:

mysql> select * from user;

+----+--------------+

| id | name         |

+----+--------------+

|  1 | caterpillar  |

|  2 | momor        |

+----+--------------+

2 rows in set (0.00 sec)

 

mysql> select * from item;

+----+------------+-----------+

| id | position   | name      |

+----+------------+-----------+

|  1 |        0   | DC        |

|  1 |        1   | CF Card   |

|  2 |        0   | comics    |

+----+------------+-----------+

3 rows in set (0.00 sec)

注意到:在List的功能说明中,item表中出现position字段原因就是便于区分有序的list的准确定位;而我们对posetionindex取值也是自动排号的;

93 Map

Definition:

A map is a simple name-value pair list stored on a first rank collection.

Scenario:

Map Foo.getAges()   //  returns a collection of String name-value pairs

Hibernate Mapping

hbm.xml中设定如下:

<class name="Foo" table="foo">

    ...

    <map role="ages">

        <key column="id"/>

        <index column="name" type="string"/>

        <element column="age" type="string"/>

    </map>

</class>

Table Schema

Foo

id

 

Ages

 

 

id

name

age

A simple extra table, Ages, is used to store the name and age string-value pair. Note that the map needs its own identity column too: id

Bidirectionality:

Bidirectionality has no meaning for a map.

94 Bag

Bag是集合,与Set不同的是,Bag允许重复的元素,在Java的标准API中并没有提供Bag容器,Hibernate提供自己的Bag实现,允许您将List映射为Bag

您可以如下定义User类别,其中的List成员将被用作Bag来使用,而不管对象在List容器中的顺序:

User.java

package onlyfun.caterpillar;

 

import java.util.List;

 

public class User {

    private Integer id;

    private String name;

    private List items;

 

    // 必须要有一个预设的建构方法

    // 以使得Hibernate可以使用Constructor.newInstance()建立对象

    public User() {

    }

 

    public Integer getId() {

        return id;

    }

 

    public void setId(Integer id) {

        this.id = id;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public List getItems() {

        return items;

    }

 

    public void setItems(List items) {

        this.items = items;

    }

 

    public void addItem(String item) {

        items.add(item);

    }

   

    public void removeItem(String name) {

        items.remove(name);

    }

}

最简单的Bag映像是使用<bag>标签,在这之前,假设您如下建立表格:

CREATE TABLE user (

    id INT(11) NOT NULL auto_increment PRIMARY KEY,

    name VARCHAR(100) NOT NULL default ''

);

 

CREATE TABLE item (

    id INT(11) NOT NULL,

    name VARCHAR(100) NOT NULL

);

接着定义映射文件,如下所示:

User.hbm.xml

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping

    PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping>

    <class name="onlyfun.caterpillar.User" table="user">

 

        <id name="id" column="id" type="java.lang.Integer">

            <generator class="native"/>

        </id>

 

        <property name="name"

                  column="name"

                  type="java.lang.String"/>

      

        <bag name="items" table="item">

            <key column="id"/>

            <element column="name" type="java.lang.String"/>

        </bag>

       

    </class>

</hibernate-mapping>

假设您如下储存对象:

User user1 = new User();

user1.setItems(new ArrayList());

user1.setName("caterpillar");

user1.addItem("Java Gossip");

user1.addItem("Java Gossip");

user1.addItem("Caxxx A80");

       

User user2 = new User();

user2.setItems(new ArrayList());

user2.setName("momor");

user2.addItem("Snoppy world");       

       

Session session = sessionFactory.openSession();

Transaction tx = session.beginTransaction();

session.save(user1);

session.save(user2);

tx.commit();

session.close();

则数据库中会有如下的数据:

mysql> select * from user;

+----+-------------+

| id | name        |

+----+-------------+

|  1 | caterpillar |

|  2 | momor       |

+----+-------------+

2 rows in set (0.00 sec)

 

mysql> select * from item;

+----+-------------------+

| id | name              |

+----+-------------------+

|  1 | Java Gossip       |

|  1 | Java Gossip       |

|  1 | Caxxx A80         |

|  2 | Snoppy world      |

+----+-------------------+

4 rows in set (0.00 sec)

您可以如下更新数据:

Session session = sessionFactory.openSession();

Transaction tx = session.beginTransaction();

User user = (User) session.load(User.class, new Integer(1));

user.removeItem("Java Gossip");

tx.commit();

session.close();

然而注意观察在更新数据时所使用的SQL

Hibernate: delete from item where id=?

Hibernate: insert into item (id, name) values (?, ?)

Hibernate: insert into item (id, name) values (?, ?)

由于Bag的数据允许重复,当必须更新数据时,无法确定要更新的是哪一笔数据,因而采取的方式是删除集合对象对应的所有数据,然后重新将集合对象中的数据写入数据库,显然的这种作法相当的没有效率。

作为Bag的一种扩充,Hibernate提供idbag,藉由在定义Bag映像时加上"collection-id",让Hibernate可以直接确定所要更新的数据,提高数据库操作的效率,您可以先如下建立表格:

CREATE TABLE user (

    id INT(11) NOT NULL auto_increment PRIMARY KEY,

    name VARCHAR(100) NOT NULL default ''

);

 

CREATE TABLE item (

    cid CHAR(32) NOT NULL,

    id INT(11) NOT NULL,

    name VARCHAR(100) NOT NULL

);

其中item表格的cid就用于数据更新时定位之用,接着在映像文件中使用<idbag>标签加以定义:

User.hbm.xml

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping

    PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping>

    <class name="onlyfun.caterpillar.User" table="user">

 

        <id name="id" column="id" type="java.lang.Integer">

            <generator class="native"/>

        </id>

 

        <property name="name"

                  column="name"

                  type="java.lang.String"/>

      

        <idbag name="items" table="item">

            <collection-id column="cid" type="java.lang.String">

                <generator class="uuid.hex"/>

            </collection-id>

            <key column="id"/>           

            <element column="name" type="java.lang.String"/>

        </idbag>

       

    </class>

 

</hibernate-mapping>

使用上面用过的程序片段来储存对象的话,数据库中会有如下的数据:

mysql> select * from user;

+----+-------------+

| id | name        |

+----+-------------+

|  1 | caterpillar |

|  2 | momor       |

+----+-------------+

2 rows in set (0.00 sec)

 

mysql> select * from item;

+----------------------------------+------+--------------------+

| cid                              | id   | name               |

+----------------------------------+------+--------------------+

| 297eba61056726030105672605df0001 |  1   | Java Gossip        |

| 297eba61056726030105672605df0002 |  1   | Java Gossip        |

| 297eba61056726030105672605df0003 |  1   | Caxxx A80          |

| 297eba61056726030105672605df0004 |  2   | Snoppy world       |

+----------------------------------+------+--------------------+

4 rows in set (0.00 sec)

如果使用上面提到过的程序片段来更新对象的话,则实际上Hibernate会使用以下的SQL来进行更新:

Hibernate: delete from item where cid=?

这一次并不是整个删除集合中的数据,而是直接藉由cid来确定所要更新的数据,比起只使用Bagidbag的效率好了许多。

95内含 Component 的容器

假设您建立了以下的表格:

CREATE TABLE user (

    id INT(11) NOT NULL auto_increment PRIMARY KEY,

    name VARCHAR(100) NOT NULL default ''

);

 

CREATE TABLE email (

    id INT(11) NOT NULL,

    address VARCHAR(100) NOT NULL

);

一个user可以有多个email,但不可重复,这可以使用Set来映像,在对应的对象方法,您可以如下设计对象:

package onlyfun.caterpillar;

 

import java.util.Set;

 

public class User {

    private Integer id;

    private Set emails;

    ....

}

假设您原先预定在Set中储存的是String型态,而后设计时考虑独立设计一个MailAddress类别,而Set中将储存MailAddress的实例,例如:

User.java

package onlyfun.caterpillar;

 

import java.util.Set;

 

public class User {

    private Integer id;

    private String name;

    private Set emails;

 

    // 必须要有一个预设的建构方法

    // 以使得Hibernate可以使用Constructor.newInstance()建立对象

    public User() {

    }

 

    public Integer getId() {

        return id;

    }

 

    public void setId(Integer id) {

        this.id = id;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public Set getEmails() {

        return emails;

    }

 

    public void setEmails(Set emails) {

        this.emails = emails;

    }

   

    public void addEmail(MailAddress mailAddress) {

        this.emails.add(mailAddress);

    }

   

    public void removeEmail(MailAddress mailAddress) {

        this.emails.remove(mailAddress);

    }

}

 

MailAddress.java

package onlyfun.caterpillar;

 

public class MailAddress {

    private String address;

 

    public MailAddress() {      

    }

   

    public String getAddress() {

        return address;

    }

 

    public void setAddress(String address) {

        this.address = address;

    }

 

    public void sendMail() {

        System.out.println("Send mail to " + address);

    }

}

在映射文件方面,可以使用<composite-element>来为MailAddress作映射,如下:

User.hbm.xml

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping

    PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping>

    <class name="onlyfun.caterpillar.User" table="user">

        <id name="id" column="id" type="java.lang.Integer">

            <generator class="native"/>

        </id>

 

        <property name="name" column="name" type="java.lang.String"/>

       

        <set name="emails" table="email">

            <key column="id"/>

            <composite-element class="onlyfun.caterpillar.MailAddress">

                <property name="address" column="address"/>

            </composite-element>

        </set>

    </class>

</hibernate-mapping>

您可以如下储存对象:

User user = new User();

user.setName("caterpillar");

       

user.setEmails(new HashSet());

MailAddress mailAddress = new MailAddress();

mailAddress.setAddress("caterpillar.onlyfun@gmail.com");

user.addEmail(mailAddress);

       

mailAddress = new MailAddress();

mailAddress.setAddress("caterpillar.onlyfun@yahoo.com");

user.addEmail(mailAddress);

       

Session session = sessionFactory.openSession();

Transaction tx = session.beginTransaction();

session.save(user);

tx.commit();

session.close();

则数据库中会储存如下的数据:

mysql> select * from user;

+----+-------------+

| id | name        |

+----+-------------+

|  1 | caterpillar |

+----+-------------+

1 row in set (0.00 sec)

 

mysql> select * from email;

+----+-------------------------------------------+

| id | address                                   |

+----+-------------------------------------------+

|  1 | caterpillar.onlyfun@yahoo.com             |

|  1 | caterpillar.onlyfun@gmail.com          |

+----+-------------------------------------------+

2 rows in set (0.00 sec)

 

在查询时,address表格的数据会封装为MailAddress的实例,一个范例如下:

Session session = sessionFactory.openSession();

       

User user = (User) session.load(User.class, new Integer(1));

Iterator iterator = user.getEmails().iterator();

while(iterator.hasNext()) {

    MailAddress mailAddress = (MailAddress) iterator.next();

    mailAddress.sendMail();

}

session.close();

96容器的排序

从数据库的观点来看,SetMapBag是无序的,而List是有序的,这边所谓的无序或有序,是指将容器中对象储存至数据库时,是否依容器对象中的顺序来储存。

然而从数据库取得数据之后,您也许会希望SetMap等容器中的对象可以依一定的顺序来排列,您可以从两个层次来容器中的对象排序,一是在加载数据后于JVM中排序,另一是在数据库中直接使用order by子句来排序。

Set 这篇文章中的范例来作说明,要在JVM中就数据进行排序,您可以在映像文件中使用sort属性来定义容器的排序,这适用于SetMap,例如:

User.hbm.xml

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping

    PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping>

 

    <class name="onlyfun.caterpillar.User" table="user">

        ....

        <set name="emails" table="email" sort="natural">

            <key column="id"/>

            <element type="java.lang.String"

                     column="address"/>

        </set>

    </class>

 

</hibernate-mapping>

sort="natural"表示使用对象的comparaTo()方法来进行排序,容器中的对象上必须有实作java.lang.Comparable 接口,例如String就有实现java.lang.Comparable接口,结果会使用字典顺序来排列容器中的对象。

您可以实现自己的排序方式,只要定义一个类别来实作java.util.Comparator接口,例如:

CustomComparator.java

package onlyfun.caterpillar;

 

import java.util.Comparator;

 

public class CustomComparator implements Comparator {

    public int compare(Object o1, Object o2) {

        if (((String) o1).equals(o2))

            return 0;

        return ((Comparable) o1).compareTo(o2) * -1;

    }

}

在自订的Comparator中,如果两个对象的顺序相同会传回0,而为了方便比较对象,要求传入的对象必须实作Comparable接口(例如 String对象就有实作Comparable接口),范例中只是简单的将原来compareTo()传回的值乘以负一,如此就可以简单的让排列顺序相反,接着可以在映射文件中指定自订的Comparator类别:

User.hbm.xml

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping

    PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping>

 

    <class name="onlyfun.caterpillar.User" table="user">

        ....

        <set name="emails" table="email"

             sort="onlyfun.caterpillar.CustomComparator">

            <key column="id"/>

            <element type="java.lang.String"

                     column="address"/>

        </set>

    </class>

 

</hibernate-mapping>

BagList并不适用于这种方式。

另一个排序的方式则是在数据库中进行,直接使用order by子句来排序,这可以在映像文件中使用order-by属性来指定,例如:

User.hbm.xml

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping

    PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping>

 

    <class name="onlyfun.caterpillar.User" table="user">

        ....

        <set name="emails" table="email" order-by="address desc">

            <key column="id"/>

            <element type="java.lang.String"

                     column="address"/>

        </set>

    </class>

 

</hibernate-mapping>

观察Hibernate所使用的SQL可以看到order by子句:

Hibernate:

select emails0_.id as id0_, emails0_.address as address0_

from email emails0_ where emails0_.id=? order by emails0_.address desc

97容器的延迟初始(Lazy Initialization

有时候您只是想要获得对象中某个属性的数据,如果您的对象中包括Set等容器对象,若从数据库中加载数据时全部加载所有的对象,却只是为了取得某个属性,显然的这样很没有效率。

Set中的范例来说,如果您只是想取得对象之后,显示对象的某些属性,例如name属性:

Session session = sessionFactory.openSession();

User user = (User) session.load(User.class, new Integer(1));

System.out.println(user.getName());

session.close();

在这个例子中,email的信息不必要从数据库中全部加载,在Hibernate中支持容器的延迟初始(Lazy onitialization),只有在真正需要容器对象中的数据时,才从数据库中取得数据,预设容器类会使用延迟加载的功能,例如上面的程序实际上会使用以下的SQL

Hibernate: select user0_.id as id0_, user0_.name as name0_0_ from user user0_ where user0_.id=?

可以藉由映像文件中的lazy属性来设定是否使用延迟初始,例如在映射文件中如下设定:

User.hbm.xml

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping

    PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping>

 

    <class name="onlyfun.caterpillar.User" table="user">

        ....

        <set name="emails" table="email" lazy="false">

            <key column="id"/>

            <element type="java.lang.String"

                     column="address"/>

        </set>

    </class>

 

</hibernate-mapping>

由于lazy属性被设定为false,延迟初始的功能被关闭,所以上面的程序会使用以下的SQL来查询:

Hibernate:

select user0_.id as id0_, user0_.name as name0_0_

from user user0_ where user0_.id=?

Hibernate:

select emails0_.id as id0_, emails0_.address as address0_

from email emails0_ where emails0_.id=?

所有的容器对象之数据一并被查询了,即使程序中还不会使用到容器中的对象信息。

在启用延迟初始的情况下,如果如下查询数据:

Session session = sessionFactory.openSession();

User user = (User) session.load(User.class, new Integer(1));

System.out.println(user.getName());

Iterator iterator = user.getEmails().iterator();

while(iterator.hasNext()) {

    System.out.println(iterator.next());

}

session.close();

在开启SQL显示的情况下,会显示以下的内容:

Hibernate:

select user0_.id as id0_, user0_.name as name0_0_

from user user0_ where user0_.id=?

 

caterpillar

 

Hibernate:

select emails0_.id as id0_, emails0_.address as address0_

from email emails0_ where emails0_.id=?

 

caterpillar.onlyfun@yahoo.com

caterpillar.onlyfun@gmail.com

可以看到,只有在需要查询容器中对象时,才会向数据库索取数据。

使用延迟初始时,由于在需要数据时会向数据库进行查询,所以session不能关闭,如果关闭会丢出LazyInitializationException 例外,例如下面的程序就会丢出例外:

Session session = sessionFactory.openSession();

User user = (User) session.load(User.class, new Integer(1));

System.out.println(user.getName());

 

session.close();

 

Iterator iterator = user.getEmails().iterator();

while(iterator.hasNext()) {

    System.out.println(iterator.next());

}

如果您使用了延迟初始,而在某些时候仍有需要在session关闭之后取得相关对象,则可以使用Hibernate.initialize()来先行加载相关对象,例如:

Session session = sessionFactory.openSession();

User user = (User) session.load(User.class, new Integer(1));

System.out.println(user.getName());

 

Hibernate.initialize(user.getEmails()); // 先加载容器中的对象

 

session.close();

 

Iterator iterator = user.getEmails().iterator();

while(iterator.hasNext()) {

    System.out.println(iterator.next());

}

即使启用延迟初始,在Hibernate.initialize()该行,email容器中的对象已经被加载,所以即使关闭session也无所谓了,这种情况发生在某个情况下,您启用了延迟初始,而使用者操作过程中,会在稍后一阵子才用到email容器,您不能浪费session在这段时间的等待上,所以您先行加载容器对象,直接关闭session以节省资源。

 
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值