I have following code to persist data in Oracle.
Language lang = new Language();
lang.setLangCode("06");
lang.setLanguage("german");
Data dc = new Data();
dc.setDescription("description_german");
dc.setName("name_german");
dc.setLanguage(lang);
//2.
Language lang2 = new Language();
lang2.setLangCode("06");
lang2.setLanguage("german");
Document doc = new Document();
doc.setDescription("description_de");
doc.setName("name_de");
doc.setLanguage(lang2); // When I do like: doc.setLanguage(lang) it persists the data
doc.setDataCollection(dc);
em.merge(doc);
When I run the above code it give me transaction rollback following are the logs
TRACE org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction - Adding resolved non-early insert action.
09-02-2018 15:14:54.273 TRACE org.hibernate.engine.internal.Cascade.cascade - Processing cascade ACTION_MERGE for: com.fis.cdpr.model.DataCollection
09-02-2018 15:14:54.273 TRACE org.hibernate.engine.internal.Cascade.cascade - Done processing cascade ACTION_MERGE for: com.fis.cdpr.model.DataCollection
09-02-2018 15:14:54.273 TRACE org.hibernate.engine.spi.CascadingAction.cascade - Cascading to merge: com.fis.cdpr.model.Language
09-02-2018 15:14:54.274 TRACE org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached - Merging detached instance
09-02-2018 15:14:54.274 TRACE org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad - Loading entity: [com.fis.cdpr.model.Language#06]
09-02-2018 15:14:54.274 TRACE org.hibernate.event.internal.DefaultLoadEventListener.doLoad - Attempting to resolve: [com.fis.cdpr.model.Language#06]
09-02-2018 15:14:54.274 TRACE org.hibernate.event.internal.DefaultLoadEventListener.doLoad - Resolved object in session cache: [com.fis.cdpr.model.Language#06]
09-02-2018 15:14:54.274 DEBUG org.hibernate.jpa.spi.AbstractEntityManagerImpl.markForRollbackOnly - Mark transaction for rollback
I have overriden equals and hashcode for Language object
Then I tried following code just o check the problem and it worked!!
Language lang1 = new Language();
lang1.setLangCode("06");
Language lang2 = new Language();
lang2.setLangCode("06");
em.merge(lang1);
em.merge(lang2);
See logs below:
09-02-2018 16:59:44.840 TRACE org.hibernate.engine.spi.ActionQueue.addInsertAction - Adding insert with no non-nullable, transient entities: [EntityInsertAction[com.fis.cdpr.model.Language#06]]
09-02-2018 16:59:44.840 TRACE org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction - Adding resolved non-early insert action.
09-02-2018 16:59:44.842 TRACE org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached - Merging detached instance
09-02-2018 16:59:44.842 TRACE org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad - Loading entity: [com.fis.cdpr.model.Language#06]
09-02-2018 16:59:44.843 TRACE org.hibernate.event.internal.DefaultLoadEventListener.doLoad - Attempting to resolve: [com.fis.cdpr.model.Language#06]
09-02-2018 16:59:44.843 TRACE org.hibernate.event.internal.DefaultLoadEventListener.doLoad - Resolved object in session cache: [com.fis.cdpr.model.Language#06]
09-02-2018 16:59:44.847 DEBUG org.hibernate.engine.transaction.internal.TransactionImpl.commit - committing
I need to understand why hibernate after looking Language object from cache is not able to persist same language object( diff reference ) but able to persist same object reference and also different language objects
I have provided relation on both Data and Document entites with Language as below
#ManyToOne(cascade= CascadeType.ALL)
#JoinColumn(name = "language_fk")
private Language language;
Update=> exception says
exception [java.lang.IllegalStateException: Multiple representations of the same entity [spring.model.Language#06] are being merged. Detached: [spring.model.Language#b588a401]; Detached: [spring.model.Language#b588a401]]
Document class
#Entity
public class Document {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="doc_name", nullable=true)
private String name;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn
private Language lang;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn
private Data data;
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Language getLang() {
return lang;
}
public void setLang(Language lang) {
this.lang = lang;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((lang == null) ? 0 : lang.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Document other = (Document) obj;
if (id != other.id)
return false;
if (lang == null) {
if (other.lang != null)
return false;
} else if (!lang.equals(other.lang))
return false;
return true;
}
Data Class
#Entity
public class Data {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="doc_name", nullable=true)
private String name;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name="doc_fk")
private Document doc;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn
private Language lang;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Document getDoc() {
return doc;
}
public void setDoc(Document doc) {
this.doc = doc;
}
public Language getLang() {
return lang;
}
public void setLang(Language lang) {
this.lang = lang;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((lang == null) ? 0 : lang.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Data other = (Data) obj;
if (id != other.id)
return false;
if (lang == null) {
if (other.lang != null)
return false;
} else if (!lang.equals(other.lang))
return false;
return true;
}
}
}
Language class
#Entity
public class Language {
#Id
private String langCode;
private String language;
public String getLangCode() {
return langCode;
}
public void setLangCode(String langCode) {
this.langCode = langCode;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((langCode == null) ? 0 : langCode.hashCode());
result = prime * result + ((language == null) ? 0 : language.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Language other = (Language) obj;
if (langCode == null) {
if (other.langCode != null)
return false;
} else if (!langCode.equals(other.langCode))
return false;
if (language == null) {
if (other.language != null)
return false;
} else if (!language.equals(other.language))
return false;
return true;
}
}
From the exception and when I executed em.merge(lang); em.merge(lang2) I believe it worked because there are two seperate calls to persist/merge the data thats why I never got exception while doing so. But otherwise it gives exception. Isn't hibernate suppose to merge objects when it finds one same object in Session. ?
Related
I have 2 entities namely Teacher and Club, I need to retrieve the teacher data along with its related club and/or sports.
I a bit new to JPA so am having trouble debugging the stack overflow error I get when I use the findAll method on the Teacher repository.
I had tried adding #JsonIgnore annotation to my one-to-many annotation to deal with the recursion problem as suggested in some similar questions but was still getting problems and am not sure how exactly it's supposed to solve the problem.
TEACHER ENTITY:
#Entity
#Table(name = "TEACHER")
public class Teacher {
private String id;
private String name;
private Collection<ClubTeacher> clubTeachersById;
#Id
#Column(name = "Id", nullable = false, length = 10)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Basic
#Column(name = "NAME", nullable = true, length = 25)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Teacher teacher = (Teacher) o;
if (id != null ? !id.equals(teacher.id) : teacher.id != null) return false;
if (name != null ? !name.equals(teacher.name) : teacher.name != null) return false;
return true;
}
#Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
#OneToMany(mappedBy = "TICClub" ,fetch = FetchType.EAGER)
public Collection<ClubTeacher> getClubTeachersById() {
return clubTeachersById;
}
public void setClubTeachersById(Collection<ClubTeacher> clubTeachersById) {
this.clubTeachersById = clubTeachersById;
}
}
CLUB ENTITY:
#Entity
#Table(name = "CLUB_TEACHER", schema = "abbc", catalog = "")
#IdClass(ClubTeacherPK.class)
public class ClubTeacher implements Serializable {
private String tic;
private String clubkey;
private Teacher teacherByTic;
#Id
#Column(name = "TIC", nullable = false, length = 10)
public String getTic() {
return tic;
}
public void setTic(String tic) {
this.tic = tic;
}
#Id
#Column(name = "CLUBKEY", nullable = false, length = 25)
public String getClubkey() {
return clubkey;
}
public void setClubkey(String clubkey) {
this.clubkey = clubkey;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ClubTeacher that = (ClubTeacher) o;
if (tic != null ? !tic.equals(that.tic) : that.tic != null) return false;
if (clubkey != null ? !clubkey.equals(that.clubkey) : that.clubkey != null) return false;
return true;
}
#Override
public int hashCode() {
int result = tic != null ? tic.hashCode() : 0;
result = 31 * result + (clubkey != null ? clubkey.hashCode() : 0);
return result;
}
#ManyToOne
#JoinColumn(name = "TIC", referencedColumnName = "Id", nullable = false,insertable=false, updatable=false)
public Teacher getTeacherByTic() {
return teacherByTic;
}
public void setTeacherByTic(Teacher teacherByTic) {
this.teacherByTic = teacherByTic;
}
}
STACK TRACE:
2021-02-17 21:42:56.516 ERROR 20546 --- [nio-3005-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.StackOverflowError] with root cause
java.lang.StackOverflowError: null
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245) ~[gson-2.8.6.jar:na]
at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:1027) ~[gson-2.8.6.jar:na]
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) ~[gson-2.8.6.jar:na]
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127) ~[gson-2.8.6.jar:na]
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245) ~[gson-2.8.6.jar:na]
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) ~[gson-2.8.6.jar:na]
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97) ~[gson-2.8.6.jar:na]
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61) ~[gson-2.8.6.jar:na]
....
I'm facing the following problem. Imagine this data model:
As you can see project_function entity is association many to many entity.
Here are my entity classes.
PeronalCard:
#Entity
#Table(name = "personal_card")
#XmlRootElement
public class PersonalCard implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id_person")
private Integer idPerson;
/* SOME OTHER ATTRIBUTES */
#OneToMany(cascade = CascadeType.ALL, mappedBy = "projectFunctionPK.personalCard")
private Set<ProjectFunction> projectFunctionSet;
public PersonalCard() {
}
public Integer getIdPerson() {
return idPerson;
}
public void setIdPerson(Integer idPerson) {
this.idPerson = idPerson;
}
#XmlTransient
public Set<ProjectFunction> getProjectFunctionSet() {
return projectFunctionSet;
}
public void setProjectFunctionSet(Set<ProjectFunction> projectFunctionSet) {
this.projectFunctionSet = projectFunctionSet;
}
#Override
public int hashCode() {
int hash = 0;
hash += (idPerson != null ? idPerson.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof PersonalCard)) {
return false;
}
PersonalCard other = (PersonalCard) object;
if ((this.idPerson == null && other.idPerson != null) || (this.idPerson != null && !this.idPerson.equals(other.idPerson))) {
return false;
}
return true;
}
}
Project:
#Entity
#Table(name = "project")
#XmlRootElement
public class Project implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id_project")
private Integer idProject;
/* OTHER ATTRIBUTES*/
#OneToMany(cascade = CascadeType.ALL, mappedBy = "projectFunctionPK.project")
private Set<ProjectFunction> projectFunctionSet;
public Project() {
}
public Integer getIdProject() {
return idProject;
}
public void setIdProject(Integer idProject) {
this.idProject = idProject;
}
#XmlTransient
public Set<ProjectFunction> getProjectFunctionSet() {
return projectFunctionSet;
}
public void setProjectFunctionSet(Set<ProjectFunction> projectFunctionSet) {
this.projectFunctionSet = projectFunctionSet;
}
#Override
public int hashCode() {
int hash = 0;
hash += (idProject != null ? idProject.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Project)) {
return false;
}
Project other = (Project) object;
if ((this.idProject == null && other.idProject != null) || (this.idProject != null && !this.idProject.equals(other.idProject))) {
return false;
}
return true;
}
}
ProjectFunction:
#Entity
#Table(name = "project_function")
#XmlRootElement
#AssociationOverrides({
#AssociationOverride(name = "projectFunctionPK.project",
joinColumns = #JoinColumn(name = "id_project", referencedColumnName = "id_project")),
#AssociationOverride(name = "projectFunctionPK.personalCard",
joinColumns = #JoinColumn(name = "id_person", referencedColumnName = "id_person")) })
public class ProjectFunction implements Serializable {
private static final long serialVersionUID = 1L;
protected ProjectFunctionPK projectFunctionPK;
private Date fromd;
private Date tod;
public ProjectFunction() {
this.projectFunctionPK = new ProjectFunctionPK();
}
#EmbeddedId
public ProjectFunctionPK getProjectFunctionPK() {
return projectFunctionPK;
}
public void setProjectFunctionPK(ProjectFunctionPK projectFunctionPK) {
this.projectFunctionPK = projectFunctionPK;
}
#Column(name = "fromd")
#Temporal(TemporalType.DATE)
public Date getFromd() {
return fromd;
}
public void setFromd(Date fromd) {
this.fromd = fromd;
}
#Column(name = "tod")
#Temporal(TemporalType.DATE)
public Date getTod() {
return tod;
}
public void setTod(Date tod) {
this.tod = tod;
}
#Transient
public Project getProject() {
return projectFunctionPK.getProject();
}
public void setProject(Project project) {
this.projectFunctionPK.setProject(project);
}
#Transient
public PersonalCard getPersonalCard() {
return this.projectFunctionPK.getPersonalCard();
}
public void setPersonalCard(PersonalCard personalCard) {
//this.personalCard = personalCard;
this.projectFunctionPK.setPersonalCard(personalCard);
}
#Override
public int hashCode() {
int hash = 0;
hash += (projectFunctionPK != null ? projectFunctionPK.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof ProjectFunction)) {
return false;
}
ProjectFunction other = (ProjectFunction) object;
if ((this.projectFunctionPK == null && other.projectFunctionPK != null) || (this.projectFunctionPK != null && !this.projectFunctionPK.equals(other.projectFunctionPK))) {
return false;
}
return true;
}
}
And finally my embedded Primary Key ProjectFunctionPK:
#Embeddable
public class ProjectFunctionPK implements Serializable {
#ManyToOne
private Project project;
#ManyToOne
private PersonalCard personalCard;
public ProjectFunctionPK() {
}
public Project getProject() {
return project;
}
public void setProject(Project project) {
this.project = project;
}
public PersonalCard getPersonalCard() {
return personalCard;
}
public void setPersonalCard(PersonalCard personalCard) {
this.personalCard = personalCard;
}
#Override
public int hashCode() {
int hash = 3;
hash = 41 * hash + Objects.hashCode(this.project);
hash = 41 * hash + Objects.hashCode(this.personalCard);
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final ProjectFunctionPK other = (ProjectFunctionPK) obj;
if (!Objects.equals(this.project, other.project)) {
return false;
}
if (!Objects.equals(this.personalCard, other.personalCard)) {
return false;
}
return true;
}
}
First I save the Project. It works fine. Then i want to connect it using project_function - so I create project_function set them existing project and personal_card and after trying to persist I get following error:
Caused by: org.postgresql.util.PSQLException: ERROR: column projectfun0_.personalcard does not exist
Position: 8
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2198)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1927)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:561)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:419)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:304)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82)
... 119 more
So apparently Hibernate does not know projectfun0_.personalcard . But I dont know why. Do you see any error in the entity classes? Or could the error possibly be somewhere else ?
Thank you very much for all your answers :)
EmbeddedId documentation
Relationship mappings defined within an embedded id class are not supported.
So, ProjectFunctionPK should contain only basic mappings, and entity mappings should be done in the entity itself. Here are some related posts
https://stackoverflow.com/a/9760808/4074715
https://stackoverflow.com/a/4692144/4074715
I am building a spring mvc application with hibernate, and JPA that needs to model a few underlying MYSQL data tables that each have composite keys with the same two data types, so each table has its own composite key class, even though all the composite keys are based on the same two data types with exact same property names. I am getting a hibernate mapping error when I try to compile the app, and I am wondering if this might be because hibernate might not be able to equate the different primary key classes. Can someone show me how to fix this so that my app will compile?
Here is the part of my Description class that establishes the ManyToOne relationship between Description and Concept classes based on their corresponding composite primary key classes:
#ManyToOne
#JoinColumn(name="descriptionPK", referencedColumnName = "conceptPK")
private Concept concept;
Here is the error that I am getting:
Caused by: org.hibernate.MappingException:
Unable to find column with logical name:
conceptPK in org.hibernate.mapping.Table(sct2_concept) and its related supertables and secondary tables
The code for ConceptPK is:
#Embeddable
class ConceptPK implements Serializable {
#Column(name="id", nullable=false)
protected BigInteger id;
#Column(name="effectiveTime", nullable=false)
#Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime effectiveTime;
public ConceptPK() {}
public ConceptPK(BigInteger bint, DateTime dt) {
this.id = bint;
this.effectiveTime = dt;
}
/** getters and setters **/
public DateTime getEffectiveTime(){return effectiveTime;}
public void setEffectiveTime(DateTime ad){effectiveTime=ad;}
public void setId(BigInteger id) {this.id = id;}
public BigInteger getId() {return id;}
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
final ConceptPK other = (ConceptPK) obj;
if (effectiveTime == null) {
if (other.effectiveTime != null) return false;
} else if (!effectiveTime.equals(other.effectiveTime)) return false;
if (id == null) {
if (other.id != null) return false;
} else if (!id.equals(other.id)) return false;
return true;
}
#Override
public int hashCode() {
int hash = 3;
hash = 53 * hash + ((effectiveTime == null) ? 0 : effectiveTime.hashCode());
hash = 53 * hash + ((id == null) ? 0 : id.hashCode());
return hash;
}
}
The code for DescriptionPK is:
#Embeddable
class DescriptionPK implements Serializable {
#Column(name="id", nullable=false)
protected BigInteger id;
#Column(name="effectiveTime", nullable=false)
#Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime effectiveTime;
public DescriptionPK() {}
public DescriptionPK(BigInteger bint, DateTime dt) {
this.id = bint;
this.effectiveTime = dt;
}
/** getters and setters **/
public DateTime getEffectiveTime(){return effectiveTime;}
public void setEffectiveTime(DateTime ad){effectiveTime=ad;}
public void setId(BigInteger id) {this.id = id;}
public BigInteger getId() {return id;}
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
final DescriptionPK other = (DescriptionPK) obj;
if (effectiveTime == null) {
if (other.effectiveTime != null) return false;
} else if (!effectiveTime.equals(other.effectiveTime)) return false;
if (id == null) {
if (other.id != null) return false;
} else if (!id.equals(other.id)) return false;
return true;
}
#Override
public int hashCode() {
int hash = 3;
hash = 53 * hash + ((effectiveTime == null) ? 0 : effectiveTime.hashCode());
hash = 53 * hash + ((id == null) ? 0 : id.hashCode());
return hash;
}
}
You need to change #ManyToOne annotation to use multiple columns as shown below, and also you dont need to create duplicate two embeddable classes ConceptPK and DescriptionPK if all properties are same, just create one EmbeddablePK and use in both entities.
#OneToMany(mappedBy = "concept", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
public List<Description> descriptions = new LinkedList<Description>();
And Description class:
#ManyToOne
#JoinColumns({ #JoinColumn(name = "A_COLUMN", referencedColumnName = "A_COLUMN", insertable = false, updatable = false),
#JoinColumn(name = "B_COLUMN", referencedColumnName = "B_COLUMN", insertable = false, updatable = false),
})
public Concept concept;
When check instance is equal with other instance, I get
java.lang.StackOverflowError.
Because of there are bidirectional relationship, That's why, my Override equal method call equal() function each other recursively.
Should I remove one check equal condition in override equal method of one side?
What will be better way? Some PG suggest to me to use EqualsBuilder of Apache.
OrderItem.java
public class OrderItem {
private String id;
private Order order;
public OrderItem(String id, Order order) {
this.id = id;
this.order = order;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setOrder(Order order) {
this.order = order;
}
public Order getOrder() {
return order;
}
#Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (!(object instanceof OrderItem)) {
return false;
}
final OrderItem other = (OrderItem)object;
if (!(id == null ? other.id == null : id.equals(other.id))) {
return false;
}
if (!(order == null ? other.order == null : order.equals(other.order))) {
return false;
}
return true;
}
}
Order.java
public class Order {
private String id;
private List<OrderItem> orderItemList;
public Order(String id) {
this.id = id;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setOrderItemList(List<OrderItem> orderItemList) {
this.orderItemList = orderItemList;
}
public List<OrderItem> getOrderItemList() {
return orderItemList;
}
#Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (!(object instanceof Order)) {
return false;
}
final Order other = (Order)object;
if (!(id == null ? other.id == null : id.equals(other.id))) {
return false;
}
if (!(orderItemList == null ? other.orderItemList == null : orderItemList.equals(other.orderItemList))) {
return false;
}
return true;
}
}
Test
public static void main(String[] args) {
Order order1 = new Order("1");
List<OrderItem> orderItemList = new ArrayList<OrderItem>();
orderItemList.add(new OrderItem("1", order1));
orderItemList.add(new OrderItem("2", order1));
order1.setOrderItemList(orderItemList);
Order order2 = new Order("1");
List<OrderItem> orderItemList2 = new ArrayList<OrderItem>();
orderItemList2.add(new OrderItem("1", order2));
orderItemList2.add(new OrderItem("2", order2));
order2.setOrderItemList(orderItemList2);
if(order1.equals(order2)) {
System.out.println("Equal");
} else {
System.out.println("Not Equal");
}
}
I would rewrite it to use only idattribute for equality check. But this is important: don't forget to override also the hashcode() method if you want your entities behave correctly in Java collections.
I just wanna ask know how its possible to create object after creating your database with Hibernate annotations?
When i run the code below, it creates the database with the objects, but when i run the second time it just creates exactly the same, and none new objects are added? How come? How do i create objects using annotations with the method .save, after creating the database with annotations? Or is it not possible to do so with annotations?
Thanks in advance.
public static void main(String[] args) {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
Adress adress = new Adress("Streetname", "postcode");
Person person1 = new Person("Peter Hanks", adress);
Person person2 = new Person("Sophie Hanks", adress);
session.save(person1);
session.save(person2);
transaction.commit();
} catch (HibernateException e) {
transaction.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
Heres the code person.class
#Entity
#Table(name="person")
public class Person implements Serializable {
private long id;
private String navn;
private Adresse adresse;
public Person() {
}
public Person(String navn, Adresse adresse) {
this.navn = navn;
this.adresse = adresse;
}
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name= "adresse_id", nullable = false)
public Adresse getAdresse() {
return adresse;
}
public void setAdresse(Adresse adresse) {
this.adresse = adresse;
}
#Id
#GeneratedValue
#Column(name= "id")
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Column(name = "navn", nullable= false, length= 100)
public String getNavn() {
return navn;
}
public void setNavn(String navn) {
this.navn = navn;
}
#Override
public int hashCode() {
int hash = 3;
hash = 29 * hash + (this.navn != null ? this.navn.hashCode() : 0);
hash = 29 * hash + (this.adresse != null ? this.adresse.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Person other = (Person) obj;
if ((this.navn == null) ? (other.navn != null) : !this.navn.equals(other.navn)) {
return false;
}
if (this.adresse != other.adresse && (this.adresse == null || !this.adresse.equals(other.adresse))) {
return false;
}
return true;
}
You might need to show us how you've written and annotated your Person and Adress (sic) objects.
If you've written "correct" equals() and hashcode() implementations (i.e. that don't look at the #Id of the object) then your save() calls will do nothing the second time around because the objects you've asked to save already exist in the database.
just changed the settings for hibernate.hbm2ddl.auto from create to create-update, and now theres no problem...