Spring Data JPA-基础使用

Spring Data JPA-基础使用

简介

Spring Data JPA 是基于JPA标准操作数据库的简化方案,底层默认使用的是 Hibernate 5来实现的。

在Spring Data JPA 中提供常用的CURD的接口实现,很多地方可以直接使用,提高开发效率。

核心接口简介

Spring Data JPA 接口关系如下图

![image-20200623165122198](Spring Data JPA-基础使用

)

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接口中提供了两种查询方式:

  1. 基于方法名称命名规则查询
  2. 基于@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 ages) … where x.age in ?1
NotIn not in() findByAgeNotIn(Collection ages) … 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);
	}

}

上一篇:awk使用shell变量,shell获取awk中的变量值


下一篇:Python基础灬函数补充(作用域,迭代器,生成器)