Nullable #ManyToOne not accepting null value [duplicate] - java

This question already has an answer here:
Set parent target to null if source is null in MapStruct
(1 answer)
Closed 4 years ago.
I have a many-to-one relationship that I want to be nullable.
Here's the parent:
#Entity
#Table(name = "C_CUSTOMER")
class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#OneToMany (fetch = FetchType.LAZY, mappedBy="user", cascade = CascadeType.REMOVE)
private List<Profile> profiles;
}
And the child:
#Entity
#Table(name = "C_PROFILE")
class Profile {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#ManyToOne(optional = true)
#JoinColumn(nullable = true, name = "user_id", referencedColumnName = "id", insertable = false, updatable = false)
private User user;
}
When I try to save a profile without a userId, the following error is threw:
org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : fr.entity.Profile.user -> fr.entity.User
If the field userId has a value, then it works smoothly.
I tried a bunch of answers from other questions on SO, but so far nothing has worked. The easiest way would be to ditch the relation in the entity files and use Integer customerId, but that's not really satisfactory for me, 'cause it would mean that the cascade deletion wouldn't work anymore.
Thanks in advance.
EDIT
The problem comes from a entity <-> dto mapping. I added an answer about it, will probably edit if I come across a workaround.

Tried your code on my machine. Below are my entity classes:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import lombok.Data;
#Entity
#Table(name = "C_PROFILE")
#Data
public class Profile {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
#ManyToOne(optional = true)
#JoinColumn(nullable = true, name = "user_id", referencedColumnName = "id", insertable = false, updatable = false)
private User user;
}
User class:
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import lombok.Data;
#Entity
#Table(name = "C_CUSTOMER")
#Data
class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String email;
#OneToMany (fetch = FetchType.LAZY, mappedBy="user", cascade = CascadeType.REMOVE)
private List<Profile> profiles;
}
Repository:
import org.springframework.data.jpa.repository.JpaRepository;
import io.polarisdev.returns.model.Profile;
public interface ProfileRepository extends JpaRepository<Profile, String> {
}
Code to save the Profile without user:
Profile p = new Profile();
p.setName("Name");
profileRepository.save(p);

So, after some digging inside the generated files: there's no solution to it (for now). The problem comes from a mapping between entity <-> dto, using mapstruct: having not mentioned this step, no wonder it wasn't working like it should for me... Well, the profile mapper contains this:
protected User profileToUser(Profile profile) {
if ( profile == null ) {
return null;
}
User user = new User();
User.setId(profile.getUserId());
return user;
}
Meaning I need to reassign a null value before saving the Profile. There is apparently a ticket about this on the github, so wait and see. Seems like there's some suggestions too to make it work, so if I come across one that work, i'll edit this answer (unless someone answer with a solution before).
EDIT
After a few researches on the mapstruct git and SO, I came across a solution that work, though it's not really elegant.
#AfterMapping
public Profile doAfterMapping(#MappingTarget Profile entity) {
if (entity != null && entity.getUser().getId() == null) {
entity.setUser(null);
}
return entity;
}
So... I'll put the question in duplicate. Thanks a bunch to the ones that helped me (though I wouldn't have need to post if I had been more vigilant).

Related

Spring JPA add pagination to #ManyToMany [duplicate]

This question already has answers here:
Spring Data JPA Pageable with #ManyToMany
(2 answers)
Closed 1 year ago.
In my current project, I am using JPA and Hibernate to handle my database layer.
One of my entities has a Many-To-Many relation to itself, which works great using the #ManyToMany and the #JoinTable annotations.
My problem is that I am asked to add a pagination support to the entity. I have searched online for a solution but the closest thing I have found to a solution works on a different use case, where the relation is between 2 entities (and not an entity to itself).
This is the important parts from the entity's class:
package iob.data;
import iob.data.primarykeys.InstancePrimaryKey;
import iob.logic.exceptions.instance.InvalidBindingOperationException;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
#NoArgsConstructor
#AllArgsConstructor
#Getter
#Setter
#RequiredArgsConstructor
#Entity
#Table(name = "INSTANCES")
#IdClass(InstancePrimaryKey.class)
public class InstanceEntity {
//<editor-fold desc="Primary key">
#Id
// The index would be generated from a sequence named "INSTANCES_SEQUENCE"
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "INSTANCES_SEQUENCE")
// Here we create that sequence, and define it to be updated every insertion (allocationSize = 1).
#SequenceGenerator(name = "INSTANCES_SEQUENCE", sequenceName = "INSTANCES_SEQUENCE", allocationSize = 1)
private long id;
#Id
#NonNull
private String domain;
//</editor-fold>
//<editor-fold desc="Many to Many relation">
// Define a new table that would store the references
#JoinTable(name = "INSTANCES_TO_INSTANCES",
// The main columns for this attribute are the parent's primary key which is constructed from domain and id
inverseJoinColumns = {#JoinColumn(name = "PARENT_ID", referencedColumnName = "id"),
#JoinColumn(name = "PARENT_DOMAIN", referencedColumnName = "domain")},
// The referenced columns for this attribute are the child's primary key which is also constructed from domain and id
joinColumns = {#JoinColumn(name = "CHILD_ID", referencedColumnName = "id"),
#JoinColumn(name = "CHILD_DOMAIN", referencedColumnName = "domain")})
// Declare the parent's side of the relation
#ManyToMany(fetch = FetchType.LAZY)
private Set<InstanceEntity> parentInstances = new HashSet<>();
// Declare the children's size of the relation, and define that it is related to the parentInstances
#ManyToMany(mappedBy = "parentInstances", fetch = FetchType.LAZY)
private Set<InstanceEntity> childInstances = new HashSet<>();
//</editor-fold>
public void addParent(InstanceEntity parent) {
if (this.equals(parent))
throw new InvalidBindingOperationException("Cannot assign parent to himself");
parentInstances.add(parent);
}
public void addChild(InstanceEntity child) {
if (this.equals(child))
throw new InvalidBindingOperationException("Cannot assign child to himself");
childInstances.add(child);
}
#Override
public int hashCode() {
return Objects.hash(id, domain);
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
InstanceEntity entity = (InstanceEntity) o;
return id == entity.id && domain.equals(entity.domain);
}
}
So far I tried (probably naively) write the getter for parentInstance and pass it a Pagable object (because it works on derived-queries, so worth a shot 😅) but obviously it did nothing.
The only solution I can think of is removing the relation, and creating it manually (create the table using another entity and add a new PagingAndSortingRepository that would retrieve the relevant instances and then convert them to InstanceEntity in the service).
So, how can I add a pagination support for parentInstances and childInstances?
I have found the solution in some unexpected post. It is not about pagination, but it still solved my problem.
So the solution in my case was to add the following function to my PagingAndSortingRepository interface:
Page<InstanceEntity> findDistinctByParentInstancesIn(#Param("parent_instances") Set<InstanceEntity> parentInstances, Pageable pageable);
And then calling it is:
InstanceEntity ie = new InstanceEntity();
ie.setDomain(parentDomain);
ie.setId(Long.parseLong(parentId));
instancesDao.findDistinctByParentInstancesIn(Collections.singleton(ie), PageRequest.of(page, size));
To be honest, I'm not sure how/why it works. IntelliJ IDEA gives me an error in the repository interface Expected parameter types: Collection<Set<InstanceEntity>>.
So if someone has an explanation, I would be glad to hear it.

avoid circular dependency on hibernate

package com.example.demo.model;
import com.sun.istack.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.util.*;
#Data
#NoArgsConstructor
#AllArgsConstructor
#Entity
#EntityListeners(AuditingEntityListener.class)
#Table(name="MEDICAL_DEVICE")
public class MedicalDevice {
public MedicalDevice(UUID deviceId, DefectPriority defectPriority, State currentState) {
this.deviceId = deviceId;
this.defectPriority = defectPriority;
this.currentState = currentState;
}
public MedicalDevice(UUID deviceId, State currentState) {
this.deviceId = deviceId;
this.currentState = currentState;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name="DEVICE_ID")
#NotNull
private UUID deviceId;
#Column(name="DEFECT_PRIORITY", nullable = true)
#Enumerated(EnumType.STRING)
private DefectPriority defectPriority;
#OneToMany(mappedBy="medicalDevice")
private List<State> states = new ArrayList<>();
#OneToOne(mappedBy="medicalDevice")
private State currentState;
}
package com.example.demo.model;
import com.sun.istack.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
#Data
#NoArgsConstructor
#AllArgsConstructor
#Entity
#EntityListeners(AuditingEntityListener.class)
#Table(name="STATE")
public class State {
public State(StateNames state, UUID enteredBy, LocalDateTime enteredAt) {
this.state = state;
this.enteredBy = enteredBy;
this.enteredAt = enteredAt;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Enumerated(EnumType.STRING)
private StateNames state;
#Column(name="USER_ID")
private UUID enteredBy; //User who changed the devices state to this one
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="MEDICAL_DEVICE_ID")
#NotNull
private MedicalDevice medicalDevice;
#Column(name = "LOCAL_DATE_TIME", columnDefinition = "TIMESTAMP")
private LocalDateTime enteredAt; //Time when the devices state was changed into this one
#Column(name = "LOCAL_DATE", columnDefinition = "DATE")
private LocalDate availabilityDate; //Date when a device will be available (only used in defect states and bought state)
#OneToMany(mappedBy="state")
private List<AdditionalInformation> additionalInformation;
}
how to avoid circular dependency on hibernate between State class and MedicalDevice class? I have implemented #OneToMany List which is the old states and #OneToOne State currentState which indicates the current state. I would like to have it separate not all in the list but my implementation causes that>
enter image description here
Annotate MedicalAdvice object inside your State class with #JsonIgnore annotation. This way, you can prevent infinite recursive fetching of data from relationships between entity classes.
You don't provide the error message so it's hard to know exactly what's causing the circular dependency, but the basic idea is that it stems from the fact that MedicalDevice has a reference to State and vice versa, so each rely on the other.
(Incidentally, you also have MedicalDevice set up to have a list of State with a #OneToMany relationship, and one instance of State with a #OneToOne relationship. That doesn't really work, either it's a #OneToMany or it's #OneToOne. Put another way, either MedicalDevice has one State or it has many States, but it doesn't have both. I don't know if that is contributing to your problem).
In any event, it's possible the circular dependency is due to either the equals/hashcode being called, or perhaps the toString method. MedicalDevice maybe calling these methods on its State variable, which in turn will call the method on its MedicalDevice variable, etc.
A possible resolution would be to exclude the references from the equals/hashcode and toString methods. But again, without the details of the error it hard to tell what the exact issue is.

How to correctly use #ContainedIn annotation in Hibernate Search?

I'm using Hibernate with PostgreSQL
and Hibernate Search (5.7.0.Alpha1)
with ElasticSearch (2.4.2).
I have two classes: Book and Author.
A book can have many authors
and an author can author more than one book.
I annotated Book class like this:
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
import org.hibernate.search.annotations.*;
#Indexed
#Entity
public class Book implements Record {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE)
protected Long id;
#Field
protected String title;
#ManyToMany
#JoinTable(name = "books_authors",
joinColumns = #JoinColumn(name = "book_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "author_id", referencedColumnName = "id"))
#IndexedEmbedded(includeEmbeddedObjectId = true)
protected List<Author> authors = new ArrayList<>();
//constructors, getters and setters
//...
}
The problem is that when an author gets updated
(for example their name changes), the document of the correspoding book
does not change in ElasticSearch.
For example after executing this code:
package com.example.app;
import com.example.app.model.Author;
import com.example.app.model.Book;
import com.example.app.model.Category;
import java.io.IOException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class App
{
public static void main(String[] args) throws IOException
{
SessionFactory sessionFactory = new Configuration().configure()
.buildSessionFactory();
Author author01 = new Author("Author 01");
Book book01 = new Book("Book 01");
book01.addAuthor(author01);
{
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(author01);
session.save(book01);
session.getTransaction().commit();
session.close();
}
author01.setName("Author 02");
{
Session session = sessionFactory.openSession();
session.beginTransaction();
session.saveOrUpdate(author01);
session.getTransaction().commit();
session.close();
}
//without this the app won't end
System.exit(0);
}
}
the author document in ElasticSearch will get updated,
but the book document will not change:
{"_index":"com.example.app.model.author","_type":"com.example.app.model.Author","_id":"2","_score":1,
"_source":{"name":"Author 02"}}
{"_index":"com.example.app.model.book","_type":"com.example.app.model.Book","_id":"3","_score":1,
"_source":{"title":"Elementy","authors":[{"name":"Author 01", "id":"2"}]}}}
I read that for the situations like this I need to use #ContainedIn annotation at the Author side,
so I did. For this reason I needed to add the property authoredBooks, I didn't plan it before.
package com.example.app.model;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
import org.hibernate.search.annotations.*;
#Indexed
#Entity
public class Author {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE)
protected long id;
#Field
protected String name;
#ContainedIn
#ManyToMany(mappedBy = "authors")
private List<Book> authoredBooks = new ArrayList<>();
//constructors, getters and setters
//...
}
This however did not change the behaviour of Hibernate Search,
so book document is still not updated.
Could you give some hints on what can I do or check?
I'm using Hibernate with PostgreSQL and Hibernate Search (5.7.0.Alpha1) with ElasticSearch (2.4.2).
First thing to do would be to upgrade to an actual release of Hibernate Search (not an Alpha or Beta), to be sure you're not experiencing a bug that has been solved since.
Apart from that... your initial code only updates one side of the relationship; did you make sure to add a author01.addBook(book01) line after ook01.addAuthor(author01)?

#OneToMany SQLIntegrityConstraintViolationException error upon insert (Hibernate)

I am having trouble inserting records with a #OneToMany relationship using Hibernate and Spring MVC. I can successfully insert records without adding anything to the #OneToMany collection. However, upon adding a collection record, it fails stating that there is a SQLIntegrityConstraintViolationException.
My current code for the mapping (annotation-style) is as follows:
Contact.java
package mil.navy.navsupbsc.entity;
import java.util.Collection;
import java.util.LinkedHashSet;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
#Entity
#Table(name = "CONTACT2")
public class Contact extends Auditable {
public Contact() {
}
// Create with mandatory fields
public Contact(long id, Salutation salutation, String firstName,
String middleInitial, String lastName,
MilitaryCivilianInformation milCivInfo) {
this.setContactId(id);
this.setSalutation(salutation);
this.setFirstName(firstName);
this.setMiddleInitial(middleInitial);
this.setLastName(lastName);
this.setMilitaryCivilianInformation(milCivInfo);
}
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#SequenceGenerator(name = "CONTACT_SEQ")
#Column(name = "CONTACT_ID")
private Long contactId;
#Fetch(FetchMode.SUBSELECT)
#OneToMany(cascade = { CascadeType.ALL, CascadeType.REMOVE }, mappedBy = "contact", orphanRemoval = true)
private Collection<Email> emails = new LinkedHashSet<Email>();
/**
* #return the emails
*/
public Collection<Email> getEmails() {
for (Email email : emails) {
email.getEmailType();
}
return emails;
}
/**
* #param emails
* the emails to set
*/
public void setEmails(Collection<Email> emails) {
this.emails.clear();
for (Email email : emails) {
this.addEmail(email);
}
}
public void addEmail(Email email) {
email.setContact(this);
this.getEmails().add(email);
}
[...more Getters / Setters and fields]
}
Email.java
package mil.navy.navsupbsc.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.codehaus.jackson.annotate.JsonBackReference;
/**
* Implements Auditing Properties
*/
#Entity
#Table(name = "EMAIL")
public class Email extends Auditable {
private static final long serialVersionUID = -4833322552325183301L;
#Id
#GeneratedValue
#SequenceGenerator(name = "EMAIL_SEQ")
#Column(name = "EMAIL_ID")
private long emailId;
#JsonBackReference
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "CONTACT_FK")
private Contact contact;
[More fields]
public Contact getContact() {
return contact;
}
public void setContact(Contact contact) {
this.contact = contact;
}
public long getEmailId() {
return emailId;
}
public void setEmailId(long emailId) {
this.emailId = emailId;
}
[more getters / setters]
}
ContactDAOImpl (I've tried many variations of this with no success)
public void saveContact(Contact contact) {
Session session = sessionFactory.getCurrentSession();
Collection<Email> emailCollection = new LinkedHashSet<Email>();
emailCollection = contact.getEmails();
Contact contactToSave;
long contactId;
if (contact.getContactId() == 0 || contact.getContactId() == null) {
contactToSave = new Contact((long) 0, contact.getSalutation(),
contact.getFirstName(), contact.getMiddleInitial(),
contact.getLastName(),
contact.getMilitaryCivilianInformation());
session.save(contactToSave);
session.flush();
for (Email email : emailCollection) {
// email.setContact(contactToSave);
contactToSave.addEmail(email);
}
session.saveOrUpdate(contactToSave);
session.flush();
session.clear();
}
Any help with this is much appreciated. I had a previous version of this that updated records correctly, but can't seem to work out the Save new records. I also originally used the contact that I passed in from the web service, but I attempted to create a new record in the DAO to eliminate potential problems in the latest variation of my code.
Also, I know that there are many similar questions, but I have tried many of the answers with no success (hence the new question).
Thank you for your help!
UPDATE
I checked to see what ID the data layer returns after the initial save and verified (unsuccessfully) that the same ID was saved in the database. The returned ID is different than the saved ID. For example, the latest save showed the Contact ID as '1129' with the returned contact after the initial save. I did a retrieve from the database with contact ID '1129' - and it successfully returned the contact. After closing the transaction, I viewed the data directly in the database. The database showed '193' as the Contact ID instead of '1129'. Any ideas??
I figured out the issue I was having.
Prior to creating the Hibernate entity definition, I created a sequence and trigger in the database directly. I also specified the same sequence in the entity definition within the JAVA hibernate code. However, my syntax for generating the sequence was not complete.
Since the syntax for generating the sequence was incomplete, the JAVA code was using the default HIBERNATE_SEQUENCE generator, rather than the sequence I created. Hibernate returned the sequence value from HIBERNATE_SEQUENCE (creating the ID prior to the database insert). However, immediately prior to inserting the value into the database, Oracle ran my custom sequence and assigned the Contact ID to the newly generated value.
Consequently, when I tried to add a value to the collection, the Insert statement attempted to use the sequence value generated by Hibernate as the foreign key, rather than the sequence value generated by the database.
In order to ensure that the Hibernate code and database were in sync, I removed the ContactID trigger from the database. Based on another question in StackOverflow (Hibernate and Oracle Sequence), I updated the JAVA Hibernate code for the Contact.java ContactID declaration to:
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CONTACT_SEQ")
#SequenceGenerator(name = "CONTACT_SEQ", sequenceName = "contact_seq", allocationSize = 1)
#Column(name = "CONTACT_ID")
private Long contactId;
Thankfully this fixed the problem. The JAVA Hibernate code now creates the ID through the sequence I specified. The database then successfully inserts those values into the database!
I was also able to simplify my save to:
public void saveContact(Contact contact) {
Session session = sessionFactory.getCurrentSession();
if (contact.getContactId() == 0 || contact.getContactId() == null) {
session.save(contact);
session.flush();
}
}
I'm sure that I'll need to change it again though to account for updating the contact - probably using saveOrUpdate() instead of save().

JPA with #ManyToOne

I have two classes like this
package models;
import java.util.*;
import javax.persistence.*;
import play.db.jpa.*;
#Entity
#Table(name = "commitment_type_value")
public class CommittmentTypeValue extends Model{
#Id
#Column(name = "id", nullable = false)
public Long id;
#Column(name = "value", nullable = true)
public String type;
#ManyToOne
#JoinColumn(name="commitment_type_id")
public CommitementType commitmentType;
public CommittmentTypeValue(){
}
}
-------------
package models;
import java.util.*;
import javax.persistence.*;
import play.db.jpa.*;
/**
*
* #author hatem
*/
#Entity
#Table(name = "commitment_type")
public class CommitementType extends Model{
#Id
#Column(name = "id", nullable = false)
public Long id;
#Column(name = "type", nullable = true)
public String type;
#OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="commitmentType")
public List<CommittmentTypeValue> commitmentTypeValues;
public CommitementType(){
}
}
when I execute my app, this problem appears :
A JPA error occurred (Unable to build EntityManagerFactory): A Foreign
key refering models.CommitementType from models.CommittmentTypeValue
has the wrong number of column. should be 2
Please, can Any one tell me what 's wrong ?
Please check your foreign key column name it should match the exactly with the name of column.
EDIT
If your problem is still unsolved then please check if your persistance.xml has
<property name="generateDdl" value="true" />
and if it already have then check if you are getting any error in generation of table.
If yes then clear the data in table
or
add drop-and-create-tables option in config file
or
change your code as follows
#ManyToOne(optional=true)
#JoinColumn(name="commitment_type_id", nullable = true)
public CommitementType commitmentType;
Because you might have old data in table which might be stopping the creation of new table.
Reference column name is missing in your many to one join in class CommittmentTypeValue
#ManyToOne
#JoinColumn(name="commitment_type_id" referencedColumnName="id" )
public CommitementType commitmentType;
Also specify target entity
#OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, targetEntity=CommittmentTypeValue.class, mappedBy="commitmentType")
public List<CommittmentTypeValue> commitmentTypeValues;
The error sounds like you Id in CommitementType is composite, so your foreign key must contain two columns.
Include the code for the CommitementType.

Categories

Resources