Hibernate Core Reference Manual学习笔记——Chapter 1. Tutorial
Hibernate Core Reference Manual
Chapter 1. Tutorial
TableofContents
1.1.Part1-ThefirstHibernateApplication
1.1.1.Setup
1.1.2.Thefirstclass
1.1.3.Themappingfile
1.1.4.Hibernateconfiguration
1.1.5.BuildingwithMaven
1.1.6.Startupandhelpers
1.1.7.Loadingandstoringobjects
1.2.Part2-Mappingassociations
1.2.1.MappingthePersonclass
1.2.2.AunidirectionalSet-basedassociation
1.2.3.Workingtheassociation
1.2.4.Collectionofvalues
1.2.5.Bi-directionalassociations
1.2.6.Workingbi-directionallinks
1.3.Part3-TheEventManagerwebapplication
1.3.1.Writingthebasicservlet
1.3.2.Processingandrendering
1.3.3.Deployingandtesting
1.4.Summary
1.1.Part1-ThefirstHibernateApplication
JavaBean类有getter和setter方法,是一种推荐使用的设计模式。但对Hibernate而言并不是必须的。Hibernate可以直接访问类的属性。Hibernate可以访问public、private和protected修饰的getter和setter方法,就像它可以直接访问public、private和protected修饰的属性。
所有要被持久化的类都需要由无参的构造函数,因为Hibernate会使用反射来为你创建对象。构造函数可以是private的。howeverpackageorpublicvisibilityisrequiredforruntimeproxygenerationandefficientdataretrievalwithoutbytecodeinstrumentation.
Hibernate需要知道如何加载和保存持久化类的对象。这就是Hibernate配置文件的作用。配置文件告诉Hibernate去访问数据库中的哪张表,哪些列。
在Hibernate配置文件里使用的type不是java数据类型,也不是SQL数据类型,而是Hibernate映射类型。转换器可以从java类型转换到SQL类型,也可以反过来。如果没有配置type,Hibernate会尝试确定正确的映射类型。在某些场合下,这种使用java反射技术的自动检测并不能得出你期望的结果。比如说java.util.Date类型,Hibernate不知道是应该映射到SQL的date、timestamp还是time类型。同时这种自动检测会耗费时间和资源,如果注重性能,最好明确的配置type属性。
SessionFactory是一个全局的工厂,代表一个特定的数据库。如果你有好几个数据库,你应该在配置文件里配置多个SessionFactory。
If you give the org.hibernate.SessionFactory a name in your configuration, Hibernate will try to bind it to JNDI under that name after it has been built. Another, better option is to use a JMX deployment and let the JMX-capable container instantiate and bind a HibernateService to JNDI. Such advanced options are discussed later.涉及到很多陌生的名词,先看概念吧。The getCurrentSession() method always returns the "current" unit of work.还记得我们在hibernate.cfg.xml文件中的配置吧
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 省略了无关内容 --> <!-- Enable Hibernate's automatic session context management --> <property name="current_session_context_class">thread</property> </session-factory> </hibernate-configuration>
Hibernate会根据上面的配置把当前工作单元的上下文与当前的java线程绑定。
当你第一次调用getCurrentSession()时,会生成一个org.hibernate.Session,然后,Hibernate将Session绑定到当前线程。当事务结束时,不论是提交还是回滚,Hibernate会自动将Session与当前线程解除绑定,并关闭Session。如果你再一次调用getCurrentSession(),你会得到一个新的org.hibernate.Session,并可以开始一个新的工作单元。
org.hibernate.Session的scope非常灵活,你不应该为每一个数据库操作都创建一个新的org.hibernate.Session。
1.2.Part2-Mappingassociations
Thedesignquestionsyouhavetodealwithare:directionality,multiplicity,andcollectionbehavior.
Hibernate automatically detects that the Object has been modified and needs to be updated. This is called automatic dirty checking.只要对象还处在persistent状态,比如说通过session.load()方法加载的对象/** * Return the persistent instance of the given entity class with the given identifier, * assuming that the instance exists. This method might return a proxied instance that * is initialized on-demand, when a non-identifier method is accessed. * <br><br> * You should not use this method to determine if an instance exists (use <tt>get()</tt> * instead). Use this only to retrieve an instance that you assume exists, where non-existence * would be an actual error. * * @param entityName a persistent class * @param id a valid identifier of an existing persistent instance of the class * @return the persistent instance or proxy * @throws HibernateException */ public Object load(String entityName, Serializable id) throws HibernateException;
也就是说对象还绑定在某个特定的 org.hibernate.Session上,Hibernate监测任何改变,并后台执行SQL。将内存和数据库进行同步的过程,通常发生在一个工作单元的最后(比如说commit或rollback),称为flushing。
如果一个处于persistent状态的对象与org.hibernate.Session断开绑定,这种状态称为detached。在detached状态所做的任何改变,可以通过update方法进行持久化。
Hibernate把所有JDK类型看成值类型(value types)。你也可以创建自己的值类型。要注意值类型集合与实体类型集合在映射上的区别。<set name="participants" table="PERSON_EVENT" inverse="true"> <key column="EVENT_ID"/> <many-to-many column="PERSON_ID" class="Person"/> </set>
映射文件中,inverse属性是用来干什么的呢?对于你,对于Java,一个双向连接就是一个简单的双方的引用。但是对Hibernate而言,它并没有足够的信息来正确组织SQL INSERT和UPDATE语句(从而避免约束冲突)。使某一侧的关联inverse,会告诉Hibernate将其看作是另一侧的镜像。这就是Hibernate为了解决从一个关系模型到数据库模式转换过程中出现的问题所需要的全部信息。
1.3. Part 3 - The EventManager web application
在一个request中使用一个HibernateSession。而不是每一个数据库操作都使用一个Session。
the session-per-request pattern. Instead of the transaction demarcation code in every servlet, you could also write a servlet filter. See the Hibernate website and Wiki for more information about this pattern called Open Session in View. You will need it as soon as you consider rendering your view in JSP, not in a servlet.