SpringDataJPA初识

以下内容引用尚硅谷,如有侵权请联系删除

第一章 SpringData概述

Spring Data : Spring的一个子项目。用于简化数据库访问,支持NoSQL和关系数据存储。其主要目标是使数据库的访问变得方便快捷。

SpringData项目所支持NoSQL存储

  • MongoDB (文档数据库)
  • Neo4j(图形数据库)
  • Redis(键/值存储)
  • Hbase (列族数据库)

SpringData项目所支持的关系数据存储技术

  • JDBC
  • JPA

第二章 JPASpringData概述

JPA Spring Data:致力于减少数据访问层(DAO)的开发量.开发者唯一要做的,就只是声明持久层的接口,其他都交给Spring Data JPA 来帮你完成!

框架怎么可能代替开发者实现业务逻辑呢?比如︰当有一个
UserDao.findUserByld()这样一个方法声明,大致应该能判断出这是根据给定条件的ID查询出满足条件的 User 对象。Spring Data JPA 做的便是规范方法的名字,根据符合规范的名字来确定方法需要实现什么样的逻辑。

第三章 Spring Data Jpa HelloWorld

![在这里插入图片描述]( https://img-blog.csdnimg.cn/4734f080acf941e3a61effb0fe390054.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

第四章 Repository接口

4.1 Repository接口概述

![在这里插入图片描述]( https://img-blog.csdnimg.cn/c6eb2d6f39c6435abefc30f142e64b1e.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

4.2 Repository的子接口

![在这里插入图片描述]( https://img-blog.csdnimg.cn/72434904216c406ba90c284822ae9f60.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

4.3 SpringData方法定义规范

简单条件查询

![在这里插入图片描述]( https://img-blog.csdnimg.cn/18e4a4c61b1e44c3ab056763f0921a95.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

支持的关键字

![在这里插入图片描述]( https://img-blog.csdnimg.cn/443728ed1d854914943857782001ceaa.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/3d06b6892ef549038e53a9d17a74a356.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

查询方法解析流程

![在这里插入图片描述]( https://img-blog.csdnimg.cn/6e0f8b14cff94cd6a86727d784b4489a.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

第五章 使用@Query注解

5.1 使用@Query自定义查询

![在这里插入图片描述]( https://img-blog.csdnimg.cn/96f7939e2c79449eb9beca1ccb3c67a5.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

5.2 索引参数与命名参数

![在这里插入图片描述]( https://img-blog.csdnimg.cn/92d619951afd426a90637a403dc32dcc.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/ed6e1f34309646a980512f0fe98adc7e.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

5.3 用@Query来指定本地查询

![在这里插入图片描述]( https://img-blog.csdnimg.cn/37a443d0474d4756ba75829ee7963c01.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

第六章 @Modifying 注解和事务

6.1 @Query 与@Modifying 执行更新操作

![在这里插入图片描述]( https://img-blog.csdnimg.cn/d143ef4436db4a359a46a684e0fe3f8d.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

6.2 事务

![在这里插入图片描述]( https://img-blog.csdnimg.cn/0d47403bc9eb4841b218579285984dd0.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

第七章 CrudRepository接口

![在这里插入图片描述]( https://img-blog.csdnimg.cn/53953f1eaa094ed999c6fd887e5fc999.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

第八章 PagingAndSortingRepository接口

![在这里插入图片描述]( https://img-blog.csdnimg.cn/1752b54cca4245d89bae0d0df37cfda8.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

第九章 JpaRepository接口

![在这里插入图片描述]( https://img-blog.csdnimg.cn/553b7f0e63c641e28a2130a351f79824.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

第十章 JpaSpecificationExecutor接口

详细使用方法可参考如下网站
https://blog.csdn.net/J080624/article/details/84581231
![在这里插入图片描述]( https://img-blog.csdnimg.cn/6a2f47a317da4ea5bbd0d679b7308211.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

![在这里插入图片描述]( https://img-blog.csdnimg.cn/4a4aa7f5c7674aa993fd049d4feb0cdc.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_17,color_FFFFFF,t_70,g_se,x_16)

第十一章 为某一个 Repository 上添加自定义方法

![在这里插入图片描述]( https://img-blog.csdnimg.cn/46568da8577b4ade859bd195a00ad29f.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/0d15ef644bf940eaae1b0e0ee29ad646.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_19,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/6202735583d644f78f6089c7335b5370.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

第十二章 代码阶段性总结

![在这里插入图片描述]( https://img-blog.csdnimg.cn/70dfa0414d3f406aa71a2915ea7b6ff2.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_12,color_FFFFFF,t_70,g_se,x_16)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>SpringData01</artifactId>
    <version>1.0-SNAPSHOT</version>

    <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>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>

        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <!--spring start-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.8</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 start-->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <!--hibernate-jap-->
        <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-->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>${c3p0.version}</version>
        </dependency>

        <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>


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

        <!--spring-data-jpa-->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.9.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.2.4.RELEASE</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>
    </dependencies>

</project>
jdbc.user=springcloud
jdbc.password=springcloud
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://172.16.19.104:3306/springdata
<?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:tx="http://www.springframework.org/schema/tx"
	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.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.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<!-- 配置自动扫描的包 -->
	<context:component-scan base-package="com.atguigu.springdata"></context:component-scan>

	<!-- 1. 配置数据源 -->
	<context:property-placeholder location="classpath:db.properties"/>

	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="user" value="${jdbc.user}"></property>
		<property name="password" value="${jdbc.password}"></property>	
		<property name="driverClass" value="${jdbc.driverClass}"></property>
		<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
		<!-- 配置其他属性 -->
	</bean>

	<!-- 2. 配置 JPA 的 EntityManagerFactory -->
	<bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<!--JPA适配器-->
		<property name="jpaVendorAdapter">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
		</property>
		<!--JPA注解扫描-->
		<property name="packagesToScan" value="com.atguigu.springdata"></property>
		<property name="jpaProperties">
			<props>
				<!-- 二级缓存相关 -->
				<!--
				<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
				<prop key="net.sf.ehcache.configurationResourceName">ehcache-hibernate.xml</prop>
				-->
				<!-- 生成的数据表的列的映射策略 -->
				<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
				<!-- hibernate 基本属性 -->
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.format_sql">true</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>
	</bean>

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

	<!-- 4. 配置支持注解的事务 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>

	<!-- 5. 配置 SpringData -->
	<!-- 加入jpa 的命名空间 -->
	<!-- base-package: 扫描 Repository Bean 所在的 package -->
	<jpa:repositories base-package="com.atguigu.springdata"
		entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>

</beans>

package com.atguigu.springdata;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import java.util.Date;

@Table(name="JPA_PERSONS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {

	@GeneratedValue
	@Id
	private Integer id;

	private String lastName;

	private String email;

	private Date birth;

	@JoinColumn(name = "ADDRESS_ID")
	@ManyToOne
	private Address address;

	private Integer addressId;


	@Override
	public String toString() {
		return "Person [id=" + id + ", lastName=" + lastName + ", email="
				+ email + ", brith=" + birth + "]";
	}
}

package com.atguigu.springdata;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Table(name="JPA_ADDRESSES")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Address {

    @Id
    @GeneratedValue
    private Integer id;

    private String province;

    private String city;

}

package com.atguigu.springdata;

public interface PersonDao {

    void test();

}

package com.atguigu.springdata;


import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

public class PersonRepsotoryImpl implements PersonDao {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public void test() {
        Person person = entityManager.find(Person.class, 1);
        System.out.println("--->"+person);
    }
}

package com.atguigu.springdata;


import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.Date;
import java.util.List;

/**
 * 1. Repository 是一个空接口. 即是一个标记接口
 * 2. 若我们定义的接口继承了 Repository, 则该接口会被 IOC 容器识别为一个 Repository Bean.
 * 纳入到 IOC 容器中. 进而可以在该接口中定义满足一定规范的方法.
 *
 * 3. 实际上, 也可以通过 @RepositoryDefinition 注解来替代继承 Repository 接口
 */
/**
 * 在 Repository 子接口中声明方法
 * 1. 不是随便声明的. 而需要符合一定的规范
 * 2. 查询方法以 find | read | get 开头
 * 3. 涉及条件查询时,条件的属性用条件关键字连接
 * 4. 要注意的是:条件属性以首字母大写。
 * 5. 支持属性的级联查询. 若当前类有符合条件的属性, 则优先使用, 而不使用级联属性.
 * 若需要使用级联属性, 则属性之间使用 _ 进行连接.
 */
//@RepositoryDefinition(domainClass=Person.class,idClass=Integer.class)
public interface PersonRepsotory extends JpaRepository<Person,Integer>, JpaSpecificationExecutor<Person> ,PersonDao{

    /**
     * 根据lastName来获取对应的Person
     * @param lastName
     * @return
     */
    Person getByLastName(String lastName);

    /**
     * WHERE lastName LIKE ?% AND id < ?
     * @param lastName
     * @param id
     * @return
     */
    List<Person> getByLastNameStartingWithAndIdLessThan(String lastName,Integer id);

    /**
     * WHERE lastName LIKE %? AND id < ?
     * @param lastName
     * @param id
     * @return
     */
    List<Person> getByLastNameEndingWithAndIdLessThan(String lastName,Integer id);

    /**
     * WHERE email IN (?, ?, ?) OR birth < ?
     * @param emails
     * @param birth
     * @return
     */
    List<Person> getByEmailInAndBirthLessThan(List<String> emails, Date birth);

    /**
     * WHERE a.id > ?
     * @param id
     * @return
     */
    List<Person> getByAddress_IdGreaterThan(Integer id);

    /**
     * 查询 id 值最大的那个 Person
     * 使用 @Query 注解可以自定义 JPQL 语句以实现更灵活的查询
     * @return
     */
    @Query("SELECT p from Person p WHERE p.id=(SELECT MAX(p2.id) FROM Person  p2)")
    Person getMaxIdPerson();

    /**
     * 为 @Query 注解传递参数的方式1: 使用占位符.
     * @param lastName
     * @param email
     * @return
     */
    @Query("SELECT p from Person p where p.lastName=?1 and p.email=?2")
    List<Person> testQueryAnnotationParams1(String lastName,String email);

    /**
     * 为 @Query 注解传递参数的方式2: 命名参数的方式.
     * @param lastName
     * @param email
     * @return
     */
    @Query("SELECT p from Person p where p.lastName=:lastName and p.email=:email")
    List<Person> testQueryAnnotationParams2(@Param("email") String email, @Param("lastName") String lastName);

    /**
     * SpringData 允许在占位符上添加 %%.
     * @param lastName
     * @param email
     * @return
     */
    @Query("SELECT p FROM Person p WHERE p.lastName LIKE %?1% OR p.email LIKE %?2%")
    List<Person> testQueryAnnotationLikeParam(String lastName, String email);

    /**
     * SpringData 允许在占位符上添加 %%.
     * @param email
     * @param lastName
     * @return
     */
    @Query("SELECT p FROM Person p WHERE p.lastName LIKE %:lastName% OR p.email LIKE %:email%")
    List<Person> testQueryAnnotationLikeParam2(@Param("email") String email, @Param("lastName") String lastName);

    /**
     * 设置 nativeQuery=true 即可以使用原生的 SQL 查询
     */
    @Query(value = "SELECT COUNT(id) from jpa_persons",nativeQuery = true)
    long getTotalCount();

    /**
     * 可以通过自定义的 JPQL 完成 UPDATE 和 DELETE 操作.
     * 注意: JPQL 不支持使用 INSERT
     * 在 @Query 注解中编写 JPQL 语句, 但必须使用 @Modifying 进行修饰. 以通知 SpringData, 这是一个 UPDATE 或 DELETE 操作
     * UPDATE 或 DELETE 操作需要使用事务, 此时需要定义 Service 层. 在 Service 层的方法上添加事务操作.
     * 默认情况下, SpringData 的每个方法上有事务, 但都是一个只读事务. 他们不能完成修改操作!
     * @param id
     * @param email
     */
    @Modifying
    @Query("UPDATE Person p SET p.email=:email where p.id=:id")
    void updatePersonEmail(@Param("id") Integer id,@Param("email") String email);
}

package com.atguigu.springdata;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class PersonService {

    @Autowired
    private PersonRepsotory personRepsotory;

    @Transactional
    public void updatePersonEmail(Integer id, String email){
        personRepsotory.updatePersonEmail(id,email);
    }

    @Transactional
    public void savePersons(List<Person> personList){
        personRepsotory.save(personList);
    }

}

import com.atguigu.springdata.Person;
import com.atguigu.springdata.PersonRepsotory;
import com.atguigu.springdata.PersonService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.sql.DataSource;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

public class SpringDataTest {

    private ApplicationContext ctx=null;

    private PersonRepsotory personRepsotory =null;

    private PersonService personService;

    {
        ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        personRepsotory=ctx.getBean(PersonRepsotory.class);
        personService=ctx.getBean(PersonService.class);
    }

    @Test
    public void testDataSource() throws SQLException {
        DataSource dataSource = ctx.getBean(DataSource.class);
        System.out.println(dataSource.getConnection());
    }

    @Test
    public void testJpa() {

    }

    @Test
    public void testHelloWorldSpringData() throws FileNotFoundException, IOException, InstantiationException, IllegalAccessException{

        Person person = personRepsotory.getByLastName("1");
        System.out.println(person);
    }

    @Test
    public void testKeyWords(){
        List<Person> persons = personRepsotory.getByLastNameStartingWithAndIdLessThan("1", 10);
        System.out.println(persons);

        persons = personRepsotory.getByLastNameEndingWithAndIdLessThan("X", 10);
        System.out.println(persons);

        persons = personRepsotory.getByEmailInAndBirthLessThan(Arrays.asList("AA@atguigu.com", "FF@atguigu.com",
                "SS@atguigu.com"), new Date());
        System.out.println(persons.size());
    }

    @Test
    public void testKeyWords2(){
        List<Person> persons = personRepsotory.getByAddress_IdGreaterThan(1);
        System.out.println(persons);
    }

    @Test
    public void testQueryAnnotation(){
        Person person = personRepsotory.getMaxIdPerson();
        System.out.println(person);
    }

    @Test
    public void testQueryAnnotationParams1(){
        List<Person> persons = personRepsotory.testQueryAnnotationParams1("AA", "aa@atguigu.com");
        System.out.println(persons);
    }

    @Test
    public void testQueryAnnotationParams2(){
        List<Person> persons = personRepsotory.testQueryAnnotationParams2("aa@atguigu.com", "AA");
        System.out.println(persons);
    }

    @Test
    public void testQueryAnnotationLikeParam(){
		//List<Person> persons = personRepsotory.testQueryAnnotationLikeParam("%A%", "%bb%");
		//System.out.println(persons.size());
        //
		//List<Person> persons = personRepsotory.testQueryAnnotationLikeParam("A", "bb");
		//System.out.println(persons.size());

        List<Person> persons = personRepsotory.testQueryAnnotationLikeParam2("bb", "A");
        System.out.println(persons.size());
    }

    @Test
    public void testNativeQuery(){
        long count = personRepsotory.getTotalCount();
        System.out.println(count);
    }

    @Test
    public void testModifying(){
		//personRepsotory.updatePersonEmail(1, "mmmm@atguigu.com");
        personService.updatePersonEmail(1,"mmmm@atguigu.com");
    }

    @Test
    public void testCrudReposiory(){
        List<Person> persons = new ArrayList<>();

        for(int i = 'a'; i <= 'z'; i++){
            Person person = new Person();
            person.setAddressId(i + 1);
            person.setBirth(new Date());
            person.setEmail((char)i + "" + (char)i + "@atguigu.com");
            person.setLastName((char)i + "" + (char)i);

            persons.add(person);
        }

        personService.savePersons(persons);
    }

    @Test
    public void testPagingAndSortingRespository(){
        //pageNo 从 0 开始.
        int pageNo = 6 - 1;
        int pageSize = 5;
        //Pageable 接口通常使用的其 PageRequest 实现类. 其中封装了需要分页的信息
        //排序相关的. Sort 封装了排序的信息
        //Order 是具体针对于某一个属性进行升序还是降序.
        Sort.Order order1 = new Sort.Order(Sort.Direction.DESC, "id");
        Sort.Order order2 = new Sort.Order(Sort.Direction.DESC, "email");
        Sort sort = new Sort(order1, order2);

        PageRequest pageable = new PageRequest(pageNo, pageSize, sort);
        Page<Person> page = personRepsotory.findAll(pageable);

        System.out.println("总记录数: " + page.getTotalElements());
        System.out.println("当前第几页: " + (page.getNumber() + 1));
        System.out.println("总页数: " + page.getTotalPages());
        System.out.println("当前页面的 List: " + page.getContent());
        System.out.println("当前页面的记录数: " + page.getNumberOfElements());
    }

    /**
     * saveAndFlush方法相当于merge方法
     */
    @Test
    public void testJpaRepository(){
        Person person = new Person();
        person.setBirth(new Date());
        person.setEmail("xy@atguigu.com");
        person.setLastName("xyz");
        person.setId(28);

        Person person2 = personRepsotory.saveAndFlush(person);

        System.out.println(person == person2);
    }

    /**
     * 目标: 实现带查询条件的分页. id > 5 的条件
     *
     * 调用 JpaSpecificationExecutor 的 Page<T> findAll(Specification<T> spec, Pageable pageable);
     * Specification: 封装了 JPA Criteria 查询的查询条件
     * Pageable: 封装了请求分页的信息: 例如 pageNo, pageSize, Sort
     */
    @Test
    public void testJpaSpecificationExecutor(){
        int pageNo = 3 - 1;
        int pageSize = 5;
        PageRequest pageable = new PageRequest(pageNo, pageSize);

        //通常使用 Specification 的匿名内部类
        Specification<Person> specification = new Specification<Person>() {
            /**
             * @param *root: 代表查询的实体类.
             * @param query: 可以从中可到 Root 对象, 即告知 JPA Criteria 查询要查询哪一个实体类. 还可以
             * 来添加查询条件, 还可以结合 EntityManager 对象得到最终查询的 TypedQuery 对象.
             * @param *cb: CriteriaBuilder 对象. 用于创建 Criteria 相关对象的工厂. 当然可以从中获取到 Predicate 对象
             * @return: *Predicate 类型, 代表一个查询条件.
             */
            @Override
            public Predicate toPredicate(Root<Person> root,
                                         CriteriaQuery<?> query, CriteriaBuilder cb) {
                Path path = root.get("id");
                Predicate predicate = cb.gt(path, 5);
                return predicate;
            }
        };

        Page<Person> page = personRepsotory.findAll(specification, pageable);

        System.out.println("总记录数: " + page.getTotalElements());
        System.out.println("当前第几页: " + (page.getNumber() + 1));
        System.out.println("总页数: " + page.getTotalPages());
        System.out.println("当前页面的 List: " + page.getContent());
        System.out.println("当前页面的记录数: " + page.getNumberOfElements());
    }

    @Test
    public void testCustomRepositoryMethod(){
        personRepsotory.test();
    }

}

posted @ 2022-01-24 10:07  KeepArlen  阅读(65)  评论(0)    收藏  举报