在编写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();
    }
}