29
JPA
Calvin edited this page 2013-11-14 01:37:15 +08:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

1.JPA

1.1 自动扫描Entity

彻底删除persistence.xml中Entity的逐一配置,采用自动扫描。因为Weblogic/Jboss这些自带JPA支持的应用服务器有时候会多管闲事的扫描persistence.xml,因此彻底删除掉这个文件是个不错的选择。

	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
		<property name="packagesToScan" value="org.springside.examples.quickstart"/>
	</bean>

1.2 NamingStrategy

数据库的表名,列名与Entity对应的规则,最常见的一个需求是把LOGIN_NAME翻译成loginName,Hibernate提供了ImprovedNamingStrategy, 在JPA中可以这样设置:

	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
		<property name="jpaProperties">
			<props>
				<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
			</props>
		</property>
	</bean>

1.3 测试

测试所有Mapping的Case

在quickstart里有一个JpaMappingTest,会遍历所有Entity,执行一次select操作看entity上的JPA annotation有没有问题,必备。

flush

hibernate很智能的,事务未提交前都不会轻易执行sql,为了让它执行一下以测试sql是否正确,需要在测试用例里注入一个EntityManager

	@PersistenceContext
	private EntityManager em;

然后在每个save操作后面,跟一句em.flush(); 当然,因为事务是默认回滚的,并不会真正提交到数据库。

1.4 Mapping演示

  1. 所有Entity都继承于同一个定义了主键的IdEntity
  2. Showcase中Team与User的One to Many关系 及反向的User 与 Team的Many to One关系
  3. Showcase中User与Role的Many to Many关系
  4. Showcase中Team与Manager的One to One关系

不过OneToMany的演示中没有适当的用例来设置(cascade = CascadeType.ALL, orphanRemoval = true),另外@Embeddable和@ElementCollection都还没有合适的用例来演示,以后尽量补上。

1.5 Tips

@NamedQuery?

在Entity的开头以@NamedQuery标注用到的sql,好处是JPA的实现会缓存这些JQL的编译结果,坏处就是在本来干净的Entity写满了JQL,而且那个name是一个字符串,不容易在IDE里快速定位到具体的语句。

所以还是在DAO接口里定义JQL算了。

日期字段使用JodaTime ?

见 Joda Time章节

##2. Hibernate ##2.1 Hibernate二级缓存

  1. Hibernate二级缓存非必需 二级缓存主要用于按主键缓存对象及其关联的Collections。而对sql查询结果的缓存默认是不打开的,除非是非常静态,不怎么变化的数据集。 因为很多普通的CRUD管理系统并不需要非常高的性能还存在集群同步的风险,非常高的性能的系统可能会用memcached并自行精确控制,因此Hibernate自带的2nd系统并不是标配,仅放在showcase里进行演示。

  2. 新版的配置更新,原来的Provider写法

<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">ehcache/ehcache-hibernate-local.xml</prop>

hibernate3.3后换成

<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
<prop key="net.sf.ehcache.configurationResourceName">ehcache/ehcache-hibernate-local.xml</prop>

3 SpringSide Modules

暂时的Hibernates里有两个方法:
1.initLazyProperty(Object proxyedPropertyValue), 强制初始化对象的某个lazy load属性

Hibernates.initLazyProperty(user.getGroups()); 
  1. getDialect(DataSource dataSource),通过传入的dataSource,取出jdbc url然后判断出Dialect,这样就成功减少一个配置Dialect的配置项了。 原来的写法
	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
		<property name="jpaProperties">
			<props>
				<prop key="hibernate.dialect">${hibernate.dialect}</prop>
			</props>
		</property>
	</bean>
	<bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />

现在改为

	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
        ...
	</bean>
	<bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
		<property name="databasePlatform">
			<bean factory-method="getDialect" class="org.springside.modules.persistence.Hibernates">
				<constructor-arg ref="dataSource"/>
			</bean>
		</property>
	</bean>

##4. Log4jdbc显示SQL 见DataSource章节的Log4jdbc显示SQL

##资料

  • Book:< Pro JPA 2 Mastering the Java Persistence API> 2009 最详细最罗嗦的手册