Spring Data JPA-基础篇(二)

前置文章:

Spring Data JPA-基础篇(一)

前言:

前置文章中我们已经介绍了基础JPA的使用方式,JPA是操作数据库的一种ORM规范,而文章中使用的Hibernate是其具体的实现。
本文则是使用Spring Data JPA来进行具体的CRUD操作。

零、本文纲要

一、基础准备

  1. pom.xml配置
  2. applicationContext.xml
  3. Customer实体类
  4. CustomerDao接口

二、基础CRUD

  1. 测试准备
  2. 测试查询
  3. 测试保存
  4. 测试删除
  5. 测试查询所有
  6. 测试聚合查询
  7. 判断是否存在

三、JPQL形式查询

  1. 条件查询
  2. 多条件查询
  3. 更新操作

四、SQL形式查询

  1. 查询全部
  2. 模糊匹配

五、方法命名规则查询

  1. 条件查询
  2. 模糊匹配
  3. 多条件查询

一、基础准备

1. pom.xml配置

① 属性控制
    
    
        8
        8
        5.1.20.RELEASE
        5.0.7.Final
        2.2.4
        1.6.6
    
② 依赖管理

此处依赖部分并没有过多说明,因为现在大家使用的Spring Boot、Spring Cloud都在淡化我们依赖配置的内容,更关注代码开发本身。

    
    
        
        
            junit
            junit
            4.12
            test
        
        
        
            org.springframework
            spring-core
            ${spring.version}
        
        
            org.springframework
            spring-context
            ${spring.version}
        
        
            org.springframework
            spring-context-support
            ${spring.version}
        
        
            org.springframework
            spring-orm
            ${spring.version}
        
        
            org.springframework
            spring-beans
            ${spring.version}
        
        
            org.springframework
            spring-aop
            ${spring.version}
        
        
            org.aspectj
            aspectjweaver
            1.6.0
        
        
            org.springframework.data
            spring-data-jpa
            1.9.0.RELEASE
        
        
            org.springframework
            spring-test
            ${spring.version}
        
        
        
            javax.el
            javax.el-api
            ${javax.el.version}
        
        
            org.glassfish.web
            javax.el
            ${javax.el.version}
        
        
        
            org.hibernate
            hibernate-core
            ${hibernate.version}
        
        
            org.hibernate
            hibernate-entitymanager
            ${hibernate.version}
        
        
            org.hibernate
            hibernate-validator
            5.2.1.Final
        
        
        
            mysql
            mysql-connector-java
            8.0.30
        
        
        
            c3p0
            c3p0
            0.9.1.2
        
        
        
            log4j
            log4j
            1.2.17
        
        
            org.slf4j
            slf4j-api
            ${slf4j.version}
        
        
            org.slf4j
            slf4j-log4j12
            ${slf4j.version}
        
    

2. applicationContext.xml

① 基础约束准备

引入了beans、aop、context、jdbc、tx、jpa这些命名空间。





② 数据源配置
    
    
        
        
        
        
    
③ 创建entityManagerFactory对象
    
    
        
        

        
        

        
        
            
        

        
        
            
                
                
                
                
                
                
                
                
            
        

        
        
            
        
    
④ 配置事务管理器
    
    
        
    
⑤ 整合Spring Data JPA
    
    
⑥ 声明式事务

此处非必要

    
    
        
            
            
            
            
            
            
            
        
    
    
    
        
        
    
⑦ 配置包扫描
    
⑧ 整合其他配置文件

此处暂时没有。

3. Customer实体类

/**
 * 客户实体类
 * → 配置映射关系
 *      1. 实体类和表的映射关系;
 *      2. 实体类中属性和表中字段的映射关系;
 * → 实体类和表的映射关系
 *      ① @Entity:声明实体类;
 *      ② @Table:配置实体类和表的映射关系;
 *          → name:配置数据库表名称;
 * → 实体类中属性和表中字段的映射关系
 *      ① @Id:声明主键的配置;
 *      ② @GeneratedValue:配置主键生成策略;
 *          → strategy:主键策略
 *              a、 GenerationType.IDENTITY  自增,MySQL数据库;
 *                  底层数据库必须支持自动增长,采用数据库自增方式对ID进行自增。
 *              b、 GenerationType.SEQUENCE  序列,Oracle数据库;
 *                  底层数据库支持序列。
 *              c、 GenerationType.TABLE
 *                  JPA提供的一种机制,通过一张数据库表的形式帮助完成主键自增。
 *              d、 GenerationType.AUTO
 *                  由程序自动选择主键生成策略。
 *      ③ Column:实体类属性与表字段映射
 *          → name:数据库表字段名称
 */
@Table(name = "cst_customer")
@Entity
public class Customer {

    /*客户主键*/
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cust_id")
    private Long custId;

    /*客户名称*/
    @Column(name = "cust_name")
    private String custName;

    /*客户资源来源*/
    @Column(name = "cust_source")
    private String custSource;

    /*客户级别*/
    @Column(name = "cust_level")
    private String custLevel;

    /*客户所属行业*/
    @Column(name = "cust_industry")
    private String custIndustry;

    /*客户的联系方式*/
    @Column(name = "cust_phonoe")
    private String custPhone;

    /*客户地址*/
    @Column(name = "cust_address")
    private String custAddress;

    ...

}

4. CustomerDao接口

NOTE
JpaRepository,该接口封装了基础CRUD操作:
→ T:操作的实体类类型;
→ ID:实体类中主键属性的类型。

JpaSpecificationExecutor,该接口封装了复杂查询(分页):
→ T:操作的实体类类型。

/**
 * 符合SpringDataJpa规范的接口
 * → JpaRepository,该接口封装了基础CRUD操作
 * T:操作的实体类类型;
 * ID:实体类中主键属性的类型。
 * → JpaSpecificationExecutor,该接口封装了复杂查询(分页)
 * T:操作的实体类类型。
 */
public interface CustomerDao extends JpaRepository, 
JpaSpecificationExecutor {
    ...
}

二、基础CRUD

1. 测试准备

@RunWith(SpringJUnit4ClassRunner.class) //声明Spring提供的单元测试环境
@ContextConfiguration(locations = "classpath:applicationContext.xml") //指定Spring容器配置信息
public class CustomerDaoTest {

    @Autowired
    private CustomerDao customerDao;

    ...

}

2. 测试查询

NOTE
findOne → em.find() → 立即加载;
getOne → em.getReference() → 延迟加载;

    /**
     * 测试跟据ID查询,findOne方法
     */
    @Test
    public void testFindOne() {
        Customer customer = customerDao.findOne(1L);
        System.out.println(customer);
    }

    /**
     * 跟据ID从数据库查询,getOne方法需要使用@Transactional注解
     * findOne → em.find():立即加载
     * getOne → em.getReference():延迟加载
     */
    @Test
    @Transactional
    public void testGetOne() {
        Customer customer = customerDao.getOne(5L);
        System.out.println(customer);
    }

3. 测试保存

NOTE
① 实体对象未设置主键属性值:直接保存;
② 实体对象设置主键属性值:
→ a、主键存在,进行更新;
→ b、主键不存在,跟据主键策略生成主键进行插入(保存)。

    /**
     * 测试更新|保存,save方法
     * → 先查询,后更新|保存
     * 如果没有设置ID属性,则进行保存操作;如果设置了ID属性,则会进行更新|保存。
     * ① 如果指定ID数据存在,则进行更新操作;
     * ② 如果指定ID数据不存在,则进行保存操作(注意:保存时主键会依据主键策略自动生成,而不是指定的主键)。
     */
    @Test
    public void testSave() {
        Customer customer = new Customer();
        customer.setCustId(22L);
        customer.setCustName("Stone");
        customerDao.save(customer);
    }

4. 测试删除

    /**
     * 测试删除delete
     * → 先查询,后删除
     */
    @Test
    public void testDelete() {
        customerDao.delete(21L);
    }

5. 测试查询所有

    /**
     * 测试查询所有findAll
     */
    @Test
    public void testFindAll() {
        List customers = customerDao.findAll();
        for (Customer customer : customers) {
            System.out.println(customer);
        }
    }

6. 测试聚合查询

    /**
     * 测试聚合(统计)查询
     */
    @Test
    public void testCount() {
        long count = customerDao.count();
        System.out.println(count);
    }

7. 判断是否存在

    /**
     * 测试查询判断是否存在
     * 传统方式:
     * ① 判断查询结果是否为空null;
     * ② 判断查询结果条数是否大于0;【JPA采用此方式】
     */
    @Test
    public void testExists() {
        boolean exists = customerDao.exists(4L);
        System.out.println(exists);
    }

三、JPQL形式查询

1. 条件查询

① 接口方法准备
    /**
     * 跟据客户名称查询客户信息
     * JPQL:FROM Customer WHERE custName = ?
     * 注意:在@Query注解的value属性中,需要使用"?1"来指定具体占位。
     *
     * @param custName 客户名称
     * @return 客户信息
     */
    @Query(value = "FROM Customer WHERE custName = ?1")
    public Customer findJpql(String custName);
② 测试
    /**
     * 测试JPQL查询
     */
    @Test
    public void testJpql() {
        Customer yinRui = customerDao.findJpql("Yin Rui");
        System.out.println(yinRui);
    }

2. 多条件查询

① 接口方法准备
    /**
     * JPQL:FROM Customer WHERE custName = ? AND custId = ?
     *
     * @param custName 客户名称
     * @param custId   客户ID
     * @return 客户信息
     */
    @Query(value = "FROM Customer WHERE custName = ?1 AND custId = ?2")
    public Customer findCustNameAndCustId(String custName, Long custId);
② 测试
    /**
     * 测试JPQL多条件查询
     */
    @Test
    public void testJpqlAnd() {
        Customer nicholasDunn = customerDao.findCustNameAndCustId("Nicholas Dunn", 19L);
        System.out.println(nicholasDunn);
    }

3. 更新操作

① 接口方法准备

NOTE
相比于查询方法,此处需要配合 @Modifying 注解一起使用。

    /**
     * 更新客户姓名(@Query:代表进行查询;@Modifying:代表当前执行方法进行更新操作。)
     * SQL:UPDATE cst_customer SET cust_name = ? WHERE cust_id = ?
     * JPQL:UPDATE Customer SET custName = ? WHERE custId = ?
     *
     * @param custName
     * @param custId
     */
    @Query(value = "UPDATE Customer SET custName = ?1 WHERE custId = ?2")
    @Modifying //(@Modifying+@Query)一起使用,代表更新操作。
    public void updateCustomer(String custName, Long custId);
② 测试
    /**
     * 测试JPQL更新操作
     * → SpringDataJpa中使用jpql完成 更新|删除操作 需要手动添加事务支持;
     * → 在@Test注解下,默认SpringDataJpa执行完成会进行数据回滚;
     * → 使用@Rollback(value = false),关闭自动回滚。
     */
    @Test
    @Transactional //添加事务支持
    @Rollback(value = false)
    public void testUpdate() {
        customerDao.updateCustomer("Jeff Stone", 1L);
    }

四、SQL形式查询

1. 查询全部

① 接口方法准备
    /**
     * SQL:SELECT * FROM cst_customer
     * → 使用@Query注解,配置:
     * ① value属性:sql;
     * ② nativeQuery属性:使用本地sql查询,true;反之,false。
     *
     * @return 查询对象集合
     */
    @Query(value = "SELECT * FROM cst_customer", nativeQuery = true)
    public List findSql();
② 测试
    /**
     * 测试使用本地SQL查询全部客户信息
     */
    @Test
    public void testSql() {
        List objects = customerDao.findSql();
        for (Object[] object : objects) {
            System.out.println(Arrays.toString(object));
        }
    }

2. 模糊匹配

① 接口方法准备
    /**
     * 使用SQL查询,进行模糊匹配
     * SQL:SELECT * FROM cst_customer WHERE cust_name LIKE ?
     *
     * @param custName 客户名称
     * @return 客户信息
     */
    @Query(value = "SELECT * FROM cst_customer WHERE cust_name LIKE ?1", nativeQuery = true)
    public List findSqlLike(String custName);
② 测试
    /**
     * 测试SQL查询,模糊匹配
     */
    @Test
    public void testSqlLike() {
        List objects = customerDao.findSqlLike("%Hicks");
        for (Object[] object : objects) {
            System.out.println(Arrays.toString(object));
        }
    }

五、方法命名规则查询

1. 条件查询

① 接口方法准备

NOTE
查询方法写法:findBy + 属性名称(field_name),等值匹配

    /**
     * 方法命名规则查询,是对JPQL查询的更深层的封装,使用该规则可以不用再写JPQL语句。
     * → 查询方法写法:findBy + 属性名称(field_name),等值匹配
     * ① 以findBy开头;
     * ② 拼接对象中的属性,属性首字母改为大写;
     *
     * @param custName 客户名称
     * @return 客户信息
     */
    public Customer findByCustName(String custName);
② 测试
    /**
     * 测试按照方法命名规则查询
     */
    @Test
    public void testFindByCustName() {
        Customer itoRiku = customerDao.findByCustName("Ito Riku");
        System.out.println(itoRiku);
    }

2. 模糊匹配

① 接口方法准备

NOTE
查询方法写法:findBy + 属性名称(field_name) + 查询方式[Like|Isnull]

    /**
     * 跟据方法命名规则,进行模糊匹配
     * → 查询方法写法:findBy + 属性名称(field_name) + 查询方式[Like|Isnull]
     *
     * @param custName 客户名称
     * @return 客户信息
     */
    public List findByCustNameLike(String custName);
② 测试
    /**
     * 测试模糊匹配查询(注意:由于时占位符的形式进行填充,"%"的位置信息需要自己判断。)
     */
    @Test
    public void testFindByCustNameLike() {
        List customers = customerDao.findByCustNameLike("%Yuito");
        for (Customer customer : customers) {
            System.out.println(customer);
        }
    }

3. 多条件查询

① 接口方法准备

NOTE
查询方法写法:findBy + 属性名称(field_name) + 查询方式[Like|Isnull] + 多条件连接符(And|Or) + 属性名称(field_name) + 查询方式[Like|Isnull]

    /**
     * 跟据方法命名规则,进行多条件查询
     * → 查询方法写法:findBy + 属性名称(field_name) + 查询方式[Like|Isnull] + 多条件连接符(And|Or)
     * + 属性名称(field_name) + 查询方式[Like|Isnull]
     *
     * @param CustName 客户名称
     * @param CustAddress 客户地址
     * @return 客户信息
     */
    public List findByCustNameLikeAndCustAddress(String CustName, String CustAddress);
② 测试
    /**
     * 测试多条件查询
     */
    @Test
    public void testFindByCustNameLikeAndCustAddress() {
        List customers =
                customerDao.findByCustNameLikeAndCustAddress("Xue%", "536 Wall Street");
        for (Customer customer : customers) {
            System.out.println(customer);
        }
    }

六、结尾

以上即为Spring Data JPA-基础篇(二)的全部内容,感谢阅读。

你可能感兴趣的:(Spring Data JPA-基础篇(二))