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
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:
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.
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")
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.
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