Spring Data JPA 实现自动化的JPA Repository

    Spring Data JPA 可以终结样版式的愚蠢行为——仅仅因为要处理的领域类型不同,而要一遍遍写相同持久化的方法。

详细的代码,在github上。

Spring Data JPA 仅限于单个JPA查询。当需要做的事情无法通过Spring Data JPA来实现,可以使用传统的方式。

当Spring Data JPA 为Repository生成实现的时候,它还会查找名字与接口相同,并且添加了Impl后缀的一个类。如果这个类存在的话,Spring Data JPA将会把它的方法与Spring Data JPA所生成的方法合并一起。

项目的结构

Spring Data JPA 实现自动化的JPA Repository_第1张图片

一、引入jar包

    
      org.springframework.data
      spring-data-jpa
      2.1.6.RELEASE
    

二、使用Java方式(RootConfig.java)配置JPA ,配置Spring Data JPA

/**
 * 配置ContextLoaderListenerDataAPI的所有魔力, 扫描基础包,来查找拓展自Spring Data JPA Repository接口的所有接口,
 * 如果发现拓展自Repository的接口, 它会自动生成这个接口的实现。
 */
@Configuration
@ComponentScan(basePackages = {"com.hef.spittr"}, excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
        value = EnableWebMvc.class)})
@EnableJpaRepositories(basePackages = "com.hef.spittr.dao", entityManagerFactoryRef = "entityManagerFactoryBean")
public class RootConfig {

注意: 配置SpringDataJPA时,如果存在名称为  “entityManagerFactory ”的 Bean,就不需要定义 excludeFilters 参数了

   /**
     * 使用容器管理类型的JPA
     *
     * @param dataSource
     * @param jpaVendorAdapter 指明使用那一个厂商的JPA实现
     * @return
     */
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(DataSource dataSource,
                                                                           JpaVendorAdapter jpaVendorAdapter){
        LocalContainerEntityManagerFactoryBean emfb =
                new LocalContainerEntityManagerFactoryBean();
        emfb.setDataSource(dataSource);
        emfb.setJpaVendorAdapter(jpaVendorAdapter);
        // 扫描, 查找带有 @Entity 注解的类
        emfb.setPackagesToScan("com.hef.spittr.domain");
        return emfb;
    }

    /**
     * 使用Hibernate厂商的Jpa实现 jpaVendorAdapter
     * @return
     */
    @Bean
    public JpaVendorAdapter jpaVendorAdapter(){
        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setDatabase(Database.H2);
        adapter.setShowSql(true);
        adapter.setGenerateDdl(false);
        adapter.setDatabasePlatform("org.hibernate.dialect.H2Dialect");
        return adapter;

    }

    /**
     * @PersistenceContext 该注解是JPA规范提供的, 为了让Spring理解这些注解,并注入EntityManager,
     * 必须要配置 PersistenceAnnotationBeanPostProcessor
     * 
     * 注解会自动注册 PersistenceAnnotationBeanPostProcessor
     * @return
     */
    @Bean
    public PersistenceAnnotationBeanPostProcessor persistenceAnnotationBeanPostProcessor(){
        return new PersistenceAnnotationBeanPostProcessor();
    }

    /**
     * 异常转化,不是强制的,
     * 如果希望抛出特定的 JPA 或Hibernate 配置这个
     * @return
     */
    @Bean
    public BeanPostProcessor persistenceTranslation(){
        return new PersistenceExceptionTranslationPostProcessor();
    }

    @Bean
    public JpaTransactionManager transactionManager(){
        JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
        return jpaTransactionManager;
    }

三、定义业务实体的Repository(Dao)

import com.hef.spittr.domain.Spitter;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * 使用 Spring DataJPA终结 愚蠢的样版行为
 */
public interface SpitterDao extends JpaRepository {
}

四、测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {RootConfig.class})
@ActiveProfiles("dev")
public class SpitterDaoTest {

    @Autowired
    private SpitterDao spitterDao;

    @Test
    public void shouldNotNull(){
        Assert.assertNotNull(spitterDao);
    }

    @Test
    public void findAllSpitter(){
        List spitters = spitterDao.findAll();
        for (Spitter spitter: spitters){
            System.out.println(spitter);
        }
        Assert.assertNotNull(spitters);
    }

    @Test
    public void saveSpitter(){
        Spitter spitter = new Spitter();
        spitter.setFullName("spitter");
        spitter.setUsername("username");
        spitter.setPassword("password");
        spitter.setEmail("[email protected]");
        spitter.setUpdateByEmail(false);
        spitterDao.save(spitter);
    }

}

五、遇到的问题

问题一:写下下面的代码,报了下面的异常

@Component
@Transactional
public class SpitterServiceimpl implements SpitterService {

    @Autowired
    private SpitterDao spitterDao;

    @Override
    public Spitter findSpitterById(Long id) {
        return spitterDao.getOne(id);
    }
}

org.hibernate.LazyInitializationException: could not initialize proxy [con.hef.spittr.domain.Spitter#1] - no Session

解决方案:在实体bean上添加  @Proxy(lazy = false) 注解

@Entity
@Table(name = "spitter")
@Proxy(lazy = false)
public class Spitter implements Serializable {

 

你可能感兴趣的:(Spring)