У меня есть следующие таблицы:
@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 генерируется для: class CustomerDeal
Это не дублирование этого вопроса
Причина, по которой вы получили упомянутую выше ошибку, связана с проблемой сопоставления (я не могу понять, что именно не так). Как совершенно другой подход, я изменил ваши сопоставления. Я тестировал это, и он работает нормально. Преимущество для вас в этом сопоставлении заключается в том, что он делает класс 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);
Ваш код, который вызывает исключение, не имеет смысла, поэтому я думаю, что это не настоящий код.
CustomerDeal имеет составной ключ, поэтому вы не сможете получить его с помощью dealsRepository.findOne(1)
, что означает, что вы, вероятно, извлекали Deal not CustomerDeal, но тогда часть никогда не будет компилироваться:
Set<CustomerDeal> custDealsSet = new HashSet<CustomerDeal>();
custDealsSet.add(dealsRepository.findOne(1))
Поэтому, кроме того, я предполагаю, что вы использовали существующие сделки. И вы создали нового клиента. Поскольку ключ CustomerDeal зависит как от клиента, так и от сделки, должен быть установлен как custumer, так и сделка, прежде чем продолжать его, что вы, вероятно, забыли сделать (и вы получили свое исключение). Поэтому он должен выглядеть так:
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);
Теперь вы, вероятно, все еще в беде. Если вы переопределите значения equals и hash в CustomerDeal, поэтому они основаны на идентификаторах (что типичный генератор кода для сущностей), оба новых экземпляра CustomerDeals имеют их как null, поэтому, когда вы добавляете их в набор, второй будет переопределять первый вставленный ( поскольку нулевые идентификаторы будут равны).
Вам также необходимо сообщить JPA, что идентификатор будет получен из отношений. В вашем CustomerDea вам нужно добавить аннотацию @MapsId
(в обоих соединениях), например:
@MapsId("customerId")
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "CUSTOMER_ID", insertable = false, updatable = false)
private Customers customers;
Наконец, если таблица CustomerDeal не содержит дополнительных данных, кроме CUSTOMER_ID и Deal_ID, то это простая совместная таблица и не должна отображаться вообще. Таким образом, вы сэкономите массу неприятностей.