I have an N-N relationship that works as follows:
Destination.java (N) - (N) CustomerService.java
Within this relationship there is an entity that holds the Id's of relationships, which has some more values. The name of this is ServiceItem.java
Below the entity's:
Destination.java
@Entity
@Table(name="destination")
public class Destination implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id_destination")
private Long idDestination;
@Column(name="tenant_id", insertable=false, updatable=false)
private Long tenantId;
@Column(name="appear_website")
private Boolean dtAppearWebsite;
@Lob
@Column(name="description")
@NotEmpty(message="O campo \"Descrição do Destino\" não pode estar em branco.")
private String dtDescription;
@OneToMany(mappedBy="destination")
private Set<ServiceItem> serviceItem;
//Mais campos adicionais e Getters and Setters
public Destination() {
}
}
CustomerService.java
@Entity
@Table(name = "customer_service")
public class CustomerService implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_customer_service")
private Long id;
@Column(name = "tenant_id", insertable = false, updatable = false)
private Long tenantId;
@Column(name = "date_service")
@DateTimeFormat(pattern = "dd/MM/yyyy")
@Temporal(TemporalType.DATE)
private Date date;
@Column(name = "average_budget")
private BigDecimal averageBudget;
@Column(name = "service_situation")
private boolean situation;
@OneToMany(cascade = CascadeType.PERSIST, mappedBy = "customerService")
private List<ServiceItem> serviceItem;
@OneToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "fk_history")
private History history;
@Column(name = "service_observatons")
private String serviceObservations;
public CustomerService() {
}
//Mais campos adicionais e Getters and Setters
}
ServiceItem.java
@Entity
@Table(name = "service_item")
@IdClass(ServiceItemId.class)
public class ServiceItem {
@Id
@ManyToOne
@JoinColumn(name="destination_id")
private Destination destination;
@Id
@ManyToOne
@JoinColumn(name="customerService_id")
private CustomerService customerService;
@Column(name="tenant_id", insertable=false, updatable=false)
private Long tenantId;
@Column(name="value_negotiated")
private double valueNegotiated;
@Enumerated(EnumType.STRING)
@Column(name="sale_type")
private SaleType saleType;
@Column(name="departure_date")
@DateTimeFormat(pattern="dd/MM/yyyy")
@Temporal(TemporalType.DATE)
private Date departureDate;
@Column(name="arrival_date")
@DateTimeFormat(pattern="dd/MM/yyyy")
@Temporal(TemporalType.DATE)
private Date arrivalDate;
@Column(name="requested_destination")
private Boolean requestedDestination;
@Column(name="negociation_observations")
private String negociationObservations;
public ServiceItem() {
}
//Getters and Setters
}
To generate the id's there is the class ServiceItemId.java
public class ServiceItemId implements Serializable {
private static final long serialVersionUID = 1L;
private Long destination;
private Long customerService;
public Long getCustomerService() {
return customerService;
}
public void setCustomerService(Long customerService) {
this.customerService = customerService;
}
public Long getDestination() {
return destination;
}
public void setDestination(Long destination) {
this.destination = destination;
}
@Override
public int hashCode() {
return (int) (destination + customerService);
}
@Override
public boolean equals(Object obj) {
if(obj instanceof ServiceItemId){
ServiceItemId serviceItemId = (ServiceItemId) obj;
return serviceItemId.destination == destination && serviceItemId.customerService == customerService;
}
return false;
}
}
Well, the question is when will I persist the data ...
Dez 17, 2014 4:52:27 PM org.apache.catalina.core.StandardWrapperValve invoke
GRAVE: Servlet.service() for servlet [appServlet] in context with path [/viatge] threw exception [Request processing failed; nested exception is org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20131113-a7346c6): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'customerService_id' cannot be null
Error Code: 1048
Call: INSERT INTO service_item (arrival_date, departure_date, negociation_observations, requested_destination, sale_type, value_negotiated, customerService_id, destination_id, tenant_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
bind => [2016-08-01, 2015-10-01, teste, true, SUBMITTED_BUDGET, 3658.98, null, 1, 2]
Query: InsertObjectQuery(br.com.joocebox.model.ServiceItem@6e92b1b1)] with root cause
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'customerService_id' cannot be null
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1041)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4187)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4119)
How could you proceed in such a case?
EDITION
Come on!
My entity CustomerService (which refers to a service) has many destinations (in this case Destination ), as many destinations can belong to many CustomerService.java ).
Note that there is no @ManyToMany relationship directly between entities, but there is a class called ServiceItem that couples between the two entities.
When I persist a ServiceItem, my id for Destination is loaded, (since it already exists), the CustomerService has not yet been persisted, so it will not have an ID what is causing the problem.