How to fix Error ManyToMany in #RestController? - spring-boot

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!

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.

JPA - Issue with OneToOne relationship when two foreign keys are primary key to entity

Two foreign keys act as primary key in entity for OneToOne, I'm getting error "Provided id of the wrong type for class ....."
When I tried to POST data, It's getting inserted correctly but GET is not working.
If I change OneToOne to OneToMany it is working for POST & GET both.
Request:
{
"items": [
{
"applicant": {
"guests": [
{
"seqNumber": 1,
"name": "name",
"gender": "gender"
}
]
}
}
]
}
Back Reference:
reservation.getItems().forEach(i -> {
i.setReservation(reservation);
i.getApplicant().setItem(i);
i.getApplicant().getGuests().forEach(g -> g.setApplicant(i.getApplicant()));
});
Reservation Entity:
#Entity
#Getter
#Setter
public class Reservation {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID_RESERVATION", nullable = false, updatable = false)
private String reservationId;
#OneToMany(mappedBy = "reservation", cascade = CascadeType.ALL, orphanRemoval = true)
#JsonManagedReference
private Set<Item> items = new HashSet<>();
}
Item Entity:
#Entity
#Getter
#Setter
#IdClass(Item.ItemKey.class)
public class Item {
#Id
#Column(name = "ID_ITEM_RESERVATION", nullable = false, updatable = false)
private long itemReservationId;
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ID_RESERVATION", referencedColumnName = "ID_RESERVATION", nullable = false, updatable = false)
#JsonBackReference
private Reservation reservation;
#OneToOne(mappedBy = "item", cascade = CascadeType.ALL)
#JsonManagedReference
private Applicant applicant;
#Data
static class ItemKey implements Serializable {
private Reservation reservation;
private long itemReservationId;
}
}
Applicant Entity:
#Entity
#Getter
#Setter
#IdClass(Applicant.ApplicantKey.class)
public class Applicant {
#Id
#OneToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name = "ID_RESERVATION", referencedColumnName = "ID_RESERVATION", nullable = false, updatable = false),
#JoinColumn(name = "ID_ITEM_RESERVATION", referencedColumnName = "ID_ITEM_RESERVATION", nullable = false, updatable = false)
})
#JsonBackReference
private Item item;
#OneToMany(mappedBy = "applicant", cascade = CascadeType.ALL, orphanRemoval = true)
#JsonManagedReference
private Set<Guest> guests = new HashSet<>();
#Data
static class ApplicantKey implements Serializable {
private Item item;
}
}
Guest Entity:
#Entity
#Getter
#Setter
#IdClass(Guest.GuestKey.class)
public class Guest {
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name = "ID_RESERVATION", referencedColumnName = "ID_RESERVATION", nullable = false, updatable = false),
#JoinColumn(name = "ID_ITEM_RESERVATION", referencedColumnName = "ID_ITEM_RESERVATION", nullable = false, updatable = false)
})
#JsonBackReference
private Applicant applicant;
#Id
#Column(name = "S_NUMBER", nullable = false, updatable = false)
private Short seqNumber;
#Column(name = "N_NAME")
private String name;
#Column(name = "CD_GENDER")
private String gender;
#Data
static class GuestKey implements Serializable {
private Applicant applicant;
private Short seqNumber;
}
}
Expected output must be same as Request but getting error " ... Provided id of the wrong type for class ..."
Here is the code.

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

Spring JpaRepository manyToMany bidirectional should save instead of update

if got a language table and a system table with a many-to-many relationship:
Language:
#JsonAutoDetect
#Entity
#Table(name = "language")
public class Language implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "language_id", nullable = false)
private int languageId;
#Column(name = "language_name", nullable = false)
private String languageName;
#Column(name = "language_isocode", nullable = false)
private String languageIsoCode;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "system_language", joinColumns = {#JoinColumn(name = "language_id", updatable = false)},
inverseJoinColumns = {
#JoinColumn(name = "system_id", updatable = false)}, uniqueConstraints = {
#UniqueConstraint(columnNames = {
"language_id",
"system_id"
})})
private List<System> systems;
public Language() {
}
// GETTER & SETTERS
// ....
}
System
#JsonAutoDetect
#Entity
#Table(name = "system")
public class System implements Serializable {
#Id
#Column(name = "system_id", nullable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer systemId;
#Column(name = "system_name", nullable = false, unique = true)
private String systemName;
#OneToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "university_id", nullable = false)
private University university;
#JoinColumn(name = "calender_id", nullable = false)
#OneToOne(fetch = FetchType.EAGER)
private Calendar calender;
#OneToMany(mappedBy = "system")
#LazyCollection(LazyCollectionOption.FALSE)
private List<SystemUserRole> systemUserRoleList;
#OneToMany(mappedBy = "system")
#LazyCollection(LazyCollectionOption.FALSE)
private List<Role> roleList;
#OneToOne(mappedBy = "system")
#LazyCollection(LazyCollectionOption.FALSE)
private CsmUserEntity csmUserEntity;
#ManyToMany(mappedBy = "systems")
#LazyCollection(LazyCollectionOption.FALSE)
private List<Language> languages;
public System() {
}
// GETTER & SETTERS
// ....
}
When im writing a first dataset (systemId=1, language_id=20) into the table, everything works fine. But when i try to write a second dataset with the same language_id but with other system_id (systemId=2, language_id=20), then the existing dataset gets updated. But i want to have a new dataset instead. What can i do?
Thanks in advance!

one to many mapping in hibernate for a messaging service

I have two JPA entities: User and Message.
Each Message has one sender and one receiver of type User. And on the other side each User has two sets of type Message: inbox and outbox.
Message:
#Entity
#Table(name = "messages")
public class Message {
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "seq")
#SequenceGenerator(name = "seq", sequenceName = "MESSAGES_SEQ")
#Column(name = "ID", insertable = false, updatable = false)
private int id;
#ManyToOne
#JoinColumn(name = "SENDER")
private User sender;
#ManyToOne
#JoinColumn(name = "RECEIVER")
private User receiver;
private String subject, content;
private Date sdate;
//getters and setters
}
All the properties which not being mapped with an annotation has he same name as the columns in database and are automatically mapped by JPA.
User:
#Entity
#Table(name = "users")
public class User {
#Column(name = "USERNAME")
private String username;
#Column(name = "PASSWORD")
private String pass;
#Column(name = "EMAIL")
private String email;
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "seq")
#SequenceGenerator(name = "seq", sequenceName = "USERS_SEQ")
#Column(name = "ID", insertable = false, updatable = false)
private int id;
#OneToMany(mappedBy = "uploader")
private Set<Book> books;
#OneToMany(mappedBy = "receiver")
private Set<Message> inbox;
#OneToMany(mappedBy = "sender")
private Set<Message> outbox;
//getters and setters
}
The problem is, when I select an User from Oracle database, then the inbox property is empty. How is this caused and how can I solve it?

Resources