JPA查询方式(视频学习笔记)

3 篇文章 0 订阅
2 篇文章 0 订阅
本文详细介绍了JPA和SQL查询的技巧,包括JpaRepository的泛型使用、Jpql与Sql查询、动态查询(Specification)、一对一和多对多关系处理,以及如何正确处理事务和参数传递。适合深入理解ORM框架的最佳实践。
摘要由CSDN通过智能技术生成

tips

  1. @Service,@Repository,@Entity

  2. JpaRepository后的泛型:<对象名,主键类型>

  3. @Table、@Id、@Column

  4. @JoinColumn中字段是否正确

  5. 测试时toString是否重写,测试完成后删除

  6. Contoller中路径解析(@PathVaeiable)是否加上

  7. 插入、删除与更新要加上**@Transactional@Modifying**

  8. @Param中为字符串类型

  9. @Query中若使用sql查询要写values,若为Jpql记得在语句前后加上“ ”

一、Jpql方式查询

注意:Jpql语句中的字段名为对象中中定义的,不是数据库表中的

1. 查询
	//查询全部
	//不能使用select *,省略即可
	@Query("from user where name = ?")
	public User findUser(String name);
	
	//查询部分字段,可以使用select
	@Query("select name, sex from user where name = ?")
	public User findUser(String name);

2. 更新(需要添加事务)
	//更新需要写update字段,并加上@Modifying代表更新操作
	@Query("update User set name =?1 where id = ?2")
	@Modifying
	public void findUser(String name, int id);
3. 删除(需要添加事务)
	//更新需要写delete字段,并加上@Modifying代表更新操作
	@Query("delete from User set where id = ?1")
	@Modifying
	public void findUser(int id);
4. Jpql无插入操作
5. 索引参数

​ 多个参数时,可不加但顺序要一致
​ 在占位符号后加上索引,即可随意顺序

@Query("from user where name = ?2 ,sex=?1")
public User findUser(int sex, String name);
6. 命名参数

​ 通过给参数起别名(@Param),sql中使用 ” :+参数名“ 来接收参数

@Query("from user where name = :name ,sex= :sex")
public User findUser(@Param("sex") int sex, @Param("name")String name);
7. 对象参数

通过 “ :#{#对象.属性} ”,即可获取对象中的参数

@Query(value = "insert into user(name,sex,phone) 
       values(:#{#user.name},:#{#user.sex},:#{#user.phone})", nativeQuery = true)
@Modifying
public void insertUser(@Param("user") User user);

二、Sql方式查询

注意:sql语句中的字段名为数据库中定义的,不是对象中的

1. 使用@Query注解
2. value中写sql语句
3. nativeQuery设置为true
	@Query(value = "select * from user where name = ?1",nativeQuery=true)
	public User findUser(String name);
4. CRUD

​ 语句均与sql语句相同,但插入删除与更新需要添加事务与**@Modifying注解**

5. 参数传递与Jpql一致

三、动态查询(Specification)

(一)单条件查询
1. dao层继承接口

​ 继承JpaSpecificationExecutor接口并传入类名

public interface UserRepository extends JpaSpecificationExecutor<User>{}
2. service实现接口

​ 匿名内部类实现Specification,重写toPredicate方法

​ root:需要查询的对象的“属性”名称,不是数据库中的字段名称

​ cb(criteriaBuilder):构造查询条件的,内部封装了许多查询条件

Specification<User> spec =new Specification<User>() {	@Override    public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {    return null;    }};
3.通过root获取对象属性

​ 获取到之后封装成Path对象

	Path<Object> name = root.get("name");
4.通过cb构造查询条件

​ 选择想要匹配的条件的方法(equal时)

​ 第一个参数:需要比较的属性(一个path对象)

​ 第二个参数:需要比较的值

	Predicate res = cb.equal(name, "张三");

​ gt、lt、ge、le、like等条件时,要加上类型(".as( )")

​ 第一个参数:需要比较的属性(一个path对象),并指定类型(防止“1”与1弄乱)

​ 第二个参数:需要比较的值

Predicate res = cb.like(name.as(String.class), "张三");
5.返回Predicate对象
	return res;
6. 在接口实现外调用findOne/All方法

​ 注意:findOne方法是 JpaSpecificationExecutor 里的,不是 JpaRepository 里的

	Optional<User> one = userRep.findOne(spec);	System.out.println(one.get());
(二)多条件查询
1. 同单条件
2. 同单条件
3. 通过root获取对象属性

​ 直接使用root获取多个属性,并分别分装成Path对象

    Path<Object> name = root.get("name");    Path<Object> sex = root.get("sex");
4. 通过cb构造查询条件

​ 每个Path构造一个

	Predicate p1 = cb.equal(name, "张三");    Predicate p2 = cb.equal(sex, "17");
5. 将多个查询条件进行组合
    且关系:cb.and(p1, p2)    或关系:cb.or(p1, p2)
6. 同单条件
(三)代码
 //单条件Specification<User> spec =new Specification<User>() {    @Override    public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {        Path<Object> name = root.get("name");        Predicate res = cb.equal(name, "张三");        return res;    }};//Optional<User> one = userRep.findOne(spec);//多条件Specification<User> doublespec =new Specification<User>() {    @Override    public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {        Path<Object> name = root.get("name");        Path<Object> sex = root.get("sex");        Predicate p1 = cb.equal(name, "张三");        Predicate p2 = cb.equal(sex, "17");        Predicate res = cb.and(p1, p2);        return res;    }};Optional<User> one = userRep.findOne(doublespec);System.out.println(one.get());
(四)排序

​ 接口中的匿名类不用改

​ 在第六步调用的findAll方法中添加一个sort对象(与分页时类似)

	Sort sort = Sort.by(Sort.Direction.DESC, "sex");	Optional<User> one = userRep.findAll(spec,sort);	System.out.println(one.get());
(五)分页

​ 与排序类似

​ 创建PageRequest对象,放入findAll方法中

​ 可以只传入PageRequest对象,代表没有条件,分页全表

	Sort sort = Sort.by(Sort.Direction.DESC, "sex");	PageRequest page = PageRequest.of(0, 5, sort);	Optional<User> one = userRep.findAll(spec,page);

四、一对多

1. 在一的一方创建多的集合属性
2. 在集合属性上声明关系
	@OneToMany:配置一对多关系		targetEntity:指定对方字节码对象(class文件)
3. 在集合属性上配置外键
	@JoinColumn:配置外键		name:对方实体外键字段(多的一方)		referencedColumnName:本实体主键字段(一的一方)
4. 在多的一方创建一的对象属性
5. 在对象属性上声明关系
	@ManyToOne:配置多对一关系		targetEntity:指定对方字节码对象(class文件)
6. 在对象属性上配置外键
	@JoinColumn:配置外键		name:本实体外键字段(多的一方)		referencedColumnName:对方(主表)主键字段(一的一方)
7.级联操作

​ 在添加的主体的关联属性(OneToMany)上加@cascade

8.tips

​ 在toString中不要出现联系的属性(list与对象),不然会报内存溢出。

​ 添加关系后若想要单表查询,只要不去调用联系的属性(list与对象)的get方法即可实现。

​ 当调用联系的属性(list与对象)的get方法时才会触发多表联查。

五、多对多

1. 创建一个集合存放对方的对象
2. 声明表关系
	@ManyToMany:多对多		targetEntity:对方对象的字节码文件
3. 配置中间表(两个对象均要配置)
	@JoinTable:配置中间表		---joinColumns:当前对象在中间表中的外键			--@JoinColumn:配置中间表的外键				--name:外键的名称(随便取)				--referencedColumnName:本对象主键字段		---inverseJoinColumns:对方对象在中间表中的外键			--@JoinColumn:配置中间表的外键				--name:外键的名称(随便取)				--referencedColumnName:对方对象主键字段

六、分页

1. 创建PageRequest对象
	PageRequest page = PageRequest.of();
2. 传入参数

​ 第一个参数:当前查询的页数(从0开始)

​ 第二个参数:每页查询的数量

​ 第三个参数:排序对象(可不填)

	PageRequest page = PageRequest.of(0, 5);
3.创建Sort对象

​ Sort sort = Sort.by();

4.传入参数

​ 第一个参数:排序方式

​ 第二个参数:按照哪个字段排序

	Sort sort = Sort.by(Sort.Direction.DESC, "sex");
	PageRequest page = PageRequest.of(0, 5, sort);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值