How can I solve error 'Multiple representations of the same entity'? - spring-boot

I am new using JPA and I'm getting an error when trying to insert more than a value into the ParticipantesEntity table.
So ConcursoEntity has a OneToMany Relation to ParticipantesEntity.
ENTITY
------
public class ConcursoEntity {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CONCURSO_ID_GEN")
#SequenceGenerator(name = "CONCURSO_ID_GEN", sequenceName = "CONCURSO_SEQ", initialValue = 1, allocationSize = 1)
#Column(name = "ID", unique = true, nullable = false)
private Long id;
#Column(name = "PREMIO")
private String premio;
#Column(name = "RUT")
private String rut;
#Column(name = "FECHA_ACTUALIZACION")
private Timestamp fechaActualizacion;
#Column(name = "DIRECCION")
private String direccion;
#Column(name = "COMUNA")
private String comuna;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
#JoinColumn(name = "ID", referencedColumnName = "id")
private List<ParticipantesEntity> pticipantes;
}
public class ParticipantesEntity {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PARTICIPANTES_ID_GEN")
#SequenceGenerator(name = "PARTICIPANTES_ID_GEN", sequenceName = "PARTICIPANTES_SEQ", initialValue = 1, allocationSize = 1)
#Column(name = "ID", unique = false, nullable = false)
private Long id;
#Column(name = "RUT")
private String rut;
#Column(name = "TIPO_PARTICIPANTE")
private String tipoParticipante;
}
ERROR
org.springframework.dao.InvalidDataAccessApiUsageException: Multiple representations of the same entity [cl.bch.cloud.ms.grts.web.entities.ParticipantesEntity#1] are being merged. Detached: [ParticipantesEntity(id=1, rut=216956245, tipoParticipante=PROPIETARIO)]; Detached: [ParticipantesEntity(id=1, rut=156324865, tipoParticipante=AVAL)]; nested exception is java.lang.IllegalStateException: Multiple representations of the same entity [cl.bch.cloud.ms.grts.web.entities.ParticipantesEntity#1] are being merged. Detached: [ParticipantesEntity(id=1, rut=216956245, tipoParticipante=PROPIETARIO)]; Detached: [ParticipantesEntity(id=1, rut=156324865, tipoParticipante=AVAL)]
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:371)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:257)
REQUEST
{
"id":1,
"premio":"auto",
"rut":"162332112",
"direccion":"LOS JACINTOS 374",
"comuna":"VALPARAISO",
"participantes":[
{
"id": 1,
"rut":"156324865",
"tipoParticipante":"AVAL",
},
{
"id": 1,
"rut":"216956245",
"tipoParticipante":"PROPIETARIO",
}
]
}
I've tried adding a #ManyToOne relation in table ParticipantesEntity, but gives me the same error.

Related

Spring Data persisting Phantom Child with Null value - not null property references a null or transient value

I have the following Entities in my Project:
#Getter
#Setter
#Entity
#Table(uniqueConstraints = #UniqueConstraint(columnNames = { "purchaseId" }))
public class Purchase {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long purchaseId;
#Column(unique = true, nullable = false, length = 15)
private String purchaseNo;
#Column(nullable = false, length = 15)
private String batchCode;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "supplier.supplierId", foreignKey = #ForeignKey(name = "FK_purchase_supplier"), nullable = false)
private Supplier supplier;
#Column(nullable = false)
private LocalDate purchaseDate;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "purchaseId", nullable = false)
private List<PurchaseItem> purchaseItems;
private Double totalAmount;
#ManyToOne
#JoinColumn(name = "userId", nullable = false, foreignKey = #ForeignKey(name = "FK_invoice_purchases"))
private User staff;
#Column(length = 100)
private String remarks;
#Column(nullable = false, updatable = false)
#CreationTimestamp
private LocalDateTime createdAt;
private boolean isDeleted = false;
}
#Getter
#Setter
#Entity
#Table(uniqueConstraints = #UniqueConstraint(columnNames = {"purchaseItemId"}))
public class PurchaseItem {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long purchaseItemId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "purchaseId", insertable = false, updatable = false, foreignKey = #ForeignKey(name="FK_purchase_item"))
private Purchase purchase;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "productId", foreignKey = #ForeignKey(name="FK_product_item"), nullable = false)
private Product product;
private Double itemAmount;
#Column(nullable = false)
private Double quantity;
private Double itemTotalAmount;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
#PrimaryKeyJoinColumn(foreignKey = #ForeignKey(name = "FK_purchacase_item_batch"))
private PurchaseProductBatch productPurchaseBatch;
public void setPurchaseProductBatch() {
PurchaseProductBatch productPurchaseBatch = new PurchaseProductBatch();
productPurchaseBatch.setProduct(this.product);
productPurchaseBatch.setQuantity(this.quantity);
productPurchaseBatch.setPurchaseItem(this);
this.productPurchaseBatch = productPurchaseBatch;
}
}
#Getter
#Setter
#Entity
#Table()
public class PurchaseProductBatch{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long productBatchId;
#ManyToOne(cascade = CascadeType.DETACH)
#JoinColumn(name = "productId", foreignKey = #ForeignKey(name = "FK_product_purch"))
private Product product;
private Double quantity;
#OneToOne(fetch = FetchType.EAGER)
#MapsId
private PurchaseItem purchaseItem;
private boolean isDeleted = false;
#OneToMany(cascade = CascadeType.PERSIST)
#JoinColumn(name = "productBatchId", foreignKey = #ForeignKey(name = "FK_purchase_batch_qty"))
private Set<InvoicePurchaseBatchQuantity> invoicePurchaseBatchQuantities;
}
During Purchase Insert, everything works fine. However, if I update the Purchase record in the database and add new PurchaseItem entry, I encounter the issue below:
org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value : com.be.entity.PurchaseItem.product; nested
I have debugged my application and I see that there is a Product instance inside all of the PurchaseItem. When I commented out the PurchaseProductBatch inside PurchaseItem, everything works fine so I conclude that it is the causing the issue. However, I don't understand how and why JPA seems to create phantom PurchaseItem Records with no value.
Also, if I only update an existing PurchaseItem entry in Purchase, I don't encounter any issues.

Why hibernate is throwing constraintViolationException?

Order Entity
#Entity
#Table(name = "Order",
indexes = {
#Index(name = "ORDER_X1", columnList = "REFERENCE_ID,SOURCE_ID"),
#Index(name = "ORDER_X2", columnList = "TYPE,STATUS")
}
)
#DiscriminatorColumn(name="PROCESSOR_TYPE", discriminatorType=DiscriminatorType.STRING, length = 80)
#SequenceGenerator(name="orderSeq", sequenceName="ORDER_SEQ")
#Inheritance(strategy= InheritanceType.JOINED)
public abstract class OrderEntity implements Serializable {
#Id
#GeneratedValue(strategy= GenerationType.SEQUENCE, generator="orderSeq")
private Long id;
#ManyToMany(cascade={CascadeType.MERGE})
#JoinTable(
name = "FILE_ORDER_MAP",
joinColumns = {#JoinColumn(name = "ORDER_ID")},
inverseJoinColumns = {#JoinColumn(name = "FILE_ID")}
)
private Set<TransferFile> transferFiles = new HashSet<>();
#Column(name = "TYPE")
#Enumerated(EnumType.STRING)
private OrderType type;
#Column(name = "AMOUNT", precision = 12, scale = 2)
private LcMoney amount;
#Column(name = "STATUS")
#Enumerated(EnumType.STRING)
private OrderStatus reconStatus;
#Type(type = LcUtc.JPA_JODA_TIME_TYPE)
#Column(name = "STATUS_D", nullable = false)
#LcDateTimeUtc()
private DateTime reconStatusDate;
#Column(name = "REFERENCE_ID")
private Long referenceId;
#Column(name = "SOURCE_ID")
private Long sourceId;
#Column(name = "ACCOUNT_ID")
private Long accountId;
#Column(name = "PROCESSOR_TYPE", insertable = false, updatable = false)
#Enumerated(EnumType.STRING)
private OrderProcessorType processorType;
#Type(type = LcUtc.JPA_JODA_TIME_TYPE)
#Column(name = "TX_EXECUTION_D")
#LcDateTimeUtc()
private DateTime executedDate;
#Type(type = LcUtc.JPA_JODA_TIME_TYPE)
#Column(name = "CREATE_D")
#LcDateTimeUtc()
private DateTime createDate;
#Column(name = "IS_ON_DEMAND")
#Type(type = "yes_no")
private boolean isOnDemand;
#ManyToOne(fetch = FetchType.LAZY, optional = true, cascade = {CascadeType.PERSIST})
#JoinColumn(name="PAYER_ID", nullable=true)
private Payer payer;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "ORDER_ID", referencedColumnName = "ID")
private List<OrderTransaction> orderTransactions;
#OneToMany(cascade = {CascadeType.ALL})
#JoinColumn(name = "ORDER_ID", referencedColumnName = "ID",
foreignKey = #ForeignKey(name = "FK_ORDER")
)
private List<MatchResult> matchResults;
#Version
#Column(name = "VERSION")
private Integer version;
#Embedded
#AttributeOverrides({
#AttributeOverride(name = "externalSourceId", column = #Column(name = "TRANS_EXT_SRC_ID")),
#AttributeOverride(name = "externalId", column = #Column(name = "TRANS_EXT_REF_ID"))
})
private LcExternalIdEntity transExtId;
#PreUpdate
#PrePersist
public void beforePersist() {
if (reconStatusDate != null) {
reconStatusDate = reconStatusDate.withZone(DateTimeZone.UTC);
}
if (executedDate != null) {
executedDate = executedDate.withZone(DateTimeZone.UTC);
}
if (createDate != null) {
createDate = createDate.withZone(DateTimeZone.UTC);
}
}
// getters and setters
}
//controller method
public Response processFile(){
// separate trasaction
service.readFileAndCreateOrders(); // read files and create orders in new status
List<Order> newOrders = service.getNewOrders();
for( Order order: newOrders){
service.processOrder(order); // separate transaction
}
}
#Transaction
void processOrder(OrderEntity order){
matchResultJpaRepository.save(orderEntity.id);
log.info("Saving matchId={} for order={}", match.getId(), order.getId());
// create new transaction and add to order
OrderTransaction transaction = createNewTransaction(order);
order.getTransactions().add(transaction);
order.setStatus("PROCESSED");
log.info("Saving Order id={}, Type={}, Status={} ", order.getId(), order.getType(), order.getStatus());
orderRepository.save(order);
}
I am seeing this below error.
ORA-01407: cannot update ("PAYMENTS"."MATCH_RESULT"."ORDER_ID") to NULL
This endpoing is not exposed to user. There is a batch job which invokes this endpoint.
This code has been there for atleast a year and this is the first time i am seeing this.
This happened only once and for only one call. I am seeing both the logs printed. I am puzzled why I am seeing above error complaining about NULL order id. From the logs, we can confirm that the order id is definitely not null.
Any idea why this is happening? What can be done to fix this?

How to fix Error ManyToMany in #RestController?

I'm an entity Story:
#Entity
#Table(name = "story", schema = "")
#Data
public class Story implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "sID", unique = true, nullable = false)
private Long sID;
#Column(name = "vnName", nullable = false)
private String vnName;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "_scategory",
joinColumns = {#JoinColumn(name = "sID", nullable = false)},
inverseJoinColumns = {#JoinColumn(name = "cID", nullable = false)})
private List<Category> categoryList;
}
And Entity Category:
#Entity
#Table(name = "category", schema = "", uniqueConstraints = {#UniqueConstraint(columnNames = {"cMetatitle"}),
#UniqueConstraint(columnNames = {"cName"})})
#Data
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "cID", unique = true, nullable = false)
private Integer cID;
#Column(name = "cName", unique = true, nullable = false, length = 150)
private String cName;
#ManyToMany(mappedBy = "categoryList")
private List<Story> storyList;
}
But when I grab the Story in RestController, I get the following error message:
WARN http-nio-8080-exec-9
o.s.w.s.m.s.DefaultHandlerExceptionResolver:234 - Failure while trying
to resolve exception
[org.springframework.http.converter.HttpMessageNotWritableException]
java.lang.IllegalStateException: Cannot call sendError() after the
response has been committed
Can anybody show me how to fix it? Thank you!

Can not find entity of the oneToOne relation

public class Maintenance implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#OneToMany(cascade = CascadeType.ALL)
#JoinTable(name = "maintenance_issue_mod",
joinColumns = #JoinColumn(name = "maintenance_id"),
inverseJoinColumns = #JoinColumn(name = "issue_mod_id"))
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<IssueMod> issueMod = new HashSet<>();
#OneToOne(fetch = FetchType.LAZY, targetEntity = COrder.class)
#NotNull
#NotFound(
action = NotFoundAction.IGNORE)
#JoinColumn(name="c_order_id", nullable = false, insertable = false,
updatable = false)
private COrder cOrder;
#OneToOne
#JoinColumn(name = "invoice_id")
private Invoice invoice;
#OneToOne
#JoinColumn(name = "referred_invoice_id")
private Invoice referredInvoice;
getter and setter
this is the Maintenance class and relation of the Maintenance and COrder is OneToOne .
this is corder class
public class COrder implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#CreatedDate
#NotNull
#Column(name = "created", nullable = false)
private Instant created = Instant.now();
#Size(max = 255)
#NotNull
#Column(name = "order_number", length = 255, nullable = false, unique = true)
private String orderNumber;
Maintenance maintenance = maintenanceRepository.findById(maintenanceInvoiceDTO.getMaintenanceId());
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> " +maintenance);
COrder currentOrder = cOrderRepository.findOneById(maintenance.getcOrder().getId());
in the service to find the maintenance through the maintenanceId
then we get the following error
'Unable to find in.bsrnetwork.ctrack.domain.COrder with id 1'
but the corder id 1 is present in the the corder table

JPA Hibernate MapsId for grand child

I am trying to save an entity in JPA 2.1.
I have three tables - MVCollection, MVCollectionVersion (which is versions of MVCollection) and MVBelongsCollection(which is the items belonging to a version).
The Primary Key of MVCollection is a generated sequence number.
When I generate a collection with a version (without any items) I am using #MapsId, and the ID generated is used within the child. However I cannot seem to understand how I can replicate this with the items.
Here are snippets from the code so far :
#Entity
public class MVCollection {
#GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "MVCOLLECTION_SEQ")
#SequenceGenerator(name = "MVCOLLECTION_SEQ",
sequenceName = "VMD.MVCOLLECTION_SEQ")
#Id
#Column(name = "MVCOLLECTIONID")
private Long id;
MVCollectionVersion
#Entity
public class MVCollectionVersion {
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "versionId", column = #Column(name = "MVCVSNID")) })
private MVCollectionVersionId id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumns({
#JoinColumn(name = "MVCOLLECTIONID", referencedColumnName = "MVCOLLECTIONID"),
})
#MapsId("mvCollectionId")
private MVCollection mvCollection;
#OneToMany(fetch = FetchType.LAZY, mappedBy="mvCollectionVersion", cascade={CascadeType.MERGE, CascadeType.PERSIST})
private List<MVBelongsCollection> mvCollectionItems;
MVCollectionId
#Embeddable
public class MVCollectionVersionId implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 2551937096790427792L;
private Long mvCollectionId;
private Integer versionId;
MVBelongsCollection
#Entity
public class MVCollectionItems
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "managedViewId", column = #Column(name = "MANAGEDVIEWID")),
#AttributeOverride(name = "mvCollectionId", column = #Column(name = "MVCOLLECTIONID")),
#AttributeOverride(name = "versionId", column = #Column(name = "MVCVSNID")) })
private MVBelongsCollectionId id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name = "MVCOLLECTIONID", referencedColumnName = "MVCOLLECTIONID"),
#JoinColumn(name = "MVCVSNID", referencedColumnName = "MVCVSNID") })
private MVCollectionVersion mvCollectionVersion;
and finally MVBelongsCollectionId
#Embeddable
public class MVBelongsCollectionId implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Column ( name = "MANAGEDVIEWID", nullable = false, precision = 38)
private Long managedViewId;
#Column ( name = "MVCOLLECTIONID", nullable = false, precision = 38)
private Long mvCollectionId;
#Column ( name = "MVCVSNID", nullable = false, precision = 38)
private Integer versionId;
if I try to create a collection with a version and with belongsCollection items, the create fails as it states the mvCollectionId field is null
"ORA-01400: cannot insert NULL into ("VMD"."MVBELONGSCOLLECTION"."MVCOLLECTIONID")"
Therefore I tried to add #MapsId as I had done with MVCollectionVersion.
public class MVBelongsCollection {
/**
* primary key
*/
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "managedViewId", column = #Column(name = "MANAGEDVIEWID")),
//#AttributeOverride(name = "mvCollectionId", column = #Column(name = "MVCOLLECTIONID")),
#AttributeOverride(name = "versionId", column = #Column(name = "MVCVSNID")) })
private MVBelongsCollectionId id;
/**
* collection that this joins to.
*/
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("mvCollectionId")
#JoinColumns({
#JoinColumn(name = "MVCOLLECTIONID", referencedColumnName = "MVCOLLECTIONID"),
#JoinColumn(name = "MVCVSNID", referencedColumnName = "MVCVSNID") })
private MVCollectionVersion mvCollectionVersion;
However in Eclipse, this shows an error on the #ManyToOne Annotation of
The type of the ID mapped by the relationship 'mvCollectionVersion' does not agree with the primary key class of the target entity.
If I start the process, I get
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: MVBelongsCollection column: MVCVSNID (should be mapped with insert="false" update="false")
I have tried adding insertable = false, and updatable = false to my #JoinColumn, the #AttributeOVerride and the underlying ID class but still get the same error.
This only happens when the #MapsId is present.
I am now at a loss how I get the MVBelongsCollection to use the generated MVCollectionId, or how I can stop both the eclipse and the runtime error.
If anyone can help I would be grateful.
Thanks in advance
I found the error of my ways...
I needed to use the same embeddedId throughout.
Therefore the MVBelongsCollectionId needed to change to include the embedded id of the parent class:
#Embeddable
public class MVBelongsCollectionId implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Embedded
#AttributeOverrides( {
#AttributeOverride(name = "mvCollectionId", column = #Column(name = "MVCOLLECTIONID", nullable = false, precision = 38, scale = 0)),
#AttributeOverride(name = "versionId", column = #Column(name = "MVCVSNID", nullable = false, precision = 8, scale = 0))
})
MVCollectionVersionId collectionVersionId;
#Column ( name = "MANAGEDVIEWID", nullable = false, precision = 38)
private Long managedViewId;
....

Resources