-
Notifications
You must be signed in to change notification settings - Fork 2.9k
JPA
Spring Data JPA在JPA上又做了一层封装,只要编写接口就够了,不用写一行实现代码,CRUD方法啦,分页啦,自动将findByLoginName()的方法定义翻译成适当的QL啦都由它包了:
public interface UserDao extends PagingAndSortingRepository<User, Long> {
User findByLoginName(String loginName);
}
使用上很简单,快速浏览一下下面的资料就够了。
智能地翻译连Less,Not,And,Or都支持的方法名变成相应的JQL是它的一大卖点,比如下面的接口函数
User findByLoginNameOrEmail(String loginName, String email);
select user from User user where user.loginName=? or email =?
更厉害的是嵌套的属性也能翻译
Task findByUserId(Long id)
select task from Task task where task.user.id=?
它当然也可以直接用@Query在方法上标注复杂的查询语句。
如果要执行批量更新/删除语句,同样基于@Query编写。
@Modifying
@Query("update AccountInfo a set a.salary = ?1 where a.salary < ?2")
public int increaseSalary(int after, int before);
预先封装好的分页与排序功能也是一大卖点,只要在接口定义时多丢一个Pageable或Sort参数就可以了,在Quickstart中有分页与排序的详细演示
Page<Task> findByUserId(Long id, Pageable pageRequest);
只有一个坑爹的地方,如果要为UserDao扩展方法(而不是接口),要新增一个UserDaoCustom接口,这时候,实现类的名字必须是UserDaoImpl,而不是UserDaoCustomImpl。
###资料
- 官方文档
- 使用 Spring Data JPA 简化 JPA 开发 IBM DW上很好的中文版教程.
彻底删除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>
数据库的表名,列名与Entity对应的规则,最常见的一个需求是把LOGIN_NAME翻译成loginName,Hibernate提供了ImprovedNamingStrategy, 在JPA中可以这样设置:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
</props>
</property>
</bean>
在quickstart里有一个JpaMappingTest,会遍历所有Entity,执行一次select操作看entity上的JPA annotation有没有问题,必备
hibernate很智能的,事务未提交前都不会轻易执行sql,为了让它执行,需要在测试用例里注入一个EntityManager
@PersistenceContext
private EntityManager em;
然后在每个save操作后面,跟一句em.flush();
暂时的Hibernates里有两个方法:
1.initLazyProperty(Object proxyedPropertyValue), 强制初始化对象的某个lazy load属性
Hibernates.initLazyProperty(user.getGroups());
- getDialect(DataSource dataSource),通过传入的dataSource,取出jdbc url然后判断出Dialect,这样就成功减少一个配置Dialect的配置项了。
- 所有Entity都继承于同一个定义了主键的IdEntity
- Showcase中Team与User的One to Many关系 及反向的User 与 Team的Many to One关系
- Showcase中User与Role的Many to Many关系
- Showcase中Team与Manager的One to One关系
在Entity的开头以@NamedQuery标注用到的sql,好处是JPA的实现会缓存这些JQL的编译结果,坏处就是在本来干净的Entity写满了JQL,而且那个name是一个字符串,不容易在IDE里快速定位到具体的语句。
所以还是用静态变量在DAO里定义JQL算了。
##3. Hibernate ##3.1 Hibernate二级缓存
- Hibernate二级缓存非必需
二级缓存主要用于按主键缓存对象及其关联的Collections。而对sql查询结果的缓存默认是不打开的,除非是非常静态,不怎么变化的数据集。 因为很多普通的CRUD管理系统并不需要非常高的性能还存在集群同步的风险,非常高的性能的系统可能会用memcached并自行精确控制,因此Hibernate自带的2nd系统并不是标配,仅放在showcase里进行演示。
- 新版的配置更新,原来的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>
##4. Log4jdbc 如果要想看到实际执行的sql和实际绑定的参数,可以使用log4jdbc,而hibernate自己的showsql看不到绑定的参数。 打开application.properties里jdbc driver换成log4jdbc的Driver,并在原来的jdbc url的中间加上log4jdbc
jdbc.driver=net.sf.log4jdbc.DriverSpy
jdbc.url=jdbc:log4jdbc:h2:file:~/.h2/quickstart;AUTO_SERVER=TRUE
然后在log4j.properties里定义log4jdbc的级别是info就行了。这里有两种选择:
#sql and execute time
log4j.logger.jdbc.sqltiming=INFO
#sql only
log4j.logger.jdbc.sqlonly=INFO
另外, 因为log4jdbc不在Maven中央库中,所以使用了一个替代品log4jdbc-remix.