@Embeddable中的实体在用作@EmbeddedId时忽略级联注释

时间:2013-08-28 06:36:01

标签: java spring hibernate jpa

我不喜欢发布一个被问过1000次的问题(如果不是更多),因为你不喜欢阅读这些重复的问题......但我现在很难过。我不明白为什么所有这些帖子中的典型解决方案,即使用'CascadeType.ALL',在这里不起作用 -

复合键

@Entity
@org.hibernate.annotations.Entity(selectBeforeUpdate = true, dynamicUpdate = true, dynamicInsert = true)
@Table(name = "A")
@SequenceGenerator(initialValue = 1, name = "a_id_gen", sequenceName = "a_id_seq")
public class ABean {

  @Id
  @Column(name = "ID")
  @Generated(GenerationTime.INSERT)
  @GeneratedValue(strategy = GenerationType.AUTO, generator = "a_id_gen")
  private long id;

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

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }
}

-

@Embeddable
public class MainPrimaryKey implements Serializable {

  @JoinColumn(name = "A_ID", referencedColumnName = "ID", insertable = true, updatable = true, nullable = false)
  @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
  private ABean a;

  public ABean getABean() {
    return a;
  }

  public void setABean(ABean a) {
    this.a = a;
  }
}

实体

@Entity
@org.hibernate.annotations.Entity(selectBeforeUpdate = true, dynamicUpdate = true, dynamicInsert = true)
@Table(name = "Main", schema = "public")
public class Main implements Serializable {

  private static final long serialVersionUID = 3028687015173402553L;

  @Column(name = "A_ID", insertable = false, updatable = false)
  private Integer aId;

  @EmbeddedId
  private MainPrimaryKey pk;

  public MainPrimaryKey getPrimaryKey() {
    return pk;
  }

  public void setPrimaryKey(MainPrimaryKey pk) {
    this.pk = pk;
  }
}

添加新实体

MainDao dao = [...]

// ...

MainPrimaryKey key = new MainPrimaryKey();

ABean aBean = new ABean();
aBean.setName("pinto");

key.setABean(aBean);

Main main = new Main();
main.setPrimaryKey(key);

dao.add(main);

错误

org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance - save the transient instance before flushing: com.blah.persistence.ABean; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.blah.persistence.ABean
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:654)
at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664)
[...]

显然,解决方法是首先保存所有依赖项。但是,我绝对不希望对实际代码中存在的所有实体都这样做。

关于这里遗漏/错误的任何想法?

1 个答案:

答案 0 :(得分:0)

我认为问题可能是这样的:

@Id
@Column(name = "ID")
@Generated(GenerationTime.INSERT)
@GeneratedValue(strategy = GenerationType.AUTO, generator = "a_id_gen")
private long id;

因为ABean的ID仅在刷新到数据库时生成,所以它是瞬态的(无id)。因此,在保存Main之前,您需要保存ABean,然后保存main。

我建议您删除@Generated(GenerationTime.INSERT)。通常你真的不想要那个!我是这样做的:

@Id
@GeneratedValue(strategy = GenerationType.AUTO,
        generator = "sequence_generator")
@SequenceGenerator(name = "sequence_generator",
        sequenceName = "my_sequence", allocationSize = 100)
@Column(name = "composition_id")
private Long id;

allocationSize确定应用程序中缓存的序列值的数量。因此,每个插入都不需要数据库跳转来将id与新实体相关联。