.IdentifierGenerationException:为:class生成的null id

时间:2015-03-24 07:43:05

标签: java hibernate jpa jpql

我有以下表格:

@Entity
@Table(name = "CUSTOMER")
public class Customers implements Serializable {

    private static final long serialVersionUID = -5419345600310440297L;
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "cust")
    @SequenceGenerator(name = "cust", sequenceName = "cust_ID_SEQ")
    @Column(name = "CUSTOMER_ID")
    private Long id;
    @Column(name = "NAME")
    private String name;
    @OneToMany(mappedBy = "customer", cascade = CascadeType.PERSIST)
    private Set<CustomerDeal> customerDeals;

    //getters and setters goes here ....
}

@Entity
@Table(name = "DEALS")
public class Deals implements Serializable {

    private static final long serialVersionUID = -7197428343863081750L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "deals_seq")
    @SequenceGenerator(name = "deals_seq", sequenceName = "DEALS_SEQ")
    @Column(name = "DEAL_ID")
    private Long dealId;

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

    //getters setters
}

@Entity
@Table(name = "CUSTOMER_DEALS")
public class CustomerDeals implements Serializable {
    private static final long serialVersionUID = -4249326793843278525L;

    @EmbeddedId
    private CustomerDealId customerDealId;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "CUSTOMER_ID", insertable = false, updatable = false)
    private Customers customers;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "DEAL_ID", insertable = false, updatable = false)
    private Deals deals;

   //getters setters

}

@Embeddable
public class CustomerDealId implements Serializable {

    private static final long serialVersionUID = 9086627167426987610L;

    @Column(name = "DEAL_ID")
    private Long dealId;

    @Column(name = "CUSTOMER_ID")
    private Long customerId;

}

然而,当我尝试创建一个新客户时

Customer cust - new Customer ()
cust.setName("Foo")
CustomerDeals custDeals = new CustomerDeals()
Set<CustomerDeal>  custDealsSet = new HashSet<CustomerDeal> 
CustomerDeal custDealsSet1 = new CustomerDeal()
CustomerDeal custDealsSet2 = new CustomerDeal()
custDealsSet1.setDeals(dealsRepository.findOne(1))//getting existing deal
custDealsSet1.customers(cust)
custDealsSet2.setDeals(dealsRepository.findOne(2))//getting existing deal
custDealsSet2.customers(cust)
custDealsSet.add(custDealsSet1) 
custDealsSet.add(custDealsSet2) 
cust.setCustomerDeals(custDealsSet)
customerRepository.saveAndFlush(cust)
    customerRepository.saveAndFlush(cust)

我正在

  

org.hibernate.id.IdentifierGenerationException:生成null id   for:class CustomerDeal

这不是this question

的重复

2 个答案:

答案 0 :(得分:2)

抛出异常的代码没有意义,所以我猜这不是真正的代码。

CustomerDeal具有复合键,因此您无法使用dealsRepository.findOne(1)检索它,这意味着您可能正在检索Deal而不是CustomerDeal但是该部件永远不会编译:

Set<CustomerDeal>  custDealsSet = new HashSet<CustomerDeal>();
custDealsSet.add(dealsRepository.findOne(1)) 

所以,除此之外,我猜你正在检索现有的交易。你创造了一个新客户。由于CustomerDeal的关键在于客户和交易,因此必须先设置客户和交易,然后再坚持下去,而您可能忘记了(并且您有例外)。所以看起来应该是这样的:

Customer cust - new Customer ();
cust.setName("Foo");

CustomerDeals custDeal = new CustomerDeals();
custDeal.setCustomer(cust);
custDeal.setDeal(dealsRepository.findOne(1));
cust.getCustomerDeals().add(custDeal);

custDeal = new CustomerDeals();
custDeal.setCustomer(cust);
custDeal.setDeal(dealsRepository.findOne(2));
cust.getCustomerDeals().add(custDeal);

customerRepository.saveAndFlush(cust);

现在你可能还有麻烦。如果覆盖CustomerDeal上的equals和hash,使它们基于ID(实体的典型代码生成器),则两个新CustomerDeals实例都将它们作为null,因此当您将它们添加到集合时,第二个将覆盖第一个插入的( as null ids将等于)。

您还需要通知JPA该ID将来自关系。 在您的CustomerDea中,您需要添加@MapsId注释(在两个连接上),例如:

@MapsId("customerId")
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "CUSTOMER_ID", insertable = false, updatable = false)
private Customers customers;

最后,除非您的CustomerDeal表包含除CUSTOMER_ID和Deal_ID之外的其他表,否则它是一个简单的联合表,根本不应该映射。这样你就可以省去很多麻烦。

答案 1 :(得分:1)

你得到上述错误的原因是由于映射问题(我无法弄清楚到底是什么错误)。作为一种完全不同的方法,我修改了你的映射。我测试了这个,它工作正常。这种映射的优势在于它使CustomerDeals类成为冗余。请注意,我在使用MySQL时删除了序列。

@Entity
@Table(name = "CUSTOMERS")
public class Customer implements Serializable {

    private static final long serialVersionUID = -5419345600310440297L;

   @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
   @Column(name = "CUSTOMER_ID")
   private Long id;

  @Column(name = "NAME")
  private String name;
  @ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
  @JoinTable(
        name="CUSTOMER_DEALS",
        joinColumns = @JoinColumn( name="CUSTOMER_ID"),
        inverseJoinColumns = @JoinColumn( name="DEAL_ID")
 )
 private Set<Deals> deals = new HashSet<Deals>();
   //Setters and Getters to follow
    }

交易类将是

@Entity
@Table(name = "DEALS")
public class Deals implements Serializable {

    private static final long serialVersionUID = -7197428343863081750L;

    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "DEAL_ID")
    private Long dealId;

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

    @ManyToMany(fetch = FetchType.EAGER, mappedBy = "deals")
    private Set<Customer> customers = new HashSet<Customer>(0);
//Setters and Getters here
}

最后进行插入的主要方法。

Customer customer = new Customer();
customer.setName("NewCust2");

Deals deals = new Deals();
deals.setDealColName("Deal2");

customer.getDeals().add(deals);

customerRepository.save(customer);