Spring Data JPA 学习笔记

简介


快速入门


建表语句:

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `sex` bit(1) NOT NULL,
  `birthday` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

使用 Spring Initializer 添加 web、JPA、 MySQL依赖,生成项目。

application.properties中配置端口、datasource url以及数据库的用户名和密码。

编写实体类:

@Entity
@Data
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;


    private String name;

    private Boolean sex;

    @Column(name = "birthday")
    private Date birth;

}

UserRepository 继承 CrudRepository 接口即可

@Repository
public interface UserRepository extends CrudRepository<User,Integer> {
}

Controller:

@RestController
@RequestMapping("user")
public class HelloWebfluxController {

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/{id}")
    public Mono<User> getUser(@PathVariable("id") Integer id){
        return Mono.just(userRepository.findById(id).get());
    }

    @DeleteMapping("/{id}")
    public Mono<String> deleteUser(@PathVariable("id") Integer id){
        userRepository.deleteById(id);
        return Mono.just("success");
    }
}

访问结果

常用的类、接口


我们需要掌握和使用到的类。
七个Repository接口:

  • Repository
  • CrudRepository
  • PagingAndSortingRepository
  • QueryByExampleExecutor
  • JpaRepository
  • JpaSpecificationExecutor
  • QueryDslPredicateExecutor

两个实现类:

  • SimpleJpaRepository
  • QueryDslJpaRepository

关系图:
关系图如图
Repository 接口 :只是一个标识。Spring 在动态代理,Repository的子类代表储存库操作。

@Indexed
public interface Repository<T, ID> {

}

CrudRepository接口 : 是Repository接口的子类,提供了通用的CRUD方法。

@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {

	<S extends T> S save(S entity);

	<S extends T> Iterable<S> saveAll(Iterable<S> entities);

	Optional<T> findById(ID id);

	boolean existsById(ID id);

	Iterable<T> findAll();

	Iterable<T> findAllById(Iterable<ID> ids);

	long count();

	void deleteById(ID id);

	void delete(T entity);

	void deleteAll(Iterable<? extends T> entities);

	void deleteAll();
}

查看 save 方法的实现方法 :

	@Transactional
	@Override
	public <S extends T> S save(S entity) {

		if (entityInformation.isNew(entity)) {
			em.persist(entity);
			return entity;
		} else {
			return em.merge(entity);
		}
	}

执行插入时,会先判断对象是否存在,再选择是添加或更新。save 方法会执行两条SQL。

查看 delete 方法的实现 :

	@Transactional
	@Override
	public void deleteById(ID id) {

		Assert.notNull(id, ID_MUST_NOT_BE_NULL);
		delete(findById(id).orElseThrow(() -> new EmptyResultDataAccessException(
				String.format("No %s entity with id %s exists!", entityInformation.getJavaType(), id), 1)));
	}

根据id删除时也会先去查记录是否存在,如果不存在会报 EmptyResultDataAccessException 异常。

PagingAndSortingRepository 接口 : 继承了CrudRepository接口,并添加了 分页、排序方法。


@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {

	Iterable<T> findAll(Sort sort);

	Page<T> findAll(Pageable pageable);
}

Iterable findAll(Sort sort); 可以获取排序好的集合

Page findAll(Pageable pageable); 分页、排序,并用page对象封装结果。

PagingAndSortingRepository 接口默认的实现类是 SimpleJpaRepository。

继承 PagingAndSortingRepository 接口即可使用分页和排序。

@GetMapping("page")
    public Page<User> findAll(){
        return userRepository.findAll(new PageRequest(1,20,new Sort(Sort.Direction.ASC,"name")));
    }

JpaRepository 接口 :继承PagingAndSortingRepository接口。通过源码和CrudRepository相比较, 它支持Query By Example,批量删除, 提高删除效率, 手动刷新数据库的更改方法, 并将默认实现的查询结果变成了List。


@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {

	@Override
	List<T> findAll();
	@Override
	List<T> findAll(Sort sort);
	@Override
	List<T> findAllById(Iterable<ID> ids);
	@Override
	<S extends T> List<S> saveAll(Iterable<S> entities);
	void flush();
	<S extends T> S saveAndFlush(S entity);
	void deleteInBatch(Iterable<T> entities);
	void deleteAllInBatch();
	T getOne(ID id);
	@Override
	<S extends T> List<S> findAll(Example<S> example);
	@Override
	<S extends T> List<S> findAll(Example<S> example, Sort sort);
}

使用方法也是继承 JpaRepostiory 接口即可。

SimpleJpaRepository 类 :如果想扩展,可以继承这个实现类。
SimpleJpaRepository类

定义查询方法


利用方法名,可以定义查询方法。
如:

findByName 就可以根据传入的name进行查询。
findDistinctPeopleByName 根据name查询People并去重
findByNameAndFirstNameAllIngoreCase 忽略大小写
findByLastNameOrderByFirstName 结果按FirstName排序
deleteByName 根据Name删除

关键字如下:
关键字列表
关键字

注解查询方法


使用注解也可以实现查询。

  • @Query : 声明在查询方法上的注解 :

    @Query("select u from User u where name = :name")
    User findByName(@Param("name") String name);
    
    

    注意 : JPQL中写的是实体类,并非是表名,并且大小写也必须一致。
    如果JPQL错误,启动时就会报错。

    @Query源码:

public @interface Query {


	String value() default "";

	String countQuery() default "";

	String countProjection() default "";

	boolean nativeQuery() default false;

	String name() default "";

	String countName() default "";
}

  • @Modifying 注解:当更新或删除时,与@Query搭配,标志这是一个更新、删除操作。(必须开启事务)

常用注解


  • @Enitty :定义对象为实体,将会被映射到数据库表。
  • @Table :指定数据库的表名
  • @Id :主键,一个实体必须有一个
  • @GeneratedValue :主键生成策略
  • @Transient :JPA映射到数据库时将会忽略这个属性
  • @Column :属性对应的列名
  • @Temporal :指定Date的精确度
  • @Enumerated :映射枚举字段
  • @Lob :将属性映射为数据库的大对象类型

QueryByExampleExcutor


按示例查询。

QueryByExampleExcutor的API:
源码
Example的源码

User user = new User();
user.setName("杨");
ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("name", ExampleMatcher.GenericPropertyMatchers.startsWith());
Example<User> ex = Example.of(user,matcher);
List<User> all = carrierDao.findAll(ex);

QueryByExampleExcutor特点:

  1. 支持动态查询
  2. 不支持过滤条件分组(不支持 OR)
  3. 仅支持字符串的开始、结束、包含和精确匹配

JpaSpecificationExecutor


源码
都是围绕着 Specification 定义的,而 Specification 则只有一个方法:
Specification
JpaSpecificationExecutor是针对Criteria API进行了predicate标准封装, 帮我们封装了通过EntityManager的查询和使用细节, 操作Criteria更加便利了一些。

多数据源


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值