spring-data-jpa 双向OneToMany JPAMap(在两端都使用即时提取)正常工作[duplicate]

8aqjt8rx  于 2022-11-10  发布在  Spring
关注(0)|答案(1)|浏览(132)

此问题在此处已有答案

Problem with LazyInitializationException(2个答案)
19天前关闭。
这篇文章是4天前编辑并提交审查的。
我在数据库中有3个表,在Java应用程序中有3个JPA实体。

@Data
@Entity
public class Fraud {

    @Id
    @Column(name = "id")
    private Integer id;

    @Column(name = "fraud_type")
    private String fraudType;

    @Column(name = "fraud_value")
    private String fraudValue;

    @OneToMany(mappedBy = "fraud", fetch = FetchType.EAGER)
    private List<FraudActionEntity> fraudActions;

}

@Data
@Entity
public class FraudActionEntity {

    @Id
    @Column(name = "id")
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "fraud_id")
    private Fraud fraud;

    @ManyToOne
    @JoinColumn(name = "action_id")
    private Action action;

    @Column(name = "enabled")
    private Boolean enabled;
}

@Data
@Entity
public class Action {

    @Id
    @Column(name = "id")
    private Integer id;

    @Column(name = "attribute_key")
    private String attributeKey;

    @Column(name = "attribute_value")
    private String attributeValue;

}

@Repository
public interface FraudRepository extends JpaRepository<Fraud, Integer> {

    public Fraud findByFraudTypeAndFraudValue(String fraudType, String fraudValue);

}
我的用例

对于某种类型的欺诈,我希望遍历该类型欺诈触发的所有操作并对其采取行动。

访问代码
Fraud fraud = fraudRepository.findByFraudTypeAndFraudValue("Type", "Value");
log.info(fraud.getFraudActions().get(0).getAction());

当我运行上面的代码时,一切正常。我也得到了fraudfraudActions的关联,没有得到任何错误。
我的印象是,由于两个实体FraudFraudActionEntity都在急切地获取对方,所以它应该会给予一些错误,如循环获取/无限获取循环,但它没有!
为什么它能工作?什么时候会给予循环提取错误或无限提取循环错误?如果它确实出现循环提取错误,我们可以在@ManyToOne端使用lazy fetch来修复它吗,如下所示:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fraud_id")
private Fraud fraud;
i7uaboj4

i7uaboj41#

更新:针对LazyInitializationException的一个简单而有效的解决方案是用@Transactional注解来注解你的方法。这将在执行方法的同时创建和维护事务,从而允许你的代码对DB的惰性init对象进行必要的调用。Learn more about it here
JPA存储库方法的返回类型应该是实体对象的列表,因为结果可能不止一行(这可能是您获取fraud变量的空值的原因)。
关于Fetch策略,您可以对该特定关联使用Eager,也可以使用other strategies。一种可能的解决方案是,在需要延迟加载的FraudAction对象列表时进行第二次查询。
此外,作为附带说明avoid using lombok data annotation,始终确保您的Entity/DTO类中有一个NoArgsConstructor(在您的示例中,@Data意外添加了该变量,因为它包括@RequiredArgsConstructor,并且您没有任何最终变量。

相关问题