generated primary key for secondary table coming null on #OneToMany relationship - mysql

I'm trying to do a simple #OneToMany relationship between contract and asset. But when hibernate tries to save , it's comming as null. What am I doing wrong?
#Entity
#Data
#EqualsAndHashCode
#NoArgsConstructor
#Table(name = "contracts")
public class Contract {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "contractId")
private List<Asset> assets;
}
#Entity
#Data
#Table(name = "assets")
public class Asset {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#ManyToOne
#JoinColumn(name = "contractId", referencedColumnName = "id")
private Contract contractId;
}
#Repository
public interface ContractRepository extends CrudRepository<Contract, Integer> {
}
private void mapAndSave(ContractDTO contractDTO) {
Contract contractToSave = new Contract();
ModelMapper mapper = BiModelMapper.createModelMapperDtoToEntity();
mapper.map(contractDTO, contractToSave);
contractRepository.save(contractToSave);
}
Caused by: java.sql.SQLIntegrityConstraintViolationException: Column 'contractId' cannot be null

The solution I was able to do is change my column table Asset.contractId to NOT NULL. Because Hibernate tries to insert the row, and after that updates the contractId.
And I change to unidirectional relationship, using only #OneToMany on Contract side.

Related

Itirate over a list and filter specific data coming from JSON then save to MySQL

I have these entities: ReleveBancaireEntity LigneReleveEntity OperationCreditEntity and these transactions entities OperationChequeEntity OperationVirementEntity and OperationEspeceEntity
So my ReleveBancaireEntity has a list of LigneReleveEntity and OperationCreditEntity has inheritance of type single table and all transactions entities extends from OperationCreditEntity, my goal is to verify and filter LigneReleveEntity based on a field called private String creditDebit; and see if it has letter D I should ignore it and don't persist it, and if it has letter C I want to persist it to the database OperationCreditEntity
Here are my entites:
#AllArgsConstructor
#NoArgsConstructor
#Getter
#Setter
#Table(name = "RELEVEBANCAIRE")
#Entity
#ToString
#Builder
public class ReleveBancaireEntity{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long releveBancaireId;
#CreationTimestamp
#Temporal(TemporalType.DATE)
private Date dateReception;
private String label;
private int nbrLignes;
private int nbrOperationCredit;
private int nbrOperationDebit;
private BigDecimal soldeInitial;
private BigDecimal soleFinal;
#OneToMany(cascade= CascadeType.ALL,mappedBy = "releveBancaire", fetch = FetchType.EAGER)
#JsonIgnoreProperties("releveBancaire")
#JsonIgnore
private List<LigneReleveEntity> lignereleve = new ArrayList<>();
=================================
#Table(name = "LIGNERELEVE")
#Entity
#Getter
#Setter
#AllArgsConstructor(access = AccessLevel.PUBLIC)
#NoArgsConstructor(access = AccessLevel.PUBLIC)
#ToString
public class LigneReleveEntity{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long ligneReleveId;
#CreationTimestamp
#Temporal(TemporalType.DATE)
private Date dateOperation;
private String operationNature;
private BigDecimal montant;
private String creditDebit;
// String creditDebit
private int ref;
private int refPaiment;
private String modePaiment;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "FK_releveBancaire", referencedColumnName = "releveBancaireId")
#JsonIgnoreProperties("lignereleve")
private ReleveBancaireEntity releveBancaire;
==============================
#Getter
#Setter
#Table(name = "OPERATIONCREDIT")
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#AllArgsConstructor
#NoArgsConstructor
public class OperationCreditEntity {
#Id
#Column(nullable = false, updatable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long operationCreditId;
#CreatedDate
private Date operationDate;
#OneToOne
private LigneReleveEntity ligneReleve;
===============================
#Getter
#Setter
#Entity
#AllArgsConstructor
#NoArgsConstructor
#DiscriminatorValue("Operation_Especes")
public class OperationEspecesEntity extends OperationCreditEntity {
private String cin;
private String nomEmetteur;
private String prenomEmetteur;
=============================
#Getter
#Setter
#Entity
#AllArgsConstructor
#NoArgsConstructor
#DiscriminatorValue("Operation_Virement")
public class OperationVirementEntity extends OperationCreditEntity {
private String rib;
===========================
#Getter
#Setter
#Entity
#AllArgsConstructor
#NoArgsConstructor
#DiscriminatorValue("Operation_Cheque")
public class OperationChequeEntity extends OperationCreditEntity{
private int numeroCheque;
And this is OperationCreditEntity(SINGLE TABLE) table on MySQL:

Use same Entity multiple times in another Entity

I am implementing a Spring Boot server using JPA and Hibernate where there are 2 entities: Channel and Translation.
The Channel entity has two fields (nameTranslations and descriptionTranslations that should hold the name and description of a channel in 2 languages french and english) which are of type Translation as described as follow:
Class Channel
#Entity
#Table(name = "CHANNEL")
public class Channel {
#Id
#Column(name = "ID")
private String id;
#OneToOne(mappedBy = "channel", cascade = CascadeType.ALL)
private Translation nameTranslations;
#OneToOne(mappedBy = "channel", cascade = CascadeType.ALL)
private Translation descriptionTranslations;
}
and
Class Translation
#Entity()
#Table(name = "TRANSLATION")
public class Translation {
#Id
#Column(name = "ID")
private String id;
#Column(length = 1024)
private String en;
#Column(length = 1024)
private String fr;
}
My issue is: How can I implement the previously described logic so that there are 2 Translation fields in the Channel class? I have tried it so far using #OneToOne annotation, but it doesn't work.
I'm not sure what kind of mapping you are trying to achieve, but this will work:
#Entity
#Table(name = "CHANNEL")
public class Channel {
#Id
#Column(name = "ID")
private String id;
#OneToOne(cascade = CascadeType.ALL)
private Translation nameTranslations;
#OneToOne(cascade = CascadeType.ALL)
private Translation descriptionTranslations;
}
or, if you want the columns on the other entity table:
#Entity
#Table(name = "CHANNEL")
public class Channel {
#Id
#Column(name = "ID")
private String id;
#OneToOne(mapped="name", cascade = CascadeType.ALL)
private Translation nameTranslations;
#OneToOne(mapped="description", cascade = CascadeType.ALL)
private Translation descriptionTranslations;
}
#Entity
#Table(name = "TRANSLATION")
public class Translation {
#Id
#Column(name = "ID")
private String id;
#Column(length = 1024)
private String en;
#Column(length = 1024)
private String fr;
#OneToOne
private Channel name;
#OneToOne
private Channel description;
}
See the Hibernate ORM documentation for one-to-one associations.

Nested one to many relationship jpa spring boot

I have three classes - Document, Page, Sentence. A Document will have multiple Pages & each Page will have multiple Sentences. I'm trying to map One to Many relationship using Spring Data JPA annotation. But it only works when there are only one layer like - Document>Page. Doesn't work while it's Document>Page>Sentence.
Can anyone please give me a solution for how to do it for nested one to many relationship ?
My classes are given below.
#Entity
#Table(name = "DOCUMENT")
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "FILEID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long idFile;
#Lob
#Column(name = "CONTENT")
private byte[] content;
#Column(name = "NAME")
private String name;
#Column(name = "ID_MAIL_USER")
private String idMailUser;
#Column(name = "NUM_PAGES")
private int numPages;
#Column(name = "TO_ANALIZE")
private boolean toAnalize;
#Column(name = "HASH")
private String hash;
#Column(name = "EXTENSION")
private String extension;
#Column(name = "SIZE")
private double size;
#Column(name = "LINK_TO_DRIVE_FILE")
private String linkToDriveFile;
#Column(name="PATH")
private String path;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#Column(name = "PAGES")
private List<Page> pages = new ArrayList<>();
// Setter Getters
}
.
#Entity
#Table(name = "PAGE")
public class Page implements Serializable {
#Id
#Column(name = "PAGE_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long idPage;
#Column(name = "PAGE_NUMBER")
private int pageNum;
#Lob
#Column(name = "CONTENT")
private String content;
#ManyToMany(cascade = CascadeType.ALL)
#Column(name = "SENTENCES")
private List<Sentence> sentences = new ArrayList<>();
// Setter Getters
}
.
#Entity
#Table(name = "SENTENCE")
public class Sentence implements Serializable {
//private long idFile;
//private long idPage;
#Id
#Column(name = "SENTENCE_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "PAGE_NUMBER")
private int pageNumber;
#Column(name = "ORDER")
private int ord;
#Column(name = "CONTENT")
private String content;
#Column(name = "HASH")
private String hash;
// Setter Getters
}
Your OneToMany mappings are incorrect. Correct it as follows
#Entity
#Table(name = "DOCUMENT")
public class Document implements Serializable {
......
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "DOCUMENT_ID") //Name the foreign key column in PAGE table to DOCUMENT_ID
private List<Page> pages = new ArrayList<>();
}
#Entity
#Table(name = "PAGE")
public class Page implements Serializable {
....
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "PAGE_ID") //Name the forein key column in PAGE table to PAGE_ID
private List<Sentence> sentences = new ArrayList<>();
}
Use #JoinColumn annotation instead of #Column to give the name of the foreign key that do the physical mapping between tables in your database.
#Entity
#Table(name = "DOCUMENT")
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy="document")
#Column(name = "PAGES")
private List<Page> pages = new ArrayList<>();
}
#Entity
#Table(name = "PAGE")
public class Page implements Serializable {
#ManyToOne
#JoinColumn(name="DOCUMENT_ID")
private Document document;
#ManyToMany(cascade = CascadeType.ALL, mappedBy="pages")
#Column(name = "SENTENCES")
private List<Sentence> sentences = new ArrayList<>();
}
#Entity
#Table(name = "SENTENCE")
public class Sentence implements Serializable {
#ManyToMany(mappedBy="sentences")
private List<Page> pages;
}
Here a Document One to Many relationship with Pages.
So.. we need define mappedBy in the entity we want to map another entity.. so in this case
#OneToMany(mappedBy="document",cascade = CascadeType.ALL, orphanRemoval = true)
and in referenced entity i.e. Pages we want foreign key DOCUMENT_ID, so we have to define it using
#ManyToOne
#JoinColumn(name="DOCUMENT_ID")

Hibernate, Spring Data, insert id of table parent on table child

I'm trying insert the id of Person in child table 'Contact'. But the Hibernate stores the value null at fk column.
I perform the mapping of a DTO to the entity, where it already brings the person's data and contact. In the end I have to save the person entity.
There is a table inheritance!
Parent table:
#Entity
#Table
#Inheritance(strategy = InheritanceType.JOINED)
#DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING, columnDefinition = "CHAR(2)", length = 2)
public abstract class Person implements Serializable {
#OneToMany(fetch = FetchType.EAGER, mappedBy = "person")
#Cascade(value={org.hibernate.annotations.CascadeType.ALL})
private #Getter #Setter Set<Contact> contacts;
}
Table Company extends of Person:
#Entity
#Table
#DiscriminatorValue(value="PJ")
public class Company extends Person implements Serializable {
#Column(nullable = false, columnDefinition = "DATE")
private #Getter #Setter LocalDate constitutionDate;
}
And where is the problem!
#Entity
#Table(name = "contact")
#EqualsAndHashCode
public class Contact implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private #Getter Integer id;
#Column(columnDefinition = "VARCHAR(16)", length = 16, nullable = false)
private #Getter #Setter String phoneNumber;
#ManyToOne(fetch = FetchType.LAZY, optional = false,targetEntity=Person.class)
#JoinColumn(name = "person_id", nullable = false, referencedColumnName="id")
private #Getter #Setter Person person;
public Contact() {}
public Contact(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
What am I doing wrong? What's the best strategy?
Excuse me for my poor English!
Can't find nothing obvious that's wrong but let me try some things:
Your cascade annotation on Person class doesn't need the specific Hibernate enumeration You can use like :
#OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL }, mappedBy = "cliente")
In your ManyToOne annotation on Contact class please try to add:
#ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
BTW, an inheritance relationship between Person and Company doesn't seem logic to me, but that has nothing to do with your stated problem for sure.

create composite primary key using foreign key using hibernate

I have a table complaint master which contains a primary key which is further used as a foreign key inside another table named as complaint_treatment having one to many relationship .
#Entity
#Table(name = "complaint_master")
public class ComplaintMaster{
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
#Column(name = "complaint_id")
private long complaint_id;
#OneToMany(mappedBy= "complaintMasterForkey", cascade = CascadeType.ALL )
/*#JsonManagedReference(value="ComplaintTreatmentKey-ComplaintMaster")*/
#LazyCollection(LazyCollectionOption.FALSE)
private List<ComplaintTreatmentKey> complaintTreatmentKey = new ArrayList<>();
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "submitted_on")
private Date submitted_on;
#Column(name = "auth_code")
private String authCode;
// GETTERS AND SETTERS
}
I have another table complaint_treatment in which i have to create composite primary key but the key two fields that are participating are foreign key.
so i used embeded to solve this issue.
#SuppressWarnings("serial")
#Embeddable
public class ComplaintTreatmentKey implements Serializable {
#ManyToOne(cascade = CascadeType.ALL)
#JsonBackReference(value = "ComplaintTreatmentKey-ComplaintMaster")
#JoinColumn(name = "complaint_id")
protected ComplaintMaster complaintMasterForkey;
#ManyToOne(cascade = CascadeType.ALL)
#JsonBackReference(value = "ComplaintTreatmentKey-ServiceCategory")
protected ServiceCategory serviceCategoryForKey;
}
and then using #EmbeddedId use it.
#Entity
#Table(name = "complaint_treatment")
public class ComplaintsTreatment {
#EmbeddedId
private ComplaintTreatmentKey treatmentComplaintKey;
#Column(name = "description")
private String description;
#JoinColumn(name = "status_id")
private StatusMaster statusMaster;
#Column(name = "rca")
private String rca;
#JoinColumn(name = "priority_id")
private PriorityMaster priorityMaster;
#JoinColumn(name = "assigend_to")
private Employee assignedTo;
#Column(name = "closed_on")
private Date closedOn;
}
but it through an error
Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Use of #OneToMany or #ManyToMany targeting an unmapped class: com.nxtlife.model.ComplaintMaster.complaintTreatmentKey