欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

整合Spring Data JPA 和 Spring

程序员文章站 2022-04-25 19:31:40
...

pom.xml

使用Spring Data JPA,需要整合Spring与Spring Data JPA,并且需要提供JPA的服务提供者hibernate,所以需要导入spring相关坐标,hibernate坐标,数据库驱动坐标等

(可能存在版本冲突的问题)

<properties>
        <spring.version>4.2.4.RELEASE</spring.version>
        <hibernate.version>5.0.7.Final</hibernate.version>
        <slf4j.version>1.6.6</slf4j.version>
        <log4j.version>1.2.12</log4j.version>
        <c3p0.version>0.9.1.2</c3p0.version>
        <mysql.version>5.1.6</mysql.version>
</properties>

    <dependencies>
        <!-- junit单元测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>
        
        <!-- spring beg -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        
        <!-- spring end -->

        <!-- hibernate beg -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.1.Final</version>
        </dependency>
        <!-- hibernate end -->

        <!-- c3p0 beg -->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>${c3p0.version}</version>
        </dependency>
        <!-- c3p0 end -->

        <!-- log end -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <!-- log end -->

        
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
        
        <!-- el beg 使用spring data jpa 必须引入 -->
        <dependency>  
            <groupId>javax.el</groupId>  
            <artifactId>javax.el-api</artifactId>  
            <version>2.2.4</version>  
        </dependency>  
          
        <dependency>  
            <groupId>org.glassfish.web</groupId>  
            <artifactId>javax.el</artifactId>  
            <version>2.2.4</version>  
        </dependency> 
        <!-- el end -->
    </dependencies>

applicationContext.xml

配置spring的配置文件(配置spring Data jpa的整合, 将jpa交给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:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
		http://www.springframework.org/schema/data/jpa 
		http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
	
<!--注意:1.实体类所在的包。2.DAO所在的包。3.Spring自己的扫描包。-->
	<!-- 1.dataSource 配置数据库连接池-->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="com.mysql.jdbc.Driver" />
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/数据库" />
		<property name="user" value="root" />
		<property name="password" value="root" />
	</bean>
	
	<!-- 2.配置entityManagerFactory对象, 交给Spring容器管理 -->
	<bean id="entityManagerFactory" 
            class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="dataSource" />

        <!--配置了Entity的实体类, 自动注册到容器中-->
		<property name="packagesToScan" value="实体类所在包" />

        <!--JPA的实现厂家-->
		<property name="persistenceProvider">
			<bean class="org.hibernate.jpa.HibernatePersistenceProvider" />
		</property>
  
		<!--JPA的供应商适配器-->
		<property name="jpaVendorAdapter">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <!--是否自动创建数据库表-->
				<property name="generateDdl" value="false" />
                <!--指定数据库类型-->
				<property name="database" value="MYSQL" />
                <!--数据库方言: 不同数据库支持的特有语法-->
				<property name="databasePlatform"         
                          value="org.hibernate.dialect.MySQLDialect" />
                <!--是否显示sql语句-->
				<property name="showSql" value="true" />
			</bean>
		</property>

        <!--jpa的方言 : 指定高级的特性, 如果不用, 可以不写-->
		<property name="jpaDialect">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
		</property>
	</bean>
    
	
	<!-- 3.事务管理器-->
	<!-- JPA事务管理器  -->
	<bean id="transactionManager"             
          class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />
	</bean>
	
	<!-- 整合spring data jpa-->
	<jpa:repositories base-package="dao接口所在的包"
		transaction-manager-ref="transactionManager"
		entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>
		
	<!-- 4.txAdvice, 声明式事务 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="save*" propagation="REQUIRED"/>
			<tx:method name="insert*" propagation="REQUIRED"/>
			<tx:method name="update*" propagation="REQUIRED"/>
			<tx:method name="delete*" propagation="REQUIRED"/>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="find*" read-only="true"/>
			<tx:method name="*" propagation="REQUIRED"/>
		</tx:attributes>
	</tx:advice>
	
	<!-- 5.aop-->
	<aop:config>
		<aop:pointcut id="pointcut" expression="execution(* cn.itcast.service.*.*(..))" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />
	</aop:config>
	
    <!--配置包扫描, 因为有一些注解需要被扫描到, 如Component, Service, Controller-->
	<context:component-scan base-package="cn.itcast"></context:component-scan>
		
	<!--组装其它 配置文件-->
	
</beans>

使用JPA注解配置映射关系

     见原生JPA的使用文档, 配置实体类和表的映射

编写Dao层接口

      使用Spring Data JPA,只需要按照框架的规范提供dao接口,不需要实现类就可以完成数据库的增删改查、分页查询等方法的定义,极大的简化了我们的开发过程。

      在Spring Data JPA中,对于定义符合规范的Dao层接口,我们只需要遵循以下几点就可以了:

      1.创建一个Dao层接口,并实现JpaRepository和JpaSpecificationExecutor

      2.提供相应的泛型

/**
 * JpaRepository<实体类类型,主键类型>:用来完成基本CRUD操作
 * JpaSpecificationExecutor<实体类类型>:用于复杂查询(分页等查询操作)
 */
public interface CustomerDao extends JpaRepository<Customer, Long>, JpaSpecificationExecutor<Customer> {
}

各种查询

保存(修改), 删除方法

     调用save(obj)方法

     *   如果执行此方法是对象中存在id属性,即为更新操作会先根据id查询,再更新    

     *   如果执行此方法中对象中不存在id属性,即为保存操作

      调用delete(id)方法: 根据id删除

I.基本查询
        dao.findOne(id) - 用ID进行查询,立即加载。
        dao.getOne(id) - 用ID进行查询,懒加载。
        dao.findAll() - 查询全部
II.基于JPQL进行查询
        1.在DAO接口里面添加方法。
        2.在方法上面添加@Query注解。
        3.在@Query注解写JPQL语句

 //传参的三种方式: ①顺序一致; ②指定参数的索引; ③起别名
 @Query("from Customer where name like ? or industry like ?")
 List<Customer> getListAll(String name,String industry);
    
 @Query("from Customer where name like ?2 or industry like ?1")
 List<Customer> getListAll(String industry,String name);
    
 @Query("from Customer where name like :name or industry like :industry")
 List<Customer> getListAll(@Param("industry")String industry,@Param("name") String name);

      如果要用JPQL做保存,删除和修改操作:
            1.在DAO接口里面添加方法。
            2.在方法上面添加@Query注解。
            3.在@Query注解写JPQL语句
            4.在方法上面添加@Modifying
            @Query("update Customer set address=?1 where id=?2")
            @Modifying
            void updateCustomer(String address,Long id);

III.基于原生SQL进行查询
        1.在DAO接口里面添加方法。
        2.在方法上面添加@Query注解。
        3.在@Query注解写SQL语句,和nativeQuery=true

// nativeQuery : 使用本地sql的方式查询 
 @Query(value="select * from customer",nativeQuery=true)
 public List<Customer> findSql();

IV.方法命名规则查询
        操作   + By + 属性名 + 比较运算(like等运算) + 【And|Or  属性名 + 比较运算(like等运算)】
        find   + By + Name + Like
    eg: 
        findByNameLike(String name);
       == select * from Customer where name like ?
        
  ** 比较运算如果是等于号可以省略**
        findById(Long id)
        
   find|read|get|query|stream|count|delete|remove + By + 属性名 + 查询方式 + [And | Or + 属性名 + 查询方式] 

V.动态条件查询 *****
   JpaSpecificationExecutor中定义的方法
        /**
         * 查询一个对象
         */
        T findOne(Specification<T> spec);

        /**
         * 查询多个对象
         */
        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 - 这个就是用来动态拼接查询条件的类。(构造的就是查询条件)

Specification接口中只定义了如下一个方法:
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
        root负责找到属性,cb负责比较属性值。

 public List<Customer> query(Customer customer){
      List<Customer> list = customerDao.findAll(new Specification<Customer>() {
         @Override
         public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                    if(customer==null){
                        return null;
                    }
                    List<Predicate> list = new ArrayList<>();
                    if(customer.getId()!=null){
                        Predicate id = cb.equal(root.get("id"), customer.getId());
                        list.add(id);
                    }
                    if(customer.getAddress()!=null && !"".equals(customer.getAddress())){
                        Predicate address = cb.like(root.get("address").as(String.class), "%" + customer.getAddress() + "%");
                        list.add(address);
                    }
                    if(customer.getPhone()!=null && !"".equals(customer.getPhone())){
                        Predicate phone = cb.equal(root.get("phone"), customer.getPhone());
                        list.add(phone);
                    }
                    // TODO ....
                    return cb.and(list.toArray(new Predicate[]{}));
                }
            });
            return list;
        }