Spring-Data-JPA 爬坑记

一: 实体类的常用注解

2.1 @Entity 标识这个 pojo 是一个 jpa 实体

2.2 @Table(name = "表名") 指定类对应的数据库表名

2.3 @Id 标记某一字段为表主键

2.4 @GeneratedValue 标记主键生成策略

2.5 @Column 标记为字段,有如下属性

2.5.1 name 对应数据库的字段名,默认为 属性名

2.5.2 unique 是否唯一,默认 false

2.5.3 nullable 是否可以为空 默认为 true

2.5.4 inserttable 是否可以插入,即提交 insert 语句时是否持久化的数据库

2.5.5 updateable 是否可以跟新,即提交 update 语句时是否能修改该字段

2.5.6 length 字段长度

2.5.7 precision 和 scale 多少位数字,保留几位小数

2.5.8 secondaryTable 从表名,该字段不在当前表,可以指定其它从表的名称

2.5.9 columnDefinition 定义建表时创建此列的DDL,使用时,其它属性将失效

2.5.9.1 columnDefinition="TEXT" 设置为文本类型

2.6 @Temporal(TemporalType.DATE) 设置为时间类型

2.6.1 TemporalType.DATE yyyy-mm-dd

2.6.2 TemporalType.TIME hh:mm:ss

2.6.3 TemporalType.TIMESTAMP yyyy-mm-dd hh:mm:ss

二: 持久层 @Repository

1,Repository<T, T> 基础接口, 第一个 T 实体类 第二个T 主键类型 如 <User, Long>

1.1 提供了以方法名为查询条件方法

Keyword Sample JPQL snippet
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is,Equals findByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = 1?
Between findByStartDateBetween … where x.startDate between 1? and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age <= ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull findByAgeIsNull … where x.age is null
IsNotNull,NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike … where x.firstname not like ?1
StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound with appended %)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in %)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection<Age> ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection<Age> age) … where x.age not in ?1
True findByActiveTrue() … where x.active = true
False findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)

 

简单的列子, 以上的 findBy 也可以改为 getBy 或者 readBy

package com.hwq.jpa.entity;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

@Entity
@Setter
@Getter
public class Status {

    @Id
    @GeneratedValue
    @JoinColumn
    Long id;

    Long pId;

    @Column(length = 20)
    String name;

}
package com.hwq.jpa.dao;

import com.hwq.jpa.entity.Status;
import org.springframework.data.repository.Repository;

@org.springframework.stereotype.Repository  // 注意两个 Repository 不要冲突
public interface StatusDao extends Repository<Status, Long> {

    Status getById(Long id); // 根据 id Status 类

}

2, CrudRepository<T, T> 提供了简单的增删改查的方法, 继承自 Repository<T, T>

3, PagingAndSortingRepository<T, T> 提供了分页和排序的方法, 继承自 CrudRepository<T, T>

4,JpaRepository<T, T> 继承自  PagingAndSortingRepository<T, T> 

5,JpaSpecificationExecutor<T> 条件查询

简单的例子,依然使用上面的实体类

package com.hwq.jpa.dao;

import com.hwq.jpa.entity.Status;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StatusDao extends JpaRepository<Status, Long>, JpaSpecificationExecutor<Status> {

}
package com.hwq.jpa.controller;

import com.hwq.jpa.dao.StatusDao;
import com.hwq.jpa.entity.Status;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.*;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.persistence.criteria.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/status")
public class StatusController {

    @Autowired
    StatusDao statusDao;

    @RequestMapping("/insert")
    public Status insert(Status status) {
        // 保存或者修改的方法
        // 当存在主键时为修改,不存在为保存
        return statusDao.save(status);
    }

    @RequestMapping("select")
    public Map<String, Object> select(Integer page, Integer size) {
        // 实例化 排序类, Sort 可以传入多个 Order
        // Direction.DESC 降序
        // Direction.ASC  升序
        // "id"           排序字段
        Order order1 = new Order(Direction.DESC, "id");
        Sort sort = new Sort(order1);

        // 实例化分页类
        // page 查询的当前页数
        // size 查询的每一页的最大记录数
        PageRequest pageAble = new PageRequest(page, size, sort);

        // 调用 findAll 方法
        Page<Status> result = statusDao.findAll(pageAble);

        // 获取需要的数据
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("rows", result.getTotalElements());    // 获取总记录数
        map.put("page", result.getNumber());           // 当前是第几页
        map.put("pages", result.getTotalPages());      // 总共多少页
        map.put("data", result.getContent());          // 当前页的数据
        map.put("size", result.getNumberOfElements()); // 当前页的记录数

        return map;
    }

    @RequestMapping("/select-if")
    public Map<String, Object> selectIf(Integer page, Integer size) {
        Order order1 = new Order(Direction.DESC, "id");
        Sort sort = new Sort(order1);
        PageRequest pageAble = new PageRequest(page, size, sort);
        Specification<Status> statusSpecification = new Specification<Status>() {
            @Override
            public Predicate toPredicate(Root<Status> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate predicate = null;  // 最终返回的对象, 由 cb 创建
                Path path = root.get("id");  // 定位到实体类的 id
                predicate = cb.gt(path, 1);  // WHERE id > 1
                return predicate;
            }
        };

        // 调用 findAll 方法
        Page<Status> result = statusDao.findAll(statusSpecification, pageAble);

        // 获取需要的数据
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("rows", result.getTotalElements());    // 获取总记录数
        map.put("page", result.getNumber());           // 当前是第几页
        map.put("pages", result.getTotalPages());      // 总共多少页
        map.put("data", result.getContent());          // 当前页的数据
        map.put("size", result.getNumberOfElements()); // 当前页的记录数

        return map;
    }

}

6,自定义的 Repository 方法《 注意以下三点 》《 无特殊情况,少用 》

6.1 必须创建一个任意的 接口  XxxDao

6.2 定义的  XxxRepository 继承 XxxDao

6.3 实现 XxxDao 的类名称必须为 XxxRepositoryImpl

6.3.1 实现类中可以使用 EntityManager 完美接入 JPA 的内容

简单的例子, 依然使用最开始的实体类为

package com.hwq.jpa.repository.dao;

import com.hwq.jpa.entity.Status;

public interface StatusDao {
    Status selectStatusById(Long id);
}
package com.hwq.jpa.repository;

import com.hwq.jpa.entity.Status;
import com.hwq.jpa.repository.dao.StatusDao;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

@Repository
public interface StatusRepository extends
        JpaRepository<Status, Long>, JpaSpecificationExecutor<Status>, StatusDao
{

}
package com.hwq.jpa.repository;

import com.hwq.jpa.entity.Status;
import com.hwq.jpa.repository.dao.StatusDao;

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

public class StatusRepositoryImpl implements StatusDao {

    @PersistenceContext
    EntityManager entityManager;

    @Override
    public Status selectStatusById(Long id) {
        Status status = entityManager.find(Status.class, id);
        return status;
    }
}

原文地址:https://www.cnblogs.com/lovling/p/9144347.html

时间: 2024-09-29 15:30:22

Spring-Data-JPA 爬坑记的相关文章

最近项目中使用Spring data jpa 踩过的坑

最近在做一个有关OA项目中使用spring data JPA 操作数据库,结果遇到了补个不可思议的麻烦.困惑了好久. 首先看一下问题吧,这就是当时测试"设置角色时,需要首先删除该用户已经拥有的角色时"报错如下图: 一开始遇到这个问题 并没有感觉到有多大问题,后来就找了几个小时还是没有结果....后来在网上搜了好多还是没有找到结果...这时的自己就崩溃了,于是就去网上 搜索有关spring data jpa 相关Insert 和delete 及update的等操作问题,结果一眼就看到了问

Spring Data JPA中踩过的坑

说老实话,Spring Data JPA很好用,上次使用还是2013年,当时只是完成Java Bean和数据库中表的映射. 最近想起来用Spring Data JPA的起因是手头有一个项目,源代码是用原生SQL+JDBC实现的,在第一次部署时要初始化数据库,还hardcode了很多数据库配置参数.正好最近有空,就打算用Spring Boot Data JPA(spring-boot-starter-data-jpa)改造一下,仔细看了一下源代码发现和几年前已经天差地别,如果你的业务逻辑不是特别复

记: Spring Data Jpa @OneToMany 级联查询被动触发的问题

I have encountered a bug in using Spring Data Jpa. Specifically,when @OneToMany was used to maintain a one-to-many relationship, lazy loading was effective.However,it may passively trigger the cascading query without using the cascading property. My

Spring data Jpa,Mybatis,读写锁,@Lock 使用

Spring data jpa 支持注解式的读写锁(悲观锁),实际上这个东西硬编码也简单,但是基于Jpa 命名方式定义的Sql,只能用注解添加支持读写锁了, 不了解读写锁的可以点这里 mysql读写锁及事务 并且推荐 PESSIMISTIC_READ,PESSIMISTIC_WRITE,而不是 READ,WRITE,但是官方文档貌似没有更新这个案例,踩了一些坑. 新建一个实体Book.java /** * User: laizhenwei * Date: 2018-04-18 Time: 9:0

Spring Boot 2.x基础教程:使用Spring Data JPA访问MySQL

在数据访问这章的第一篇文章<Spring中使用JdbcTemplate访问数据库> 中,我们已经介绍了如何使用Spring Boot中最基本的jdbc模块来实现关系型数据库的数据读写操作.那么结合Web开发一章的内容,我们就可以利用JDBC模块与Web模块的功能,综合着使用来完成一个适用于很多简单应用场景的后端应用了. 然而当我们有一定的开发经验之后,不难发现,在实际开发过程中,对数据库的操作大多可以归结为:"增删改查".就最为普遍的单表操作而言,除了表和字段不同外,语句几

Spring Data JPA实战视频教程

视频大纲 JPA入门 Spring Data JPA入门 Repository的定义 查询方法的命名策略 JPQL查询,结果映射 Named Query,Named Native Query 排序,分页 JPA Criteria查询 Querydsl查询 Query by Example 一对一,一对多,多对一,多对多 @EnableJpaRepositories 注解 自定义.扩展Repository 实体的生命周期 审计 乐观锁,悲观锁 集成 OpenJPA 查询批注 缓存 事务 Sprin

Spring Data JPA 1.10.1 详解二之快速Demo

一.maven配置文件加入依赖 Spring Data JPA 依赖,最新稳定的版本为1.10.1.RELEASE,这里需要说明下的是,其依然依赖hibernate JPA相关JAR,hibernate-core之类的是不需要的.hibernate是JPA规范的一种实现,所以需要加入其依赖.ehcache是hibernate二级缓存的配置,不是必须的. <dependency>         <groupId>org.springframework.data</groupI

Spring Data JPA进阶——Specifications和Querydsl

Spring Data JPA进阶--Specifications和Querydsl 本篇介绍一下Spring Data JPA中能为数据访问程序的开发带来更多便利的特性,我们知道,Spring Data repository的配置很简单,一个典型的repository像下面这样: public interface CustomerRepository extends JpaRepository<Customer, Long> { Customer findByEmailAddress(Str

spring data jpa基本介绍

jpa是将java对象持久化到关系型数据库的标准方式,spring data jpa作为spring data项目在关系型数据库数据访问层的解决方案,为简化jpa存储提供了良好的支持. 有关jpa的文章网上实在是太多太多,以下几篇写的比较不错,几乎涵盖了书中所有要讲的东西,也不copy来copy去的了,免得真正需要的人又搜出一大堆废话. jpa学习笔记:http://www.blogjava.net/luyongfa/archive/2012/11/01/390572.html spring d

Spring Data JPA 入门Demo

什么是JPA呢? 其实JPA可以说是一种规范,是java5.0之后提出来的用于持久化的一套规范:它不是任何一种ORM框架,在我看来,是现有ORM框架在这个规范下去实现持久层. 它的出现是为了简化现有的持久化框架,例如hibernate.Toplink等,让我们的程序再不用去使用这些现有的产品所提供的API,也就是说,我们只需遵循这套规范,用什么框架实现数据库操作就不会有太高的耦合度,JPA可以为我们降低耦合,并且简化我们的ORM操作. JPA主要提供3方面的技术: 1.ORM映射元数据,通常对应