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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/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
Spring数据+开放jpa+延迟加载+OneTONE关系_Jpa_Spring Data_Openjpa - Fatal编程技术网

Spring数据+开放jpa+延迟加载+OneTONE关系

Spring数据+开放jpa+延迟加载+OneTONE关系,jpa,spring-data,openjpa,Jpa,Spring Data,Openjpa,我们在项目中使用SpringDataVersion1.3.2和OpenJPA22.2.2。我们面临OneTONE关系实体中延迟加载字段的问题。我将用一个例子来描述这个问题: 我们有两个实体,分别是Person和Address。人与地址之间存在一对一的关系。下面给出了为简洁起见遗漏的Person和Address实体getter和setter的代码示例: @Entity public class Person { @Id @GeneratedValue(strategy = GenerationT

我们在项目中使用SpringDataVersion1.3.2和OpenJPA22.2.2。我们面临OneTONE关系实体中延迟加载字段的问题。我将用一个例子来描述这个问题:

我们有两个实体,分别是Person和Address。人与地址之间存在一对一的关系。下面给出了为简洁起见遗漏的Person和Address实体getter和setter的代码示例:

@Entity
public class Person {

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

private String firstName;

private String lastName;

@OneToOne(mappedBy = "person", fetch = FetchType.LAZY)
private Address address;
}

@Entity

public class Address {

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

private String streetAddress;

private String city;

private String zipCode;

@OneToOne
@JoinColumn(name="PERSON_ID")
private Person person;
}
然后,我们通过从JpaRepository扩展来创建AddressRepository和PersonRepository,为我们提供这两个实体的基本CRUD操作

在我们的应用程序中,Person实体首先被创建,没有任何与之关联的地址。然后,通过在Address实例中设置适当的Person实体,在稍后的时间点创建Address实体。在这一点之前,一切都按预期进行

现在,如果通过传递适当的id使用PersonRepository的findOne方法查询Person实体,那么返回的Person实例没有填充地址字段。当我们访问PersonRepository返回的Person的地址字段时,它恰好为空。我们希望,如果有一个地址实体与Person关联,那么Person中的地址字段将可用。假设fetch类型设置为LAZY,则只意味着只有在尝试访问地址字段时才会加载它。当我们直接使用EntityManager.find方法使用JPA API时,它就是这样工作的

这段代码在我们使用hibernate时也可以正常工作。由于一些法律原因,我们不得不将我们的JPA提供商更改为OpenJPA,这停止了工作。在使用OpenJPA时,为了让OneToOne的延迟加载正常工作,我们是否应该做些不同的事情

注意:我们已打开二级缓存。我们发现OpenJPA中的二级缓存存在问题,并在OpenJPA上打开了此缺陷。然而,即使存在此缺陷,也有一种解决方法,使用entitymanagerfactory的execute方法和JPA API将实体从二级缓存中逐出,我们可以让它工作。然而,通过spring数据,我们观察到,即使在使用此解决方法时,也存在此问题。为此,我们在jpa存储库中提供entity manager factory ref,然后在bean中注入相同的emf以从缓存中逐出实体:

<jpa:repositories base-package="com.abc.dsp.spring.data.repository" entity-manager-factory-ref="emf"/>
由于spring数据在我们的项目中的广泛使用,很难使用纯JPAAPI。此外,正如一些答案中提到的,我们正试图避免由于广泛的代码影响而更改为急切获取类型或自定义setter方法

更新:
使用自定义setter方法也不起作用。工作原理是将fetch类型更改为EAGER。但是,我们希望将fetchType保持为LAZY,因为在大多数情况下,我们不需要关联的对象,而且该对象相当重。

好的,所以我找到了从缓存中逐出实体的解决方法不起作用的原因。我试图从事务边界之外的人访问地址字段。我使用findOne查询Person,并从一个用@Transactional注释的方法返回该实例。我试图访问调用方法中返回的Person实例的地址字段,该字段未使用@Transactional annotation进行注释。一旦我使用@Transactional annotation访问了方法中的地址字段,那么一旦我使用了变通方法,一切都正常了。我只是在这里再次捕获解决方法,以方便其他人参考:

1通过在JPA:repositories标记中指定EntityManager引用,将EntityManagerFactory注入JPA存储库

<jpa:repositories base-package="com.ge.dsp.spring.data.repository" entity-manager-factory-ref="emf"/>
这将确保下一个findOne/findAll调用将获得缓存未命中并返回正确构造的实体。注意,由于openJPA中的错误,必须这样做

emf.getCache().evict(Class cls, Object primaryKey)