JPA(Java Persistence API)是 Java 标准中的一套ORM规范(提供了一些编程的 API 接口,具体实现由 ORM 厂商实现,如Hiernate、TopLink 、Eclipselink等都是 JPA 的具体实现),借助 JPA 技术可以通过注解或者XML描述【对象-关系表】之间的映射关系,并将实体对象持久化到数据库中(即Object Model与Data Model间的映射)。
JPA是Java持久层API,由Sun公司开发,希望规范、简化Java对象的持久化工作,整合ORM技术,整合第三方ORM框架,建立一种标准的方式,目前也是在按照这个方向发展,但是还没能完全实现。在ORM框架中,Hibernate框架做了较好的 JPA 实现,已获得Sun的兼容认证。
JPA 的优势:
1.开发者面向 JPA 规范的接口,但底层的JPA实现可以任意切换:觉得Hibernate好的,可以选择Hibernate JPA实现;觉得TopLink好的,可以选择TopLink JPA实现。
JPA规范:
ORM映射元数据:JPA支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中
JPA的Criteria API:提供API来操作实体对象,执行CRUD操作,框架会自动将之转换为对应的SQL,使开发者从繁琐的 JDBC、SQL中解放出来。
JPQL查询语言:通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
Spring Data JPA介绍
Spring Data JPA是在实现了 JPA 规范的基础上封装的一套 JPA 应用框架(Criteria API还是有些复杂)。虽然ORM框架都实现了 JPA 规范,但是在不同的ORM框架之间切换仍然需要编写不同的代码,而使用Spring Data JPA能够方便的在不同的ORM框架之间进行切换而不需要更改代码。Spring Data JPA旨在通过统一ORM框架的访问持久层的操作,来提高开发人的效率。
Spring Data JPA是一个 JPA 数据访问抽象。也就是说Spring Data JPA不是一个实现或 JPA 提供的程序,它只是一个抽象层,主要用于减少为各种持久层存储实现数据访问层所需的样板代码量。但是它还是需要JPA提供实现程序,其实Spring Data JPA底层就是使用的 Hibernate实现。
Spring Data JPA 其实并不依赖于 Spring 框架。
Spring Data JPA 通过Repository来支持上述功能,默认提供的几种Repository已经满足了绝大多数需求:
JpaRepository( 为Repository的子接口:JpaRepository -> PagingAndSortingRepository -> CrudRepository -> Repository) QueryByExampleExecutor JpaSpecificationExecutor QuerydslPredicateExecutor
后三者用于更复杂的查询,如动态查询、关联查询等;第一种用得最多,提供基于方法名(query method)的查询,用户可基于第一种继承创建自己的子接口(只要是Repository的子接口即可),并声明各种基于方法名的查询方法。
Repository 的实现类: SimpleJpaRepository QueryDslJpaRepository
区别 | JDBC | MYBATIS(MP) | JPA |
---|---|---|---|
开发效率 | 慢 | 快 | 最快 |
执行效率 | 最快 | 快 | 开 |
灵活性 | 差 | 高 | 低 |
ORM | 不 | 半自动 | 全自动 |
1、导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
2、配置属性
# 应用服务 WEB 访问端口
server.port=8080
spring.jpa.database=mysql
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql:///2306a
spring.jpa.showSql=true
spring.jpa.hibernate.ddlAuto=update
编写实体类(jpa会自动根据实体类创建表)
用户表
package com.wang.pojo;
import jakarta.persistence.*;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.ArrayList;
import java.util.List;
/**
* @author 王利明
*/
@Data
@Table(name="user")
@Entity
@Accessors(chain = true)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private Integer age;
@ManyToMany
@JoinTable(name = "user_role",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns =@JoinColumn(name = "role_id"))
List<Role> roles=new ArrayList<>(10);
}
角色表
package com.wang.pojo;
import jakarta.persistence.*;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name="role")
@Data
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer rid;
private String rname;
@ManyToMany(mappedBy = "roles")
List<User> users = new ArrayList<>(10);
}
分别为他们创建 dao 继承JpaRepository 泛型为类 和 主键 类型
RoleDao
package com.wang.dao;
import com.wang.pojo.Role;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RoleDao extends JpaRepository<Role,Integer> {
}
UserDao
package com.wang.dao;
import com.wang.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserDao extends JpaRepository<User,Integer> {
}
测试
package com.wang;
import com.wang.dao.RoleDao;
import com.wang.dao.UserDao;
import com.wang.pojo.Role;
import com.wang.pojo.User;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class JpaApplicationTests {
@Resource
private UserDao userDao;
@Resource
private RoleDao roleDao;
@Test
void contextLoads() {
User user=new User();
user.setAge(22).setName("张三");
this.userDao.save(user);
}
@Test
public void testSelect(){
//查询所有
// this.userDao.findAll().forEach(user -> System.out.println(user));
//根据id查询单个对象
User user = this.userDao.findById(3).get();
// if(user != null){
// this.userDao.delete(user);
// }
// this.userDao.deleteById(3);
user.setAge(11).setName("xxxx");
this.userDao.saveAndFlush(user);
}
@Test
public void test1(){
//如果是多对一,则先新增单方
//先插部门
Role d1= new Role();
d1.setRname("人");
Role d2= new Role();
d2.setRname("鬼");
Role d3= new Role();
d3.setRname("蛇");
Role d4= new Role();
d4.setRname("神");
User a1=new User();
a1.setName("张三");
a1.setAge(12);
User a2=new User();
a2.setName("张四");
a2.setAge(12);
User a3=new User();
a3.setName("张五");
a3.setAge(12);
User a4=new User();
a4.setName("张六");
a4.setAge(12);
this.roleDao.save(d1);
this.roleDao.save(d2);
this.roleDao.save(d3);
this.roleDao.save(d4);
this.userDao.save(a1);
this.userDao.save(a2);
this.userDao.save(a3);
this.userDao.save(a4);
}
@Test
public void test5(){
//测试多对多
//新增角色
Role r1 = new Role();
r1.setRname("程序员");
Role r2 = new Role();
r2.setRname("组长");
Role r3 = new Role();
r3.setRname("经理");
//创建用户
User u1=new User();
u1.setAge(22).setName("张三22");
User u2=new User();
u2.setAge(23).setName("张33");
User u3=new User();
u3.setAge(22).setName("张11");
//关系
// List<Role> list1=new ArrayList<>();
// list1.add(r1);list1.add(r2);list1.add(r3);
// u1.setRoles(list1);
u1.getRoles().add(r1);
u1.getRoles().add(r2);
u1.getRoles().add(r3);
u2.getRoles().add(r2);
u3.getRoles().add(r1);
u3.getRoles().add(r2);
//保存角色
this.roleDao.save(r1);
this.roleDao.save(r2);
this.roleDao.save(r3);
//保存用户
this.userDao.save(u1);
this.userDao.save(u2);
this.userDao.save(u3);
}
}