Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当使用getOne和findOne方法时,Spring数据JPA_Jpa_Spring Data_Spring Data Jpa - Fatal编程技术网

当使用getOne和findOne方法时,Spring数据JPA

当使用getOne和findOne方法时,Spring数据JPA,jpa,spring-data,spring-data-jpa,Jpa,Spring Data,Spring Data Jpa,我有一个用例,它调用以下内容: @Override @Transactional(propagation=Propagation.REQUIRES_NEW) public UserControl getUserControlById(Integer id){ return this.userControlRepository.getOne(id); } 观察@Transactional具有传播。需要\u NEW,存储库使用getOne。运行应用程序时,我收到以下错误消息: Except

我有一个用例,它调用以下内容:

@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
public UserControl getUserControlById(Integer id){
    return this.userControlRepository.getOne(id);
}
观察
@Transactional
具有传播。需要\u NEW,存储库使用getOne。运行应用程序时,我收到以下错误消息:

Exception in thread "main" org.hibernate.LazyInitializationException: 
could not initialize proxy - no Session
...
但是,如果我通过
findOne(id)
更改
getOne(id)
,所有操作都可以正常进行

顺便说一句,在用例调用getUserControlById方法之前,它已经调用了insertUserControl方法

@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
public UserControl insertUserControl(UserControl userControl) {
    return this.userControlRepository.save(userControl);
}
这两种方法都是传播。需要新的,因为我正在执行一个简单的审核控制

我使用
getOne
方法,因为它是在接口中定义的,并且我的存储库接口从那里扩展而来,我当然在使用JPA

JpaRepository接口扩展自。
findOne(id)
方法在
crudepository
中定义

我的问题是:

  • 为什么
    getOne(id)
    方法失败
  • 什么时候应该使用
    getOne(id)
    方法
  • 我正在与其他存储库一起工作,所有存储库都使用
    getOne(id)
    方法,只有在我使用传播时,所有存储库都可以正常工作。需要\u NEW它失败

    根据getOneAPI:

    返回对具有给定标识符的实体的引用

    根据findOneAPI:

    按实体的id检索实体

  • 什么时候应该使用
    findOne(id)
    方法

  • 建议使用什么方法


  • 1。为什么getOne(id)方法失败?

    见本节。您重写已就位的事务可能是导致问题的原因。然而,如果没有更多的信息,这个问题很难回答

    2。何时应该使用getOne(id)方法?

    没有深入研究Spring数据JPA的内部,区别似乎在于用于检索实体的机制

    如果查看下的for
    getOne(ID)
    ,请参见:

    这个方法似乎只是委托给JPA实体管理器的实现

    但是,对于
    findOne(ID)
    来说,没有提到这一点

    线索也在存储库的名称中。
    JpaRepository
    是特定于JPA的,因此如果需要,可以将调用委托给实体管理器。
    crudepository
    不知道所使用的持久化技术。它被用作JPA等多种持久性技术的标记接口


    因此,对于您的用例,这两种方法并没有真正的“区别”,只是
    findOne(ID)
    比更专业的
    getOne(ID)
    更通用。您使用哪种方法取决于您和您的项目,但我个人会坚持使用
    findOne(ID)
    ,因为它使您的代码不那么具体,并为您打开了通向MongoDB等东西的大门。在未来,无需太多重构:)

    getOne
    方法只返回来自DB的引用(延迟加载).
    因此,基本上您在事务之外(不考虑您在服务类中声明的
    Transactional
    ),并且会发生错误。

    基本区别在于
    getOne
    是延迟加载的,而
    findOne
    不是

    考虑以下示例:

    public static String NON_EXISTING_ID = -1;
    ...
    MyEntity getEnt = myEntityRepository.getOne(NON_EXISTING_ID);
    MyEntity findEnt = myEntityRepository.findOne(NON_EXISTING_ID);
    
    if(findEnt != null) {
         findEnt.getText(); // findEnt is null - this code is not executed
    }
    
    if(getEnt != null) {
         getEnt.getText(); // Throws exception - no data found, BUT getEnt is not null!!!
    }
    
    TL;博士
    T findOne(ID ID)
    (旧API中的名称)/
    可选findById(ID)
    (新API中的名称)依赖于执行实体快速加载的
    EntityManager.find()

    T getOne(ID)
    依赖于执行实体延迟加载的
    EntityManager.getReference()
    。因此,为了确保实体的有效加载,需要对其调用方法

    findOne()
    因此,在大多数情况下,支持
    findOne()/findById()
    而不是
    getOne()


    API变更 至少从
    2.0
    版本开始,
    Spring数据Jpa
    已修改
    findOne()

    以前,它在
    crudepository
    界面中定义为:

    T findOne(ID primaryKey);
    
    <S extends T> Optional<S> findOne(Example<S> example);
    
    现在,您将在
    crudepository
    中找到的单个
    findOne()
    方法是
    QueryByExampleExecutor
    接口中定义的方法:

    T findOne(ID primaryKey);
    
    <S extends T> Optional<S> findOne(Example<S> example);
    
    现在它返回一个
    可选的
    。这对于防止
    NullPointerException
    来说并不坏

    因此,现在实际的选择是在
    可选的findById(ID)
    T getOne(ID)
    之间


    依赖于两种不同JPA EntityManager检索方法的两种不同方法 1) 缔约国表示:

    按实体的id检索实体

    当我们查看实现时,可以看到它依赖于
    EntityManager.find()
    进行检索:

    public Optional<T> findById(ID id) {
    
        Assert.notNull(id, ID_MUST_NOT_BE_NULL);
    
        Class<T> domainType = getDomainClass();
    
        if (metadata == null) {
            return Optional.ofNullable(em.find(domainType, id));
        }
    
        LockModeType type = metadata.getLockModeType();
    
        Map<String, Object> hints = getQueryHints().withFetchGraphs(em).asMap();
    
        return Optional.ofNullable(type == null ? em.find(domainType, id, hints) : em.find(domainType, id, type, hints));
    }
    
    其javadoc声明:

    使用指定的属性按主键查找

    因此,检索加载的实体似乎是意料之中的事

    2) 而各州(重点是我):

    返回对具有给定标识符的实体的引用

    事实上,参考术语实际上是board,jpaapi没有指定任何
    getOne()
    方法。
    因此,要理解Spring包装器的作用,最好的办法是研究实现:

    @Override
    public T getOne(ID id) {
        Assert.notNull(id, ID_MUST_NOT_BE_NULL);
        return em.getReference(getDomainClass(), id);
    }
    
    下面是一个
    EntityManager
    方法,声明为:

    public <T> T find(Class<T> entityClass, Object primaryKey,
                      Map<String, Object> properties);
    
    public <T> T getReference(Class<T> entityClass,
                                  Object primaryKey);
    
    public T getReference(类entityClass,
    对象主密钥);
    
    幸运的是,
    EntityManager
    javadoc更好地定义了它的意图(重点是我的):

    获取一个实例,该实例的状态可能是延迟获取的。如有要求, 实例在中不存在
    public UserDTO getById(int userId) throws Exception {
    
        final User user = userDao.getOne(userId);
    
        if (user == null) {
            throw new ServiceException("User not found", HttpStatus.NOT_FOUND);
        }
        userDto = mapEntityToDto.transformBO(user, UserDTO.class);
    
        return userDto;
    }
    
    {
    "collection": {
        "version": "1.0",
        "data": {
            "id": 1,
            "name": "TEST_ME",
            "bookList": null
        },
        "error": null,
        "statusCode": 200
    },
    "booleanStatus": null
    
    {
    "collection": {
        "version": "1.0",
        "data": {
            "id": 0,
            "name": "Annama",
            "bookList": [
                {
                    "id": 2,
                    "book_no": "The karma of searching",
                }
            ]
        },
        "error": null,
        "statusCode": 200
    },
    "booleanStatus": null