项目的DEMO代码:https://github.com/heyu52/-spring-cloud Spring Data JPA 的使用方式和基本查询,常用的增、删、改、查需求 Spring Data JPA 已经实现了。但对于复杂的数据库场景,动态生成方法不能满足,对此 Spring Data JPA 提供了其他的解决方法,下面我们就来看看还有哪些用法。此节课我们使用上节课的代码,来继续本节内容。
自定义SQL 查询
使用 Spring Data 大部分的 SQL 都可以根据方法名定义的方式来实现,但是由于某些原因必须使用自定义的 SQL 来查询,Spring Data 也可以完美支持。 在 SQL 的查询方法上面使用 @Query 注解,在注解内写 Hql 来查询内容。
我们在UserRepository中新增一个查询方法
@Query("select u from User u")
Page<User> findAllUser(Pageable pageable);
在UserController增加
@RequestMapping("/findAllUser")
public Page<User> findAllUser()
{
int page=0,size=10;
Sort sort = new Sort(Sort.Direction.DESC, "id");
Pageable pageable = PageRequest.of(page, size, sort);
return userRepository.findAllUser(pageable);
}
运行项目,在浏览器输入:http://127.0.0.1:8080/findAllUser
上面的代码,实现了分页了,这里有几个问题是要注意的,记得页码是从0开始,并不是从1开始,如果你的表中的行数少,你又从1开始查数据,那么你可能是看不到数据的。@Query里面的脚本,并不是我们平时写的脚本,这种叫Hql ,注意,没有带*,如果写得不对,IDE工具会有提示的。为了解决这个恶心的脚本问题,还有一种写法,是可以完全和我们平时的脚本一致的,看下面的例子:
@Query( value="select * from user u where u.name = ?1",nativeQuery = true)
Page<User> findByUserName(String nickName, Pageable pageable);
在UserController增加
@RequestMapping("/findByUserName")
public Page<User> findByUserName(String name)
{
int page=0,size=10;
Sort sort = new Sort(Sort.Direction.DESC, "id");
Pageable pageable = PageRequest.of(page, size, sort);
return userRepository.findByUserName(name,pageable);
}
运行项目,在浏览器输入:http://127.0.0.1:8080/findByUserName?name=csdn
注意,及nativeQuery这里的值为true,nativeQuery表示使用原生SQL。
上面使用了参数,参数是按顺序来处理的,如果有多个参数也可以按照这个方式添加 1、2、3…。我们也可以使用名字来识别,使用@Param,写法如下
@Query( value="select * from user u where u.name = :name",nativeQuery = true)
Page<User> findByUserName2(@Param("name") String name, Pageable pageable);
在UserController增加
@RequestMapping("/findByUserName2")
public Page<User> findByUserName2(String name)
{
int page=0,size=10;
Sort sort = new Sort(Sort.Direction.DESC, "id");
Pageable pageable = PageRequest.of(page, size, sort);
return userRepository.findByUserName2(name,pageable);
}
运行项目,在浏览器输入:http://127.0.0.1:8080/findByUserName2?name=csdn
前面说了查,接下来我们说更新:
@Transactional(timeout = 10)
@Modifying
@Query("update User set Name = ?1 where id = ?2")
int updateUserNameById(String name, Long id);
在UserController增加
@RequestMapping("/updateUserNameById")
public int updateUserNameById(String name,Long id)
{
return userRepository.updateUserNameById(name,id);
}
运行项目,在浏览器输入:http://127.0.0.1:8080/updateUserNameById?name=csdn2019&id=64
注意上面我们使用了 @Transactional(timeout = 10)及 @Modifying,其中事务还设置了超时时间。
使用已命名的查询
其实这种写法不推荐,这里只做简单说明。我们可以把脚本都写在model中
我们在User中增加代码
package com.csdn.demo.model;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@NamedQueries({
@NamedQuery(name = "User.findBySex3", query = "select u from User u where u.sex = ?1"),
@NamedQuery(name = "User.findByName3", query = "select u from User u where u.name = ?1") })
public class User {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String sex;
@Column(nullable = false)
private int age;
public User() {
}
public User(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(String age) {
this.sex = age;
}
@Override
public String toString() {
return this.getId() + "," + this.getName() + "," + this.getSex() + "," + this.getAge();
}
}
在UserRepository中增加方法
List<User> findBySex3(String sex);
List<User> findByName3(String name);
在UserController增加
@RequestMapping("/findBySex3")
public List<User> findBySex3(String sex)
{
return userRepository.findBySex3(sex);
}
@RequestMapping("/findByName3")
public List<User> findByName3(String name)
{
return userRepository.findByName3(name);
}
运行项目,在浏览器输入:http://127.0.0.1:8080/findBySex3?sex=男
在浏览器输入:http://127.0.0.1:8080/findByName3?name=csdn
上述写法,其实是NamedQueries中定义了接口的方法。