一、什么是JPA
JPA就是Java Persistence API的意思,是JDK 5.0注解或XML描述(对象—关系表)的映射关系,并将运行期的实体对象持久化到数据库中。
JPA在内部封装了常用的增删改查方法,使我们无须编写sql就能实现一些基础的增删改查功能。复杂的条件查询则可以借助Specification实现。
二、SpringBoot整合JPA
maven依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
配置:
spring:
datasource:
url: jdbc:mysql://localhost:3306/mytest
type: com.alibaba.druid.pool.DruidDataSource
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver //驱动
jpa:
hibernate:
ddl-auto: update //自动更新数据库
show-sql: true //日志中显示sql语句
三、Jpa操作
创建一个实体类Pet,JPA会自动帮助我们创建数据库表,因此字段的注解信息要准确详细。
@Entity(name = "t_pet")
public class Pet {
@Id //表示主键
@GeneratedValue(strategy = GenerationType.IDENTITY) //表示自增
private Integer id;
@Column //对应数据库中的列
private String name;
@Column
private String color;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Pet{" +
"id=" + id +
", name='" + name + '\'' +
", color='" + color + '\'' +
'}';
}
}
接下来只要写Dao层接口继承JpaRepository<T,ID>接口,不需要写方法就能实现基本的增删改查,原因是JpaRepository这个接口内部封装了常用的增删改查方法,直接调用就可以了。
public interface PetDao extends JpaRepository<Pet,Integer> {}
可以看一下JpaRepository接口里都有哪些方法:
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll();
List<T> findAll(Sort sort);
List<T> findAllById(Iterable<ID> ids);
<S extends T> List<S> saveAll(Iterable<S> entities);
void flush();
<S extends T> S saveAndFlush(S entity);
<S extends T> List<S> saveAllAndFlush(Iterable<S> entities);
/** @deprecated */
@Deprecated
default void deleteInBatch(Iterable<T> entities) {
this.deleteAllInBatch(entities);
}
void deleteAllInBatch(Iterable<T> entities);
void deleteAllByIdInBatch(Iterable<ID> ids);
void deleteAllInBatch();
/** @deprecated */
@Deprecated
T getOne(ID id);
T getById(ID id);
<S extends T> List<S> findAll(Example<S> example);
<S extends T> List<S> findAll(Example<S> example, Sort sort);
}
可以看到,JpaRepository这个接口封装了很多常用的操作数据库的方法供我们使用,另外JpaRepository还继承了一个父接口PagingAndSortingRepository,这个接口里就封装了我们常用的分页查询。
public interface QueryByExampleExecutor<T> {
<S extends T> Optional<S> findOne(Example<S> example);
<S extends T> Iterable<S> findAll(Example<S> example);
<S extends T> Iterable<S> findAll(Example<S> example, Sort sort);
<S extends T> Page<S> findAll(Example<S> example, Pageable pageable);
<S extends T> long count(Example<S> example);
<S extends T> boolean exists(Example<S> example);
此外,当JpaRepository接口当中提供的方法不能正常满足业务需求时,我们需要自定义查询。
在PetDao接口中自定义方法。
自定义方法规则: 方法的返回值根据业务实际需求定义。
方法的名称必须满足规范: findByXxx 如:findByName(),findById()
@Repository
public interface PetDao extends JpaRepository<Pet,Integer> {
List<Pet> findByName(String name);
List<Pet> findByColor(String color);
List<Pet> findByNameAndColor(String name,String color);
}
测试:
1、增加
@Autowired
PetDao petDao; //springboot在启动的时候,底层使用了动态代理方式获得了一个接口的实现类,完成了注入
@Test
void addPet(){
System.out.println("add pet");
Pet pet = new Pet();
pet.setName("PP3");
pet.setColor("yellow");
petDao.save(pet); // 可以添加和更新
}
2、删除
@Test
void deletePet() {
Pet pet = new Pet();
pet.setId(1);
petDao.delete(pet);
}
3、修改
JPA的修改有些特殊,也是用save()方法,但需要我们传入一个id,它会现根据id进行查询,如果查找到数据,会根据id进行数据修改;如果未查到数据,就会执行新增操作。
@Test
void updatePet() {
Pet pet = new Pet();
pet.setId(2);
pet.setName("PP3");
pet.setColor("yellow");
petDao.save(pet);
}
4、根据id查询
获得了一个Optional对象,Optional.get()获得当前对象。
如果查询不到,返回NoSuchElementException
//查询
@Test
void findPet(){
Optional<Pet> optionalPet = petDao.findById(1);
Pet pet = optionalPet.get();
System.out.println(pet.getId()+","+pet.getName()+" "+pet.getColor());
}
5、查询所有,返回List
@Test
void findAllPet(){
List<Pet> all = petDao.findAll();
for (Pet pet : all) {
System.out.println(pet.getId()+","+pet.getName()+" "+pet.getColor());
}
}
6、分页查询
Pageable:是一个接口类型
PageRequest:接口的实现类:不能直接new,因为构造器protected
PageRequest类中提供了方法of(),返回本类对象:
of();方法,static,静态方法
参数:
page:查询页数,从0开始
size:当前页显示的条目数
Direction.ASC 指定升序排序。Direction.DESC 降序
properties:指定具体按哪个属性进行排序
@Test
void findAllPetWithPage(){
Pageable pageable = PageRequest.of(0,2);
Page<Pet> pets = petDao.findAll(pageable);
for (Pet pet : pets) {
System.out.println(pet.getId()+""+pet.getName()+""+pet.getColor());
}
long totalElements = pets.getTotalElements();
System.out.println(totalElements);
int totalPages = pets.getTotalPages();
System.out.println(totalPages);
}
以上均为个人学习中的测试案例,如有不足,欢迎指正。