spring data jpa 学习笔记

Spring Data Jpa是Spring中为简化数据库操作,基于JPA封装的一套框架。这个框架的主要作用是为了把我们从反复,复杂的数据库操作中解放出来。

首先,Spring Data Jpa的官方学习地址:http://docs.spring.io/spring-data/jpa/docs/current/reference/html/

其次,该项目测试代码地址:https://github.com/mj3018/7-4test/tree/master/springjpaTest 这个项目上面测试了CRUDRepository接口,JpaRepository接口,JpaSpecificationExecutor接口中的

CRUD操作,多条件分页查询,自定义接口,自定义接口实现根据EntityManager进行数据库操作等

1.1 核心概念

  •      Spring Data Jpa的核心接口是Repository,这个接口是一个空接口,在使用的时候需要只需要指定该接口的Entity类(对应泛型T)及id类型(对应ID)即可。
public interface Repository<T, ID extends Serializable> {

}
  •  CRUDRepository接口,这个接口继承Repository接口,添加CRUD方法。
@NoRepositoryBean
public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> {

	<S extends T> S save(S entity);	
	<S extends T> Iterable<S> save(Iterable<S> entities);	
	T findOne(ID id);	
	boolean exists(ID id);
	Iterable<T> findAll();
	Iterable<T> findAll(Iterable<ID> ids);	
	long count();
	void delete(ID id);
	void delete(T entity);	
	void delete(Iterable<? extends T> entities);
	void deleteAll();
}

 

  • PagingAndSortingRepository 继承CRUDRepository接口,新增分页与排序的功能。
public interface PagingAndSortingRepository<T, ID extends Serializable>   extends CrudRepository<T, ID> { 
  Iterable<T> findAll(Sort sort); 
  Page<T> findAll(Pageable pageable); 
}

 

  • JpaRepository 继承PagingAndSortingRepository接口,在PagingAndSortingRepository接口基础上新增了一些比较常用的数据库操作,比如:多条件查询。
@Override
<S extends T> List<S> findAll(Example<S> example);
  •  另外在SpringDataJpa中一个比较重要的接口:JpaSpecificationExecutor。通过这个接口可以实现多条件分页查询。
//多条件查询某一个具体的entity
T findOne(Specification<T> spec);


//多条件查询满足条件的所有的entity
List<T> findAll(Specification<T> spec);

//多条件分页查询
Page<T> findAll(Specification<T> spec, Pageable pageable);

//多条件排序查询
List<T> findAll(Specification<T> spec, Sort sort);

//多条件统计满足条件的总数
long count(Specification<T> spec);

 

 Specification这个是查询的条件,构造这个查询条件的方式为:User对应的是Entity类,UserDto是查询条件。

private Specification<User> buildSpecification(final UserDto userDto) {
        return new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate predicate = cb.conjunction();
                if(userDto.getName() != null) {
                    predicate.getExpressions().add(
                            cb.like(root.<String>get("name"),userDto.getName()+"%")
                    );
                }
                if(userDto.getAddress() != null) {
                    predicate.getExpressions().add(
                            cb.like(root.<String>get("address"),userDto.getAddress()+"%")
                    );
                }
                if(userDto.getPhone() != null) {
                    predicate.getExpressions().add(
                            cb.like(root.<String>get("phone"),userDto.getPhone()+"%")
                    );
                }
                return predicate;
            }
        };
    }

 

这里也把一个多条件分页查询的使用代码贴在这里吧:UserDto是查询的条件,Specification是根据UserDto封装出来的查询条件,Pageable对应的是分页条件。

@Test
    public void testMultiQueryPage(){
        UserDto userDto = new UserDto();
        userDto.setName("name");
        Specification<User> specs = buildSpecification(userDto);

        Pageable pageable = new PageRequest(1,2);
        Page<User> page = this.userService.findAdd(specs,pageable);
        Iterator<User> iterator = page.iterator();
        while(iterator.hasNext()) {
            System.out.println(iterator.next());
            System.out.println("************************************************");
        }
        System.out.println(page.getContent());
    }
  •  spring Data Jpa配置文件:
<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-4.1.xsd
          http://www.springframework.org/schema/aop
          http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
          http://www.springframework.org/schema/tx
          http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
          http://www.springframework.org/schema/cache
          http://www.springframework.org/schema/cache/spring-cache-4.1.xsd
          http://www.springframework.org/schema/data/jpa
          http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
          http://www.springframework.org/schema/data/repository
        http://www.springframework.org/schema/data/repository/spring-repository-1.5.xsd">

    <!-- scan the package and the sub package -->
    <context:component-scan base-package="com.spring"/>


    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"/>
        <property name="suffix" value=".jsp" />
    </bean>

    <!--配置数据库-->
    <bean class="org.apache.commons.dbcp.BasicDataSource"
          destroy-method="close" id="dataSource">
        <property name="driverClassName" value="org.postgresql.Driver" />
        <property name="url" value="jdbc:postgresql://localhost:5432/demo" />
        <property name="username" value="demo" />
        <property name="password" value="demo" />
        <property name="testOnBorrow" value="true" />
        <property name="testOnReturn" value="true" />
        <property name="testWhileIdle" value="true" />
        <property name="timeBetweenEvictionRunsMillis" value="1800000" />
        <property name="numTestsPerEvictionRun" value="3" />
        <property name="minEvictableIdleTimeMillis" value="1800000" />
        <property name="validationQuery" value="SELECT version();" />
        <property name="initialSize" value="1" />
        <property name="maxActive" value="32" />
        <property name="maxIdle" value="16" />
    </bean>
    
    <!-- 使用cglib进行动态代理 -->
    <aop:aspectj-autoproxy proxy-target-class="true" />
    <!-- 支持注解方式声明式事务 -->
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
    <!-- dao -->
    <jpa:repositories base-package="com.spring.repository" repository-impl-postfix="Impl" 
                      entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager" />
    <!-- 实体管理器 -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.spring" />
        <property name="persistenceProvider">
            <bean class="org.hibernate.ejb.HibernatePersistence" />
        </property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="generateDdl" value="false" />
                <property name="database" value="POSTGRESQL" />
                <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
                <property name="showSql" value="true" />
            </bean>
        </property>
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
        </property>
        <property name="jpaPropertyMap">
            <map>
                <entry key="hibernate.query.substitutions" value="true 1, false 0" />
                <entry key="hibernate.default_batch_fetch_size" value="16" />
                <entry key="hibernate.max_fetch_depth" value="2" />
                <entry key="hibernate.generate_statistics" value="true" />
                <entry key="hibernate.bytecode.use_reflection_optimizer" value="true" />
                <entry key="hibernate.cache.use_second_level_cache" value="false" />
                <entry key="hibernate.cache.use_query_cache" value="false" />
            </map>
        </property>
    </bean>

    <!-- 事务管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

    <bean class="org.springframework.data.web.config.SpringDataWebConfiguration"></bean>
</beans>

 在上面这个配置文件中几个比较重要的配置有:

  • 支持SpringDataJpa数据库操作的包采用base-package、配置自定义实现Dao操作的类采用repository-impl-postfix、指定EntityManagerFactory采用entity-manager-factory-ref、事物的指定采用transaction-manager-ref
  • 接下来是实体管理器,这里需要指定persistenceProvider(就是使用SpringDataJpa的时候需要指定实现这个数据库操作的具体的实现ORM框架,这里采用Hibernate)的值为org.hibernate.ejb.HibernatePersistence。指定一个packageToScan指定扫描的包。接下来其他的配置基本上都是数据库的一些配置。

 

<!-- dao -->
    <jpa:repositories base-package="com.spring.repository" repository-impl-postfix="Impl"
                      entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager" />

 

 

<!-- 实体管理器 -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.spring" />
        <property name="persistenceProvider">
            <bean class="org.hibernate.ejb.HibernatePersistence" />
        </property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="generateDdl" value="false" />
                <property name="database" value="POSTGRESQL" />
                <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
                <property name="showSql" value="true" />
            </bean>
        </property>
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
        </property>
        <property name="jpaPropertyMap">
            <map>
                <entry key="hibernate.query.substitutions" value="true 1, false 0" />
                <entry key="hibernate.default_batch_fetch_size" value="16" />
                <entry key="hibernate.max_fetch_depth" value="2" />
                <entry key="hibernate.generate_statistics" value="true" />
                <entry key="hibernate.bytecode.use_reflection_optimizer" value="true" />
                <entry key="hibernate.cache.use_second_level_cache" value="false" />
                <entry key="hibernate.cache.use_query_cache" value="false" />
            </map>
        </property>
    </bean>
<!-- 事务管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值