Java文档阅读笔记-JPA中getOne()和findById的区别

196 篇文章 13 订阅
140 篇文章 4 订阅

findById()和getOne()都是从数据库中检索某个对象,不过获取数据的方式是不同的,getOne()是lazy操作,这种操作甚至没有访问数据库。

 

getOne()

返回ID的引用对象,他内部调用的了EntityManager.getReference()方法,这个方法返回proxy而非直接访问数据库(所以叫lazy),如果请求的实体不存在数据库中,那么此方法抛出EntityNotFoundException。

 

findById()

此方法直接访问数据库返回真实的对象,如果这条记录在数据库中不存在,则返回null。

 

何时使用getOne()何时使用findById()

getOne()避免了数据库和JVM的访问,直到返回的proxy的属性是真实的数据库访问。才会去访问数据库。

设计如下场景来说明这2个调用的区别:

Department

@Entity
@Table(name = "t_departments")
public class Department {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Long id;

    private String name;

Employee

@Entity
@Table(name = "t_employees")
public class Employee {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Long id;

    private String name;

    @ManyToOne  
    private Department department;

Employee的department属性和Department类有关。

如下代码:

@Service
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class HRService {

    @Autowired
    private DepartmentRepository departmentRepository;

    @Autowired
    private EmployeeRepository employeeRepository;

    public Department createDepartment() {
        Department dept = new Department();
        dept.setName("Product & Engg");
        return departmentRepository.save(dept);
    }

    public void createEmployee1(long deptId) {
        final Department pne = departmentRepository.getOne(deptId); 
        Employee employee = new Employee();
        employee.setName("Foo 1");
        employee.setDepartment(pne);
        employeeRepository.save(employee);
    }

使用getOne()比findById()要好,因为这里面的场景并不需要获取department的对象

生成的SQL如下:

insert into t_employees (department_id, name, id) values (?, ?, ?)

当使用findById()代替getOne()如下代码:

 public void createEmployee2(long deptId) {
        Optional<Department> pne = departmentRepository.findById(deptId);
        Employee employee = new Employee();
        employee.setName("Foo 1");
        pne.ifPresent(department -> {
            employee.setDepartment(department);
        });
        employeeRepository.save(employee);
 }

生成的SQL如下:

select department0_.id as id1_4_0_, department0_.name as name2_4_0_ from t_departments department0_ where department0_.id=? 
insert into t_employees (department_id, name, id) values (?, ?, ?)

总结:

getOne()findById()
lazily loaded目标实体直接通过ID获取数据库中的实体
只获取对象需要用的属性快速加载对象的所有属性
如果对象不存在抛出EntityNotEoundException对象不存在就返回null
更好的性能传统数据库访问方式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT1995

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值