我们在我们的项目中使用Spring Data(版本1.3.2)和OpenJPA(版本2.2.2)。 OneToOne关系在我们的实体中面临延迟加载字段的问题。我将用一个例子来描述这个问题:我们有两个实体(称为Person和Address)。 Person和Address之间有一对一的关系。下面给出的是Person和Address实体的代码示例(getter和setter冷落为了简洁):Spring数据+打开jpa +延迟加载+ OneToOne关系
@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延伸到我们提供了基本的CRUD操作这两个实体创建AddressRepository和PersonRepository。
在我们的应用程序中Person实体首先被创建,没有任何地址与它关联。然后通过在地址实例中设置适当的人员实体,在稍后的时间点创建地址实体。直到这一点都按预期工作。
现在,如果通过传递适当的ID来查询Person实体使用PersonRepository的findOne方法,那么返回的Person实例没有填充地址字段。当我们访问由PersonRepository返回的Person的地址字段时,它恰好为null。如果有与Person关联的Address实体,我们期待Person中的地址字段可用。假设提取类型设置为LAZY,这意味着只有当我们尝试访问地址字段时才会加载该提取类型。当我们直接使用JPA API时(使用EntityManager.find()方法),这就是它的工作原理。
这段代码在我们使用hibernate的时候用得很好。由于某些法律原因,我们必须将我们的JPA提供程序更改为OpenJPA,并停止工作。使用OpenJPA进行延迟加载OneToOne工作时,有什么我们应该做的不同吗?
注意:我们已启用L2缓存。我们发现OpenJPA存在L2高速缓存问题,并在OpenJPA上打开了这个缺陷(https://issues.apache.org/jira/browse/OPENJPA-2522)。但是,即使存在这种缺陷,也有一种解决方法(使用entitymanagerfactory的evict方法将实体从L2缓存中删除),并使用JPA API,我们可以使其运行。但是,对于春季数据,我们发现即使在使用此解决方法时也存在此问题。我们这样做是通过提供JPA储存库的实体管理器工厂-REF,然后注入我们的豆子一样电动势从缓存中驱逐实体:
<jpa:repositories base-package="com.abc.dsp.spring.data.repository" entity-manager-factory-ref="emf"/>
由于我们的项目广泛使用的弹簧的数据是难以转向使用纯粹的JPA API。此外,正如在某些回答here和here中所提到的,由于广泛的代码影响,我们正试图避免更改为渴望获取类型或自定义设置方法。
更新: 使用自定义setter方法也不起作用。正在工作的是将获取类型更改为EAGER。但是,我们希望将fetchType保持为LAZY,因为在大多数情况下,我们不需要关联的对象,而且该对象非常重。