SpringData Jpa(1)SpringDataJpa入门

一、SpringData Jpa 入门

  • maven依赖相关配置
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<scope>runtime</scope>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
  • yml 相关配置
server:
  port: 8080
  servlet:
    context-path: /
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test_jpa?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
    username: root
    password: 123456
  jpa:
    database: MySQL
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
    show-sql: true
    hibernate:
      ddl-auto: update

ddl-auto: update

  1. create:每次运行程序时,都会重新创建表,故而数据会丢失
  2. create-drop:每次运行程序时会先创建表结构,然后待程序结束时清空表
  3. upadte:每次运行程序,没有表时会创建表,如果对象发生改变会更新表结构,原有数据不会清空,只会更新(推荐使用)
  4. validate:运行程序会校验数据与数据库的字段类型是否相同,字段不同会报错
  5. none: 禁用DDL处理
  • model 实体类

实体类中常用注解:

@Entity :声明这个类是一个实体类
@Table:指定映射到数据库的表格
@Id :映射到数据库表的主键属性,一个实体只能有一个属性被映射为主键
@GeneratedValue:主键的生成策略
@Column配置单列属性

@Entity
@Table(name ="tb_user")
@Data
public class User {
    @Id
    @GenericGenerator(name ="idGenerator",strategy = "uuid")
    @GeneratedValue(generator = "idGenerator")
    private String id;

    @Column(name ="username",unique= true, nullable = false, length = 64)
    private String username;

    @Column(name = "password", nullable = false,length =64)
    private String password;

    @Column(name ="email",length = 64)
    private String email;
}

主键采用UUID策略

@GenericGenerator是Hibernate提供的主键生成策略注解,注意下面的@GeneratedValue(JPA注解)使用generator= "idGenerator"引用了上面的name = "idGenerator"主键生成策略
一般简单的Demo示例中只会使用@GeneratedValue(strategy = GenerationType.IDENTITY)这种主键自增的策略,而实际数据库中表字段主键类型很少是int型的

JPA自带的几种主键生成策略

  1. TABLE: 使用一个特定的数据库表格来保存主键
  2. SEQUENCE: 根据底层数据库的序列来生成主键,条件是数据库支持序列。这个值要与generator一起使用,generator 指定生成主键使用的生成器(可能是orcale中自己编写的序列)
  3. IDENTITY: 主键由数据库自动生成(主要是支持自动增长的数据库,如mysql)
  4. AUTO: 主键由程序控制,也是GenerationType的默认值
  • Repository接口
  1. Repository: 最顶层的接口,是一个空接口,目的是为了统一所有的Repository的类型,且能让组件扫描时自动识别
  2. CrudRepository: Repository的子接口,提供CRUD 的功能。
  3. PagingAndSortingRepository:CrudRepository的子接口, 添加分页排序。
  4. JpaRepository: PagingAndSortingRepository的子接口,增加批量操作等。
  5. JpaSpecificationExecutor: 用来做复杂查询的接口。
    SpringData Jpa(1)SpringDataJpa入门_第1张图片

由图来看,一般使用JpaRepository这个接口做查询即可.这个接口拥有如下方法:

1. delete删除或批量删除
2. findOne查找单个
3. findAll查找所有
4. save保存单个或批量保存
5. saveAndFlush保存并刷新到数据库

知道这些我们就可以创建repository 了:

  • dao 层
@Repository
//User表示该Repository与实体User关联,主键类型为String
public interface UserRepository extends JpaRepository<User, String>{
	
}

​这样就完成了一个基本Repository的创建,可以直接使用其中的方法,而不需要去写实现类。

也可以自定义方法,进行操作: 例

@Repository
public interface UserRepository extends JpaRepository<User, String>, JpaSpecificationExecutor<User>{

    //自定义方法,使用Jpa标准化查询语言
    User findByUsername(String username);


    //使用JPQL查询,注意 JPQL返回的是Object[]类型
    @Query(value = "select a.id,a.email from User a where a.username like " + "%?1%")
    Object[] findAllByUsernameLike(String username);

    //使用原生的sql进行查询
    @Query(value = "select count(*) from t_user where t_user.username like " + "%?1%",nativeQuery = true)
    Integer countAllByUsername(String username);

}
  • controller层

为了简单我这里省略了Service层

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/add")
    @Transactional
    //添加
    public User saveUser() {
        User user = new User();
        user.setUsername("admin");
        user.setPassword("admin123");
        user.setEmail("[email protected]");
        return userRepository.save(user);
    }
    //删除
    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable("id") String userId) {
        userRepository.deleteById(userId);
    }
    //修改
    @PutMapping("/{id}")
    public User updateUser(@PathVariable("id") String userId, @RequestBody User user) {
        user.setId(userId);
        return userRepository.saveAndFlush(user);
    }
    //按ID查询
    @GetMapping("/{id}")
    public User getUserInfo(@PathVariable("id") String userId) {
        Optional<User> optional = userRepository.findById(userId);
        return optional.orElseGet(User::new);
    }
    //分页查询
    @GetMapping("/list")
    public Page<User> pageQuery(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        return userRepository.findAll(PageRequest.of(pageNum - 1, pageSize));
    }
    
    //分页查询 排序
    @GetMapping("/listSort")
    public Page<User> pageQuerySort(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        return userRepository.findAll(PageRequest.of(pageNum - 1, pageSize,Sort.Direction.DESC,"id"));
    }
    
    //分页查询 条件判断精确查询  Example
    @GetMapping("/listUsername")
    public Page<User> pageQueryExample(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                   @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize){
        User user = new User();
        //精确匹配
        user.setUsername("admin");
        //默认会忽略空值的字段
        Example<User> example = Example.of(user);
        return  userRepository.findAll(example,PageRequest.of(pageNum - 1, pageSize));
    }
    //分页查询  条件判断模糊查询  ExampleMatcher
    @GetMapping("/listUsernames")
    public Page<User> xx(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                         @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize){
        User user = new User();

        user.setUsername("admin");
        user.setPassword("123");
        user.setEmail("[email protected]");
        //创建匹配器,即如何使用查询条件
        ExampleMatcher matcher = ExampleMatcher.matching()//构建对象
                .withMatcher("username", ExampleMatcher.GenericPropertyMatchers.startsWith())//模糊查询匹配开头,即{username}%
                .withMatcher("password" ,ExampleMatcher.GenericPropertyMatchers.contains())//全部模糊查询,即%{address}%
                .withIgnorePaths("email");//忽略字段,即不管password是什么值都不加入查询条件

        //默认会忽略空值的字段
        Example<User> example = Example.of(user,matcher);
        return  userRepository.findAll(example,PageRequest.of(pageNum - 1, pageSize));
    }


    //自定义 使用Jpa标准化查询语言
    @GetMapping("/findUsername")
    public User findByUsername() {
        return userRepository.findByUsername("admin");
    }
    //自定义 使用 JPQL
    @GetMapping("/findList")
    public Object[] findAllByUsernameLike() {
        return userRepository.findAllByUsernameLike("admin");
    }
    //自定义 使用原生的sql进行查询
    @GetMapping("/findCount")
    public Integer countAllByUsername() {
        return userRepository.countAllByUsername("admin");
    }
}

注意:save需要添加事务才会保存在数据库中

Example

Example api的组成

Probe: 含有对应字段的实例对象。
ExampleMatcher:ExampleMatcher携带有关如何匹配特定字段的详细信息,相当于匹配条件。
Example:由Probe和ExampleMatcher组成,用于查询。

限制

属性不支持嵌套或者分组约束,比如这样的查询 firstname = ?0 or (firstname = ?1 and lastname = ?2)
灵活匹配只支持字符串类型,其他类型只支持精确匹配

ExampleMatcher

ExampleMatcher实例查询三要素

1. 实体对象:在ORM框架中与Table对应的域对象,一个对象代表数据库表中的一条记录,如上例中User对象,对应user表。在构建查询条件时,一个实体对象代表的是查询条件中的“数值”部分。如:要查询姓“X”的客户,实体对象只需要存储条件值“X”。
2. 匹配器:ExampleMatcher对象,它是匹配“实体对象”的,表示了如何使用“实体对象”中的“值”进行查询,它代表的是“查询方式”,解释了如何去查的问题。如:要查询姓“X”的客户,即姓名以“X”开头的客户,该对象就表示了“以某某开头的”这个查询方式,如上例中:withMatcher(“userName”, GenericPropertyMatchers.startsWith())
3. 实例:即Example对象,代表的是完整的查询条件。由实体对象(查询条件值)和匹配器(查询方式)共同创建。最终根据实例来findAll即可。

ExampleMatcher 静态方法

方法 说明 演示
matching() 返回一个匹配所有字段的ExampleMatcher对象;源码调用的是matchingAll()方法 ExampleMatcher.matching()
matchingAll() 返回一个匹配所有字段的ExampleMatcher对象 ExampleMatcher.matchingAll()
matchingAny() 对任意一个字段进行匹配 ExampleMatcher.matchingAny()

ExampleMatcher方法

方法 说明 返回类型
getIgnoredPaths() 返回所有设置忽略匹配 withIgonrePaths(String… ignorePaths) 的字段集合 Set
getMatchMode() 返回匹配模式(ALL ANY) ExampleMatcher.MatchMode
getNullHandler() 获取一个空处理的ExampleMatcher ExampleMatcher.NullHandler
isAllMatching() 判断匹配模式受否为matchingAll()模式 boolean
isAnyMatching() 判断匹配模式受否为matchingAny()模式 boolean
isIgnoreCaseEnabled() 判断是否开启了忽略大小写模式 boolean
isIgnoredPath(String path) 对一个字段判断是否是设置了忽略匹配模式;也就是设置了 withIgonrePaths(String… ignorePaths) 的字段 boolean
withIgnoreCase(boolean defaultIgnoreCase) 返回一个默认的ExampleMatcher,默认是忽略大小写的 ExampleMatcher
withIgnoreCase(String… propertyPaths) 对一个或多个字段设置忽略大小写 ExampleMatcher
withIgonrePaths(String… ignorePaths) 对一个或多个字段设置,则此字段不受其它匹配影响,也就是说其他任何匹配模式不对这个字段生效 ExampleMatcher
withIgnoreNullValues() 返回一个对被忽略字段 Null空值处理的ExampleMatcher对象 ExampleMatcher
withIncludeNullValues() 返回一个对字段 Null空值处理的ExampleMatcher对象 ExampleMatcher

ExampleMatcher.GenericPropertyMatchers静态方法

方法 说明 返回类型
contains() 模糊包含匹配 ExampleMatcher.GenericPropertyMatcher
endsWith() 后缀模糊匹配 ExampleMatcher.GenericPropertyMatcher
exact() 精确匹配 ExampleMatcher.GenericPropertyMatcher
ignoreCase(boolean ignoreCase) 设置忽略大小写为 true;也就是忽略大小写 ExampleMatcher.GenericPropertyMatcher
caseSensitive() 设置忽略大小写为 false;也就是不忽略大小写 ExampleMatcher.GenericPropertyMatcher
startsWith() 对开头的字符串模糊匹配 ExampleMatcher.GenericPropertyMatcher
storeDefaultMatching() 默认匹配模式 ExampleMatcher.GenericPropertyMatcher
regex() 将字符串视为正则表达式模式进行匹配 ExampleMatcher.GenericPropertyMatcher
of(ExampleMatcher.StringMatcher stringMatcher) ExampleMatcher.StringMatcher提供了枚举 ExampleMatcher.GenericPropertyMatcher
of(ExampleMatcher.StringMatcher stringMatcher, boolean ignoreCase) 和上一个一样,只是多了一个boolean来指定忽略大小写 ExampleMatcher.StringMatcher提供了枚

ExampleMatcher.StringMatcher提供了如下枚举

CONTAINING 匹配包含的字符串
DEFAULT 默认匹配模式
ENDING 匹配结尾的字符串
EXACT 匹配精确的字符串
REGEX 将字符串视为正则表达式进行匹配
STARTING 匹配开始的字符串

你可能感兴趣的:(SpringData,Jpa)