Spring Data JPA-基础使用
简介
Spring Data JPA 是基于JPA标准操作数据库的简化方案,底层默认使用的是 Hibernate 5来实现的。
在Spring Data JPA 中提供常用的CURD的接口实现,很多地方可以直接使用,提高开发效率。
核心接口简介
Spring Data JPA 接口关系如下图
![image-20200623165122198](
)
Repository接口
Repository接口是Spring Data respository的中心接口,它需要管理域 class 以及域 class 的 ID 类型作为类型 arguments。此接口主要用作标记接口,用于捕获要使用的类型,并帮助您发现扩展此接口的接口。
@Indexed
public interface Repository<T, ID> {
}
CrudRepository接口
CrudRepository接口正如其名,主要提供CURD功能,从源码提供的方法可知,基本的CURD都提供了
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S var1);
<S extends T> Iterable<S> saveAll(Iterable<S> var1);
Optional<T> findById(ID var1);
boolean existsById(ID var1);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> var1);
long count();
void deleteById(ID var1);
void delete(T var1);
void deleteAll(Iterable<? extends T> var1);
void deleteAll();
}
PagingAndSortingRepository接口
该接口主要用于查询进行分页和排序使用
@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
Iterable<T> findAll(Sort var1);
Page<T> findAll(Pageable var1);
}
JpaRepository接口
从接口关系可以知道JpaRespository接口 继承了其他接口的所有方法,在平时的使用用通常使用这个接口比较多点
@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll();
List<T> findAll(Sort var1);
List<T> findAllById(Iterable<ID> var1);
<S extends T> List<S> saveAll(Iterable<S> var1);
void flush();
<S extends T> S saveAndFlush(S var1);
void deleteInBatch(Iterable<T> var1);
void deleteAllInBatch();
T getOne(ID var1);
<S extends T> List<S> findAll(Example<S> var1);
<S extends T> List<S> findAll(Example<S> var1, Sort var2);
}
QueryByExampleExecutor接口
Respository查询的方式
在respository接口中提供了两种查询方式:
- 基于方法名称命名规则查询
- 基于@Query注解
基于方法名称命名规则查询
规则: findBy(关键字)+属性名称(属性名称的首字母大写)+查询条件(首字母大写)
关键词 | SQL符号 | 样例 | 对应JPQL 语句片段 |
---|---|---|---|
And | and | findByLastnameAndFirstname | … where x.lastname = ?1 and x.firstname = ?2 |
Or | or | findByLastnameOrFirstname | … where x.lastname = ?1 or x.firstname = ?2 |
Is,Equals | = | findByFirstname,findByFirstnameIs,findByFirstnameEquals | … where x.firstname = ?1 |
Between | between xxx and xxx | 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 | is null | findByAgeIsNull | … where x.age is null |
IsNotNull,NotNull | is not null | findByAge(Is)NotNull | … where x.age not null |
Like | like | findByFirstnameLike | … where x.firstname like ?1 |
NotLike | not like | findByFirstnameNotLike | … where x.firstname not like ?1 |
StartingWith | like 'xxx%' | findByFirstnameStartingWith | … where x.firstname like ?1(parameter bound with appended %) |
EndingWith | like 'xxx%' | findByFirstnameEndingWith | … where x.firstname like ?1(parameter bound with prepended %) |
Containing | like '%xxx%' | findByFirstnameContaining | … where x.firstname like ?1(parameter bound wrapped in %) |
OrderBy | order by | findByAgeOrderByLastnameDesc | … where x.age = ?1 order by x.lastname desc |
Not | <> | findByLastnameNot | … where x.lastname <> ?1 |
In | in() | findByAgeIn(Collection |
… where x.age in ?1 |
NotIn | not in() | findByAgeNotIn(Collection |
… where x.age not in ?1 |
TRUE | =true | findByActiveTrue() | … where x.active = true |
FALSE | =false | findByActiveFalse() | … where x.active = false |
IgnoreCase | upper(xxx)=upper(yyyy) | findByFirstnameIgnoreCase |
基于@Query注解
通过使用@Query注解来进行查询,@Query注解其实是通过HQL演变过来
代码如下:
创建接口
@Repository
public interface BookRepository extends org.springframework.data.repository.Repository<Book,Long> {
/**
* 通过书名查找书
*
* @param name
* @return
*/
Book findBookByName(String name);
/**
* 更新名称和作者信息
* @param name
* @param author
* @param id
*/
@Transactional(rollbackFor = Exception.class)
@Modifying
@Query("update Book set name = ?1,author = ?2 where id = ?3")
void updateNameAndAuthorById(String name,String author,long id);
}
测试:
/**
* @Description: 测试类
* @Author: ZhangQiang
* @CreateDate: 2020/6/24 9:27
*/
@SpringBootTest
public class BooKTest {
@Autowired
private BookService bookService;
/**
* 新增
*/
@Test
public void saveBook(){
Book book = new Book();
book.setAuthor("岩井俊二");
book.setName("情书");
book.setPrice(50);
bookService.save(book);
}
/**
* 通过名称来查找
* @throws Exception
*/
@Test
public void findBookByName() throws Exception {
Book book = bookService.getBookByName("平行的世界");
System.out.println(book.toString());
}
/**
* 通过id来更新名称和作者信息
*/
@Test
public void updateNameAndAuthorById(){
bookService.updateNameAndAuthorById("平凡的世界","路遥",1);
}
/**
* 更新数据
*/
@Test
public void updatePriceByBook(){
Book book = new Book();
book.setId(3);
book.setPrice(38.0);
book.setAuthor("岩井俊二");
book.setName("情书");
bookService.save(book);
}
/**
* 分页
*/
@Test
public void findAllPageable(){
Pageable pageRequest = PageRequest.of(0,2);
Stream<Book> bookStream = bookService.findAll(pageRequest);
bookStream.forEach(book -> System.out.println(book.toString()));
}
}
注意:在JPA中更新数据可以通过@Query来更新,也可以共用save方法,save方法根据传入的实体 id来进行区分,会调用findById方法来查询,如果存在那么就是认为是更新,如果不存在 那么就是新增。
多对多
实体:
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Entity
public class User implements Serializable {
@Id
@GeneratedValue
private Long id;
private String name;
private String password;
private Integer age;
@ManyToMany
private Set<Role> roles;
}
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Role implements Serializable {
@Id
@GeneratedValue
private Long id;
@Column
private String name;
@ManyToMany(mappedBy = "roles")
private Set<User> users;
}
接口:
/**
* @Description: 角色接口
* @Author: ZhangQiang
* @CreateDate: 2020/6/24 14:39
*/
public interface RoleRepository extends JpaRepository<Role,Long> {
}
/**
* @Description: 用户接口
* @Author: ZhangQiang
* @CreateDate: 2020/6/24 10:39
*/
@Repository
public interface UserRepository extends JpaRepository <User,Long>{
}
实现:
/**
* @Description: 角色实现类
* @Author: ZhangQiang
* @CreateDate: 2020/6/24 11:17
*/
@Service
public class RoleServiceImpl implements RoleService {
@Autowired
private RoleRepository roleRepository;
@Transactional(rollbackFor = Exception.class)
@Override
public void save(Role role) {
roleRepository.save(role);
}
@Override
public Optional<Role> findById(Long id) {
return roleRepository.findById(id);
}
}
/**
* @Description: 用户实现类
* @Author: ZhangQiang
* @CreateDate: 2020/6/24 10:39
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Transactional(rollbackFor = Exception.class)
@Override
public void save(User user) {
userRepository.save(user);
}
}
测试:
@SpringBootTest
public class UserTest {
@Autowired
private UserService userServiceImpl;
@Autowired
private RoleService roleService;
@Test
public void saveUser(){
User user = new User();
user.setName("xiaozhang");
user.setPassword("11111");
user.setAge(18);
Optional<Role> role = roleService.findById(13L);
Role role1 = role.get();
HashSet<Role> set = new HashSet<>();
set.add(role1);
//会自动绑定两者之间的关系
user.setRoles(set);
userServiceImpl.save(user);
}
@Test
public void saveRole(){
Role role = new Role();
role.setName("管理员");
roleService.save(role);
}
}