SpringJPA即使在事务中也不能初始化惰性属性

j0pj023g  于 2021-07-09  发布在  Java
关注(0)|答案(1)|浏览(362)

为什么springjpa不初始化lazy属性 MyChildEntity.myParentEntity (所有字段都为空)?
我试着用 Hibernate.initialize 以及 @Transactional ,但那没用。
我的服务:

@Service
@Transactional
public class MyService {

    @Resource
    private MyChildEntityRepository myChildEntityRepository;

    @Resource
    private MyParentEntityRepository myParentEntityRepository;

    @PostConstruct
    public void init() {
        MyParentEntity p = myParentEntityRepository.save(new MyParentEntity("my name"));

        myChildEntityRepository.save(new MyChildEntity(p, "first value"));
        myChildEntityRepository.save(new MyChildEntity(new MyParentEntity(1L, "another name"), "another value"));

        // At this point both MyChildEntity's are in database and have correct foreign key value
        List<MyChildEntity> result = myChildEntityRepository.findAll();
        //even this doesn't help, myParentEntity property still has all fields equals to null
        Hibernate.initialize(result.get(0).getMyParentEntity());

        MyParentEntity p2 = result.get(0).getMyParentEntity();

        //trigger proxy's method to initialize lazy field
        System.out.print(p2.getName()); // null
        System.out.println(p2.getId()); // null

        // PROBLEM: p2 has all fields equals null
        // the same for result.get(1)

        // BUT, this works correct - returns (1L, "my name") entity
        myParentEntityRepository.findAll(); 
    }
}

子实体:

@Entity
public class MyChildEntity {

    @Id
    @SequenceGenerator(sequenceName = "CHILD_SEQ", name = "ChildSeq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ChildSeq")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "my_parent_entity_id", referencedColumnName = "id")
    private MyParentEntity myParentEntity;

    @Column
    private String value;

    // constructors, getters, setters...

父实体:

@Entity
public class MyParentEntity {

    @Id
    @SequenceGenerator(sequenceName = "WORKFLOW_SEQ", name = "WorkflowSeq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "WorkflowSeq")
    private Long id;

    @Column
    private String name;

    //constructors, getters, setters...
iibxawm4

iibxawm41#

这个 fetch 属性指示何时应该使用 javax.persistence.FetchType 枚举。 FetchType.EAGER 意味着jpa提供者必须在检索实体时检索值。另一方面, FetchType.LAZY 作为对jpa提供者的提示,它只能在第一次访问属性时等待并获取值(这可能永远不会,从而节省了对数据库的访问)。但是,jpa提供程序不需要支持延迟加载,因此这些值可能会被急切地加载。
来源:nicholas s williams的professional java for web应用程序
编辑:
我真的很抱歉我花了这么长时间。我认为这是错的。我在父实体中没有看到子实体的示例。应该是这样的:

public class MyParentEntity {
... //other fields
@OneToMany(fetch = FetchType.LAZY, mappedBy = "myParentEntity")
private Set<MyChildEntity> myChildEntities = new HashSet<MyChildEntity>;
... //other fields or constructors or getters or setters 
...     
}

我希望这能奏效。如果没有,那么在你的 MyChildEntity 同学们,里面有一个奇怪的注解 @JoinColumn 打电话 referencedColumnName . 我不知道那是什么。请把它取下来。
谢谢

相关问题