JPA一对多关系 - @transactional - 获取儿童收藏

时间:2016-04-20 08:37:56

标签: java jpa spring-data

我希望获得一对多关系的所有者实体的子集合。 我有这两个实体:

@Entity
@Table(name = "commande")
public class Commande implements Serializable {

private static final long serialVersionUID = 1L;

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

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

@OneToMany(mappedBy = "commande")
@JoinColumn(name= "papa_id")
@JsonIgnore
private Set<Piece> pieces = new HashSet<>();



@Entity
@Table(name = "piece")
public class Piece implements Serializable {

    private static final long serialVersionUID = 1L;

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

    @Column(name = "ref")
    private String ref;

    @ManyToOne
    private Commande commande; 

资源:

@RequestMapping(value = "/papas/{id}",
    method = RequestMethod.GET,
    produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
@Transactional
public ResponseEntity<Papa> getPapa(@PathVariable Long id) {
    log.debug("REST request to get Papa : {}", id);
    Papa papa = papaRepository.findOne(id);
    papa.getEnfants().size();
    ...
}

我必须使用 @Transactional 才能使.size()工作(否则我有一个例外)。 有用。 但是如果在另一种方法中我删除了一个Enfant实体,那么如果我再次调用getPapa,我会得到一个错误durint .size():

Unable to find com.myapp.stagiaireproject.domain.Enfant with id 3

交易未解决的问题是什么?

1 个答案:

答案 0 :(得分:0)

第一次将所有使用存储库的工作移至服务并将此方法标记为@Transactional。将@Transactional注释设置为控制器方法是不好的做法。

默认情况下,一对多注释是惰性的,您可以明确设置@OneToMany(mappedBy = "commande", fetch = FetchType.EAGER) 告诉hibernate在获取此实体时从数据库中读取集合。

回到你的问题:如果你这样做是一个事务,hibernate使用第一级缓存(没有禁用),即它缓存实体,它们在事务期间通过PK(id)加载。如果将所有使用存储库的工作移动到服务类,则在从控制器返回数据之前提交事务,下一个请求将从数据库读取数据,而不是从缓存中读取数据。