`

hibernate4.0官方文档学习随笔

阅读更多
public class Event{
	Long id;
	String title;
	Date date;
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public Date getDate() {
		return date;
	}
	public void setDate(Date date) {
		this.date = date;
	}
}


<hibernate-mapping package="org.hibernate.tutorial.domain">
	<class name="Event" table="EVENTS">
		<id name="id" column="EVENTS_ID">
			<generator class="native"></generator>
		</id>
		<property name="date" type="timestamp" column="EVENTS_DATE"/>
		<property name="title"/>
	</class>
</hibernate-mapping>




关于实体映射文件中的type属性中指定的属性值,既不是java中的类型,也不是数据库中的数据类型,而是"Hibernate Mapping Types" 用于java类中属性的类型与数据库字段类型的映射。如果省略了type字段,hibernate将自动尝试用正确的类型去匹配。
另外hibernate官方文档中提示:在处理实体映射文件时如果省略type属性时hibernate将使用反射技术对类型尝试进行匹配,这是一个耗费资源和时间的操作,因此出于对性能和资源的影响,最好在映射文件的属性中都加入type属性。


========================================================================================================================================
hibernate.cfg.xml文件中关于session的配置
<!-- Enable Hibernate's automatic session context management -->
 <property name="current_session_context_class">thread</property>


获取current Session
Session  session = HibernateUtil.getSessionFactory().getCurrentSession();



调用getCurrentSession()方法总是返回"当前"的工作单元,这与hibernate.cfg.xml配置文件中(<property name="current_session_context_class">thread</property>
)是有关系的org.hibernate.Session被设计用来表示单一的工作单元,getCurrentSession()方法返回的session,将与当前的java线程绑定来处理相关的操作,当事务提交\结束\回滚时,hibernate会将该session自动与当前线程解除绑定并关闭,再次调用getCurrentSession()方法,返回的又是一个新的session(工作单元)
另外:在hibernate中提供了三种方式用于对current session 进行管理,配置文件中"thread"值的配置不建议在生产上使用,当前只是为了小的demo的演示,具体讲解放到后面


(1)增加一个Person对象 person中包含event
public class Person {
	private Long id;
	private int age;
	private String firstname;
	private String lastname;
	
	Set events = new HashSet();
//增加set\get方法
}

(2)配置文件
<class name="Person" table="PERSON">
    <id name="id" column="PERSON_ID">
        <generator class="native"/>
    </id>
    <property name="age"/>
    <property name="firstname"/>
    <property name="lastname"/>

    <set name="events" table="PERSON_EVENT">
        <key column="PERSON_ID"/>
        <many-to-many column="EVENT_ID" class="Event"/>
    </set>

</class>


(3)数据库表关系映射说明:


(4)测试
private void addPersonToEvent(Long personId, Long eventId) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();

        Person aPerson = (Person) session.load(Person.class, personId);
        Event anEvent = (Event) session.load(Event.class, eventId);
        aPerson.getEvents().add(anEvent);

        session.getTransaction().commit();
}

测试说明:



通过上面的代码可以看到:我们不需要显式的执行update或者save方法,hibernate会自动探测到某些属性值发生变化了,需要更新,这叫做"automatic dirty checking" 只要数据处在"persistent stat"状态,会绑定一个当前独有的org.hibernate.Session对象,hibernate会监视任何的变化并在后台生成相关的SQL语句,在调用flushing/commit/rollback等方法后会进行内存与数据库的同步,把变化的数据持久化到数据库。

不同session下的测试:
private void addPersonToEvent(Long personId, Long eventId) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();

        Person aPerson = (Person) session
                .createQuery("select p from Person p left join fetch p.events where p.id = :pid")
                .setParameter("pid", personId)
                .uniqueResult(); // Eager fetch the collection so we can use it detached
        Event anEvent = (Event) session.load(Event.class, eventId);

        session.getTransaction().commit();

        // End of first unit of work

        aPerson.getEvents().add(anEvent); // aPerson (and its collection) is detached

        // Begin second unit of work

        Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();
        session2.beginTransaction();
        session2.update(aPerson); // Reattachment of aPerson

        session2.getTransaction().commit();
    }


说明:
You can load person and event in different units of work. Or you can modify an object outside of a org.hibernate.Session, when it is not in persistent state (if it was persistent before, this state is called detached). You can even modify a collection when it is detached:
The call to update makes a detached object persistent again by binding it to a new unit of work, so any modifications you made to it while detached can be saved to the database. This includes any modifications (additions/deletions) you made to a collection of that entity object.
我们可以通过不同的session来装载对象,我们可以在这个对象不是"persistent state"状态时修改对象,调用update方法可以使detached状态的对象持久(会将对象绑定到一个新的session); 所以对于detached对象的任何的修改对可以被持久化到数据库。


非实体关系的xml映射  Person类中增加如下属性代码
private Set emailAddresses = new HashSet();

    public Set getEmailAddresses() {
        return emailAddresses;
    }

    public void setEmailAddresses(Set emailAddresses) {
        this.emailAddresses = emailAddresses;
    }

xml配置文件
        <set name="emailAddresses" table="PERSON_EMAIL_ADDR">
            <key column="PERSON_ID"/>
            <element type="string" column="EMAIL_ADDR"/>
        </set>

数据库映射关系:





这次的映射跟上次的映射唯一不同是把many-to-mangy 改成了element,此配置告诉hibernate,增加的该collection不参考任何的其他实体。其他个标签中属性配置的意义与前面例子中的events映射相同。

双向映射: 结合上面Person中单项映射Event类例子来看下面的代码
Event类增加如下代码:
private Set emailAddresses = new HashSet();

    public Set getEmailAddresses() {
        return emailAddresses;
    }

    public void setEmailAddresses(Set emailAddresses) {
        this.emailAddresses = emailAddresses;
    }

Event.hbm.xml代码
<set name="participants" table="PERSON_EVENT" inverse="true">
            <key column="EVENT_ID"/>
            <many-to-many column="PERSON_ID" class="Person"/>
        </set>

此处的核心是属性inverse的含义:






此处关于inverse的解释不是很清楚,后面文档中如有讲解到在进行补充。
  • 大小: 71.5 KB
  • 大小: 85.1 KB
  • 大小: 16.9 KB
  • 大小: 54.2 KB
  • 大小: 22.2 KB
  • 大小: 42.4 KB
  • 大小: 35.5 KB
  • 大小: 140.1 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics