jpa2.x的getOne()/findOne()/findById()的区别及使用

查看API发现getOne()方法返回的是实体对象的代理对象(a reference),源码如下:

    /**
     * Returns a reference to the entity with the given identifier.
     *
     * @param id must not be {@literal null}.
     * @return a reference to the entity with the given identifier.
     * @see EntityManager#getReference(Class, Object)
     * @throws javax.persistence.EntityNotFoundException if no entity exists for given {@code id}.
     */
    T getOne(ID id);

在CrudRepository接口中有一个findById()的方法 ,源码如下:

    /**
     * Retrieves an entity by its id.
     * 
     * @param id must not be {@literal null}.
     * @return the entity with the given id or {@literal Optional#empty()} if none found
     * @throws IllegalArgumentException if {@code id} is {@literal null}.
     */
    Optional findById(ID id);

该方法的返回值是一个Optional,在Optional类中有个get()方法,返回的是当前对象/值,源码如下:

    /**
     * If a value is present in this {@code Optional}, returns the value,
     * otherwise throws {@code NoSuchElementException}.
     *
     * @return the non-null value held by this {@code Optional}
     * @throws NoSuchElementException if there is no value present
     *
     * @see Optional#isPresent()
     */
    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

通过看源码和api,发现可以使用findById(),先调用findById()返回封装后的对象,然后使用get()方法,返回实体对象。

去掉update()方法上的@Transactional注解,将getOne()换成findById()

    @Override
    public UserInfoModel getById(Integer id) {
        //使用getOne()返回的是代理对象,无法直接操作,会出现hibernate lazyxxx  no session 的错误
        //在测试方法上加入@Transactional注解可以解决报错的问题
//        return userInfoDao.getOne(id);
        Optional findResult = userInfoDao.findById(id);
        return findResult.get();
    }

在进行编辑测试,数据库信息更新成功。

在QueryByExampleExecutor接口中有一个findOne()方法,源码如下:

    /**
     * Returns a single entity matching the given {@link Example} or {@literal null} if none was found.
     *
     * @param example must not be {@literal null}.
     * @return a single entity matching the given {@link Example} or {@link Optional#empty()} if none was found.
     * @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the Example yields more than one result.
     */
     Optional findOne(Example example);

 对于这个Example,其实是一个查询条件的封装实例,比如要条件查询UserInfo的信息(userNameCn="xxx"),则通过Example.of(userInfo)方法创建Example 的一个对象,然后调用findOne()方法;

     @Override
    public UserInfoModel findOne(UserInfoModel userInfo) {
        //Example对象可以当做查询条件处理,将查询条件得参数对应的属性进行设置即可
        //可以通过ExampleMatcher.matching()方法进行进一步得处理
        Example userExample = Example.of(userInfo);
        Optional exampleResult = userInfoDao.findOne(userExample);
        //需要结果过做判断,查询结果为null时会报NoSuchElementException
        if (exampleResult.isPresent()) {
            return exampleResult.get();
        }
        return null;
    }


findOne()方法会返回一个Optional对象,再Optional类中有很多内置的方法,其中isPresen()方法返回Optional对象是否为null的结果,如果当前Optional对象有值,则返回true,否则返回false,当结果有值时,然后调用它的get()方法,会返回一个类型的对象,即我们要查询的实例结果。isPresent()源码如下:

    /**
     * Return {@code true} if there is a value present, otherwise {@code false}.
     *
     * @return {@code true} if there is a value present, otherwise {@code false}
     */
    public boolean isPresent() {
        return value != null;
    }

get()源码如下:

    /**
     * If a value is present in this {@code Optional}, returns the value,
     * otherwise throws {@code NoSuchElementException}.
     *
     * @return the non-null value held by this {@code Optional}
     * @throws NoSuchElementException if there is no value present
     *
     * @see Optional#isPresent()
     */
    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }


 

你可能感兴趣的:(Spring,JPA)