在编写spring data jpa的dao时,只需在接口中按规约提供方法的声明即可.而有些业务实现无法通过声明方法或编写简单的SQL实现,这就需要扩展Spring Data JPA.
1.为某一个特定的Repositrory添加自定义方法.
注意:默认情况下,Spring Data 会在base-package中查找"接口名Impl"做为实现类,也可以通过 repository-impl-postfix声明后缀.
示例:
1. 准备领域对象
@Entity
public class Employee {
@Id
@GeneratedValue
private Integer id;
@Column
private String name;
// 省略get/set方法...
}
2.定义一个接口,声明要添加的方法.
public interface EmployeeDao {
void method();
}
3.提供该接口的实现类,类名需要符合EntityNameRepositoryImpl格式,并提供实现方法.
public class EmployeeRepositoryImpl implements EmployeeDao {
//获取当前线程的EntityManager实例
@PersistenceContext
private EntityManager entityManager;
public void method() {
System.out.println("method..."+entityManager);
}
}
4.声明一个Repository接口,并继承EmplyeeDao接口.
public interface EmployeeRepository extends JpaRepository<Employee, Integer>,EmployeeDao{
}
5.使用
@ContextConfiguration("classpath:applicationContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class AppTest {
@Autowired
EmployeeRepository employeeRepository;
@Test
public void test02(){
employeeRepository.method();
}
}
2.为所有的Repositrory添加自定义方法.
示例:
1.声明一个接口,在该接口中声明需要自定义的方法,该接口需要继承spring data 的Repository接口或 其子接口.
@NoRepositoryBean
public interface BaseRepository<T,ID extends Serializable> extends JpaRepository<T,ID> {
//全局共享的自定义方法
void method();
}
2.提供BaseRepository的实现类,且继承SimpleJpaRepository,并提供方法的实现.注意:全局的扩展实 现类不要用RepositoryImpl作为后缀名,或为全局扩展接口添加@NoRepositoryBean注解告Spring data:该实现类不是一个Repository.
//实现类simpleBaseRepository
public class SimpleBaseRepository<T,ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> {
private final EntityManager entityManager;
public SimpleBaseRepository(JpaEntityInformation<T, ?> entityInformation,
EntityManager entityManager) {
super(entityInformation, entityManager);
this.entityManager=entityManager;
}
public SimpleBaseRepository(Class<T> domainClass, EntityManager em) {
super(domainClass, em);
this.entityManager=em;
}
//实现了全局自定义方法
public void method() {
System.out.println("--hello--");
}
}
3.定义一个RepositoryFactory工厂,生产BaseRepository的实现类SimpleBaseRepository的对象. 该工厂需要继承spring data jpa提供的JpaRepositoryFactory.
public class SimpleBaseRepositoryFactory extends JpaRepositoryFactory {
private final EntityManager em;
public SimpleBaseRepositoryFactory(EntityManager entityManager) {
super(entityManager);
this.em=entityManager;
}
@Override
@SuppressWarnings({"rawtypes","unchecked"})
protected Object getTargetRepository(RepositoryMetadata metadata) {
if(BaseRepository.class.isAssignableFrom(metadata.getRepositoryInterface())){
JpaEntityInformation<?,Serializable> entityInformation = getEntityInformation(metadata.getDomainType());
SimpleBaseRepository<?,Serializable> repository = new SimpleBaseRepository(entityInformation, em);
return repository;
}
return super.getTargetRepository(metadata);
}
@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
if(BaseRepository.class.isAssignableFrom(metadata.getRepositoryInterface())){
return SimpleBaseRepository.class;
}
return super.getRepositoryBaseClass(metadata);
}
}
4.定义JpaRepositoryFactoryBean的实现类,由它生成SimpleBaseRepositoryFactory工厂实例,从而生产SimpleBaseRepository的实例对象.
public class SimpleBaseRepositoryFactoryBean<T extends Repository<S,ID>,S,ID extends Serializable> extends JpaRepositoryFactoryBean<T, S, ID> {
@Override
protected RepositoryFactorySupport createRepositoryFactory(
EntityManager entityManager) {
return new SimpleBaseRepositoryFactory(entityManager);
}
}
5.最后需要在配置文件中指定<jpa:repositroies>中的factory-class属性指 定 SimpleBaseRepositoryFactoryBean,交由spring管理.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">
<description>Spring 应用配置</description>
<!-- 使用annotation 自动注册bean, 并保证@Required、@Autowired的属性被注入 -->
<context:component-scan base-package="com.zt.*"/>
<!-- 数据源配置 -->
<context:property-placeholder ignore-unresolvable="true" location="classpath*:/dataAccess.properties" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- Connection Info -->
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- Jpa Entity Manager 配置 -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" p:database="${jpa.database}"
p:showSql="${jpa.showSql}" p:generateDdl="true" />
</property>
<property name="packagesToScan" value="com.zt" />
</bean>
<!-- Jpa 事务配置 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
<!-- Spring Data Jpa配置 -->
<jpa:repositories base-package="com.zt.**.repository" repository-impl-postfix="Impl"
factory-class="com.zt.common.repository.support.SimpleBaseRepositoryFactoryBean" transaction-manager-ref="transactionManager"
entity-manager-factory-ref="entityManagerFactory" />
</beans>
6.测试
首先,准备实体对象.
@Entity
@Table(name="t_t_user")
public class User {
@Id
@GeneratedValue
private Integer id;
@Column
private String name;
//省略get/set方法
}
然后定义UserRepositroy接口.
public interface UserRepository extends BaseRepository<User, Integer>{
}
Junit测试:
@ContextConfiguration("classpath:applicationContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class AppTest {
//userRepository最后由spring注入进来的是SimpleBaseRepository.
@Autowired
private UserRepository userRepository;
@Test
public void test() {
userRepository.method();
}
}