Here is another case of this ERROR:
21:22:15,881 ERROR [SessionFactoryImpl] Error in named query: ch.software.gvs.TroubleNotification_DeviceType.byType org.hibernate.QueryException:
could not resolve property: type of: ch.ildsoftware.gvs.TroubleNotification_DeviceType
[select d.id from ch.ildsoftware.gvs.TroubleNotification_DeviceType d where d.type = :type]
I have following setting:
queries.xml:
<named-query name="ch.ildsoftware.gvs.TroubleNotification_DeviceType.byType">
<query>
select t.id from TroubleNotification_DeviceType t where t.type = :type
</query>
</named-query>
TroubleNotification_DeviceType.java
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "tblgwTroubleNotification_ADSTyp")
public class TroubleNotification_DeviceType implements Serializable {
private static final long serialVersionUID = 1L;
private TroubleNotification id;
private DeviceType type;
private String createdBy;
private String createdDate;
public TroubleNotification_DeviceType()
{}
public TroubleNotification_DeviceType(TroubleNotification id, DeviceType type) {
this.id = id;
this.type = type;
}
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "IDgwTroubleNotification", nullable = false)
public TroubleNotification getId() {
return id;
}
public void setId(TroubleNotification id) {
this.id = id;
}
#Id
#Column(name = "ADSTypID", nullable = false)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "GeraeteTypID", nullable = false)
public DeviceType getType() {
return type;
}
public void setType(DeviceType type) {
this.type = type;
}
#Column(name = "Created", nullable = false)
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
#Column(name = "CreatedDate", nullable = false)
public String getCreatedDate() {
return createdDate;
}
public void setCreatedDate(String createdDate) {
this.createdDate = createdDate;
}
}
I suspect there might be something wrong with the #Column and #JoinColumn annotation. It's just that the column-name I join with, is from a view which aliases the column name.
But maybe something else is wrong. I'm rather new to this.
snippet out of DeviceType:
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
....
#Id
#Column(name = "GeraeteTypID", nullable = false)
public Integer getId()
{
return this.id;
}
In other classes the reference would be like this, and work well (yet the column name is identical):
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "GeraeteTypID", nullable = false)
public DeviceType getType()
{
return this.type;
}
snippet out of an EJB:
#Override
#SuppressWarnings("unchecked")
public List<TroubleNotification> getTroubleNotificationByDeviceType(DeviceType aType)
{
// first get all IDgwTroubleNotification for ADSTypID
Query idSet = gvsData.createNamedQuery(
TroubleNotification_DeviceType.class.getName() + ".byType");
idSet.setParameter("type", aType);
List<TroubleNotification> idSetResult = idSet.getResultList();
final List<TroubleNotification> troubleNotificationResult = new ArrayList<TroubleNotification>();
for (int i = 0; i < idSetResult.size(); i++) {
// get all Notification for IDgwTroubleNotification
Query notificationById = gvsData.createNamedQuery(
TroubleNotification.class.getName() + ".byId");
notificationById.setParameter("id", idSetResult.get(i));
troubleNotificationResult.add((TroubleNotification) notificationById.getResultList());
}
return troubleNotificationResult;
}
Thank you for your help!
I discovered that my DB mapping was not at all proper. I have an n:m relation, which doesn't seem like an easy one with hibernate. But this was very helpful:
Hibernate Many-To-Many Revisited
But that was still not solving the problem. And I discovered that I have composite primary keys, that the primary keys of two tables are mapped in the n:m table. Another not so easy setting. So I followed this thread: Mapping ManyToMany with composite Primary key and Annotation:
The configuration from the second link, together with an SQL statement according to the second strategy in the first link works.
Related
I am trying to understand hibernate a bit better after spending already quite some time on a One to many relationship I want to establish.
So currently my application works, i.e. I can add children (DocTemplateArguments) to the parent (DocumentTemplate). What bothers me is that hibernate is not updating the child records when I set them through the parent, it actually inserts and deletes them every time again I execute a merge.
As you can see, I have already updated the equals and hashcode by only keeping the relevant fields for the business logic. So, as long as the name of the child is not updated in the set that is being used for the initialisation of parent, I want hibernate to execute an update statement instead of an insert/delete combo.
Please find some code snippets below:
Parent
import javax.persistence.*;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
#Entity
#Table(name = "document_template")
#Data
#EqualsAndHashCode(exclude="docTemplateArguments")
public class DocumentTemplate {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "name", nullable = false, length = 30)
private String name;
#Column(name = "description", nullable = true, length = 100)
private String description;
#Enumerated(EnumType.STRING)
#Column(name = "type", nullable = false, length = 15)
private DocumentType type;
#Enumerated(EnumType.STRING)
#Column(name = "format", nullable = false, length = 15)
private DocumentFormat format;
#Column(name = "content", nullable = false, length = 50000)
private String content;
#Setter(AccessLevel.NONE)
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "documentTemplate", orphanRemoval = true)
private Set<DocTemplateArgument> docTemplateArguments = new HashSet<DocTemplateArgument>();
public void setDocTemplateArguments (Set<DocTemplateArgument> dtas){
this.docTemplateArguments.addAll(dtas);
}
}
Child
import lombok.*;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import javax.persistence.*;
#Entity
#Table(name = "doc_template_argument")
#Data
#EqualsAndHashCode(exclude={"DocumentTemplate","id","dialogText"})
public class DocTemplateArgument {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column (name="name", nullable = false, length=30)
private String name;
#Column (name="dialog_text", length = 100)
private String dialogText;
#Transient
private String argument;
#ManyToOne(fetch = FetchType.EAGER)
#OnDelete(action = OnDeleteAction.CASCADE)
#JoinColumn(name="doctemplate_id", nullable=false)
private DocumentTemplate documentTemplate;
}
From my current understanding I think I need to intervene in the merge method of the DAO class of the parent in order to get this done. This currently looks as follows:
#Repository
public class DocumentTemplateDAOImpl implements DocumentTemplateDAO {
private final SessionFactory sessionFactory;
public DocumentTemplateDAOImpl(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
#Override
#Transactional
public List<DocumentTemplate> getAll() {
List<DocumentTemplate> documentTemplates = getCurrentSession().createQuery("from DocumentTemplate").list();
return documentTemplates;
}
#Override
#Transactional
public DocumentTemplate get(int id) {
return getCurrentSession().get(DocumentTemplate.class, id);
}
#Override
#Transactional
public void create(DocumentTemplate documentTemplate) {
getCurrentSession().persist(documentTemplate);
}
#Override
#Transactional
public void update(DocumentTemplate documentTemplate) {
getCurrentSession().merge(documentTemplate);
}
#Override
#Transactional
public void delete(int id) {
DocumentTemplate documentTemplate = get(id);
getCurrentSession().delete(documentTemplate);
}
private Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
}
I have no idea on how to do this though, any help would be greatly appreciated.
For completeness, the whole structure is being called in a convertToEntity method of a DTO:
public static DocumentTemplate convertToEntity(DocumentTemplateDTO documentTemplateDTO) {
DocumentTemplate documentTemplate = new DocumentTemplate();
documentTemplate.setId(documentTemplateDTO.getId());
documentTemplate.setName(documentTemplateDTO.getName());
documentTemplate.setDescription(documentTemplateDTO.getDescription());
documentTemplate.setType(documentTemplateDTO.getType());
documentTemplate.setFormat(documentTemplateDTO.getFormat());
documentTemplate.setContent(documentTemplateDTO.getContent());
documentTemplateDTO.getDocTemplateArguments().stream().forEach(dta -> dta.setDocumentTemplate(documentTemplate));
documentTemplate.setDocTemplateArguments(documentTemplateDTO.getDocTemplateArguments());
return documentTemplate;
}
EDIT
I found out why this happened. In my request I was omitting the id of the argument. I presume that when the json is deserialised it defaults a non specified property of type integer into 0, which then as such ended up in the entity.
When I put this to the latest id for the record to be updated, it properly issues an update statement. Still, I find this a bit counterintuitive when the id is explicitly excluded from the equals and hash check with:
#EqualsAndHashCode(exclude={"DocumentTemplate","id","dialogText"})
If would be great if someone can explain this!
I have something similar to this:
#Entity
#Table(name = "claim", schema = "test")
public class Claim implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "idClaim", unique = true, nullable = false)
private Integer idClaim;
#OneToOne(mappedBy = "claim", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JsonManagedReference
private ClaimReturnInfo claimReturnInfo;
#Column(name = "notes")
private String notes;
// Getters and setters
}
#Entity
#Table(name = "claim_returninfo", schema = "test")
public class ClaimReturnInfo implements Serializable {
#Id
#Column(name = "Claim_idClaim")
private Integer id;
#MapsId("Claim_idClaim")
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "Claim_idClaim")
#JsonBackReference
private Claim claim;
#Column(name = "description")
private String description;
// Getters and setters
}
ClaimReturnInfo Id is not autogenerated because we want to propagate the Id from its parent (Claim). We are not able to do this automatically and we are getting this error: ids for this class must be manually assigned before calling save() when 'cascade' is executed in ClaimReturnInfo .
Is it possible to map Claim Id into ClaimReturnInfo Id or should we do this manually?
Even if we set this ID manually on claimReturnInfo and we can perform updates, we still get this error when trying to create a new Claim:
// POST -> claimRepository.save() -> Error
{
"notes": "Some test notes on a new claim",
"claimReturnInfo": {
"description": "Test description for a new claimReturnInfo"
}
}
In the ServiceImplemetation:
#Override
#Transactional
public Claim save(Claim claim) throws Exception {
if(null != claim.getClaimReturnInfo()) {
claim.getClaimReturnInfo().setId(claim.getIdClaim());
}
Claim claimSaved = claimRepository.save(claim);
return claimSaved;
}
I have tried using the following mappings and from your comments it was apparent that Json object is populated correctly.
I have noticed that the annotation #MapsId is the culprit.If you check the documentation of #MapsId annotation it says
Blockquote
The name of the attribute within the composite key
* to which the relationship attribute corresponds. If not
* supplied, the relationship maps the entity's primary
* key
Blockquote
If you change #MapsId("Claim_idClaim") to #MapsId it will start persisting your entities.
import javax.persistence.*;
#Entity
#Table(name = "CLAIM")
public class Claim {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "idClaim", unique = true, nullable = false)
private Long idClaim;
#Column(name = "notes")
private String notes;
#OneToOne(mappedBy = "claim", cascade = CascadeType.ALL, optional = false)
private ClaimReturnInfo claimReturnInfo;
public Long getIdClaim() {
return idClaim;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public ClaimReturnInfo getClaimReturnInfo() {
return claimReturnInfo;
}
public void setClaimReturnInfo(ClaimReturnInfo claimReturnInfo) {
if (claimReturnInfo == null) {
if (this.claimReturnInfo != null) {
this.claimReturnInfo.setClaim(null);
}
} else {
claimReturnInfo.setClaim(this);
}
this.claimReturnInfo = claimReturnInfo;
}
}
package com.hiber.hiberelations;
import javax.persistence.*;
#Entity
#Table(name = "CLAIM_RETURN_INFO")
public class ClaimReturnInfo {
#Id
#Column(name = "Claim_idClaim")
private Long childId;
#Column(name = "DESCRIPTION")
private String description;
#MapsId
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "Claim_idClaim")
private Claim claim;
public Long getChildId() {
return childId;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Claim getClaim() {
return this.claim;
}
public void setClaim(Claim claim) {
this.claim = claim;
}
}
I am using Hibernate to fetch the JSON object from DB. I want that JSON object should contain all the details of the only top two of most recently created VGIs. But I don't know how to limit the result set and then sort on the basis of created date when no HQL query is used. It is fetching all the details from MySQL db.
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name = "vgi", catalog = "coworkee5")
public class VGI {
#ManyToOne
#JoinColumn(name = "employee_id", referencedColumnName = "id", insertable = false, updatable = false)
private Employees employees;
public Employees getEmployees() {
return employees;
}
public void setEmployees(Employees employees) {
this.employees = employees;
}
#OneToMany(cascade = CascadeType.ALL, targetEntity = VgiGoals.class, mappedBy = "vgi")
private List<VgiGoals> vgiGoals;
public List<VgiGoals> getVgiGoals() {
return vgiGoals;
}
public void setVgi_goals(List<VgiGoals> vgiGoals) {
this.vgiGoals = vgiGoals;
}
public VGI() {
}
#Id
#Column(name = "id")
private String id;
#Column(name = "title")
private String vgi;
#Column(name = "employee_id")
private String employee_id;
#Column(name = "created_on")
private String created;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getvgi() {
return vgi;
}
public void setvgi(String vgi) {
this.vgi = vgi;
}
public String getEmployee_id() {
return employee_id;
}
public void setEmployee_id(String employee_id) {
this.employee_id = employee_id;
}
public String getCreated() {
return created;
}
public void setCreated(String created) {
this.created = created;
}
}
Add #OrderBy annotation to sort like below.
#OneToMany(cascade = CascadeType.ALL, targetEntity = VgiGoals.class, mappedBy = "vgi")
#OrderBy("createdOn DESC")
private List<VgiGoals> vgiGoals;
NOTE : replace createdOn with your date field in VgiGoals class.
And for limit use below method in the query.
query.setFirstResult(1).setMaxResults(10);
Reading all the documentation, using #Fetch(FetchMode.JOIN) on a #ManyToOne should by default I believe generate a left outer join, but for me it is always generating an inner join. These are my beans:
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
/**
* PensionMember entity. #author MyEclipse Persistence Tools
*/
#Entity
#Table(name = "Z_PENSION_MEMBERS", schema = "DANAOS")
public class PensionMember implements java.io.Serializable {
private static final long serialVersionUID = -4541446336298304689L;
// Fields
private Long id;
private Long personsCode;
private String employeeCode;
private String personType;
private CrewOfficeEmployee employee;
private PersonTO person;
// Property accessors
#Id
#Column(name = "ID", unique = true, nullable = false, precision = 0)
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "EMPLOYEE_CODE", length = 12)
public String getEmployeeCode() {
return this.employeeCode;
}
public void setEmployeeCode(String employeeCode) {
this.employeeCode = employeeCode;
}
#ManyToOne( cascade = CascadeType.REFRESH, optional=true )
#JoinColumn( name = "EMPLOYEE_CODE", insertable = false, updatable = false )
#Fetch(FetchMode.JOIN)
public CrewOfficeEmployee getEmployee(){
return employee;
}
public void setEmployee( CrewOfficeEmployee employee ){
this.employee = employee;
}
#Column(name = "PERSONS_CODE", precision = 126, scale = 0, insertable = false, updatable = false)
public Long getPersonsCode() {
return this.personsCode;
}
public void setPersonsCode(Long personsCode) {
this.personsCode = personsCode;
}
#ManyToOne( cascade = CascadeType.REFRESH, optional=true )
#JoinColumn( name = "PERSONS_CODE" )
#Fetch(FetchMode.JOIN)
public PersonTO getPerson() {
return person;
}
public void setPerson(PersonTO person) {
this.person = person;
}
#Column(name = "PERSON_TYPE", nullable = false, length = 1)
public String getPersonType() {
return this.personType;
}
public void setPersonType(String personType) {
this.personType = personType;
}
}
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
/**
* CrewOfficeEmployee entity. #author MyEclipse Persistence Tools
*/
#Entity
#Table(name = "Z_CREW_OFFICE_EMPLOYEES", schema = "DANAOS")
public class CrewOfficeEmployee implements java.io.Serializable {
private static final long serialVersionUID = -5900130959401376537L;
// Fields
private String id;
private Integer crewOfficeJobTitleId;
private String name;
private String surname;
private Date dateOfBirth;
private Date effectiveJoiningDate;
private Date joiningDate;
private Date leavingDate;
// Property accessors
#Id
#Column(name = "ID", unique = true, nullable = false, length = 12)
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
#Column(name = "JOB_TITLE_ID", nullable = false)
public Integer getCrewOfficeJobTitleId() {
return crewOfficeJobTitleId;
}
public void setCrewOfficeJobTitleId(Integer crewOfficeJobTitleId) {
this.crewOfficeJobTitleId = crewOfficeJobTitleId;
}
#Column(name = "NAME", nullable = false, length = 30)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#Column(name = "SURNAME", nullable = false, length = 30)
public String getSurname() {
return this.surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
#Column(name = "DATE_OF_BIRTH", nullable = false, length = 7)
public Date getDateOfBirth() {
return this.dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
#Column(name = "EFFECTIVE_JOINING_DATE", nullable = false, length = 7)
public Date getEffectiveJoiningDate() {
return this.effectiveJoiningDate;
}
public void setEffectiveJoiningDate(Date effectiveJoiningDate) {
this.effectiveJoiningDate = effectiveJoiningDate;
}
#Column(name = "JOINING_DATE", nullable = false, length = 7)
public Date getJoiningDate() {
return this.joiningDate;
}
public void setJoiningDate(Date joiningDate) {
this.joiningDate = joiningDate;
}
#Column(name = "LEAVING_DATE", length = 7)
public Date getLeavingDate() {
return this.leavingDate;
}
public void setLeavingDate(Date leavingDate) {
this.leavingDate = leavingDate;
}
}
This is my query:
Criteria crit = getSession().createCriteria(PensionMember.class);
crit.createAlias("employee", "employee");
crit.createAlias("person", "person");
crit.add(
Restrictions.or(
Restrictions.and(
Restrictions.eq( PERSON_TYPE, "V" ),
Restrictions.like( "person.personsSurname", surname, MatchMode.START ).ignoreCase()
),
Restrictions.and(
Restrictions.eq( PERSON_TYPE, "O" ),
Restrictions.like( "employee.surname", surname, MatchMode.START ).ignoreCase()
)
)
);
... and this is the resulting SQL:
select * from ( select this_.ID as ID23020_6_, this_.EMPLOYEE_CODE as EMPLOYEE3_23020_6_, this_.PERSONS_CODE as PERSONS7_23020_6_,
this_.PERSON_TYPE as PERSON6_23020_6_, employee1_.ID as ID23010_0_, employee1_.JOB_TITLE_ID as JOB2_23010_0_,
employee1_.DATE_OF_BIRTH as DATE3_23010_0_, employee1_.EFFECTIVE_JOINING_DATE as EFFECTIVE4_23010_0_,
employee1_.JOINING_DATE as JOINING5_23010_0_, employee1_.LEAVING_DATE as LEAVING6_23010_0_,
employee1_.NAME as NAME23010_0_, employee1_.SURNAME as SURNAME23010_0_, person2_.STATUS_CODE as STATUS2_22758_1_, etc
from DANAOS.Z_PENSION_MEMBERS this_
inner join DANAOS.Z_CREW_OFFICE_EMPLOYEES employee1_ on this_.EMPLOYEE_CODE=employee1_.ID
inner join PERSONS person2_ on this_.PERSONS_CODE=person2_.PERSONS_CODE
where ((this_.PERSON_TYPE=? and lower(person2_.PERSONS_SURNAME) like ?) or
(this_.PERSON_TYPE=? and lower(employee1_.SURNAME) like ?)) ) where rownum <= ?
How come?! Can someone tell me what I'm doing wrong?
Thanks,
Neil
I'm using Hibernate 3.6.10 btw
Having realised it was the criteria query that was the problem, the solution was to change the createAlias() methods:
Criteria crit = getSession().createCriteria(PensionMember.class);
crit.createAlias("employee", "employee", CriteriaSpecification.LEFT_JOIN);
crit.createAlias("person", "person", CriteriaSpecification.LEFT_JOIN);
#ManyToOne( cascade = CascadeType.REFRESH, optional=true )
#JoinColumn( name = "EMPLOYEE_CODE", insertable = false, updatable = false )
#Fetch(FetchMode.JOIN)
public CrewOfficeEmployee getEmployee(){
return employee;
}
first of all change "insertable = false" to true.
I am getting(left outer join) :
Hibernate:
select this_.ID as ID1_1_1_, this_.EMPLOYEE_CODE1 as EMPLOYEE3_1_1_,
this_.EMPLOYEE_CODE as EMPLOYEE2_1_1_, crewoffice2_.ID as ID1_0_0_,
crewoffice2_.JOB_TITLE_ID as JOB_TITL2_0_0_,
crewoffice2_.DATE_OF_BIRTH as DATE_OF_3_0_0_,
crewoffice2_.EFFECTIVE_JOINING_DATE as EFFECTIV4_0_0_,
crewoffice2_.JOINING_DATE as JOINING_5_0_0_, crewoffice2_.LEAVING_DATE
as LEAVING_6_0_0_, crewoffice2_.NAME as NAME7_0_0_,
crewoffice2_.SURNAME as SURNAME8_0_0_ from Z_PENSION_MEMBERS this_
left outer join Z_CREW_OFFICE_EMPLOYEES crewoffice2_ on
this_.EMPLOYEE_CODE1=crewoffice2_.ID order by this_.ID asc
I think your code should work.
Hi I am new to this world.
I am making my own application with spring jpa hibernate.
I have an entity class. It works generally but it duplicates attributes.
My code look like this:
import java.util.Date;
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.validation.constraints.NotNull;
#Entity
public class Event {
#Id
#GeneratedValue
private Integer id;
public Integer getId() {
return id;
}
#Column(nullable = false)
public void setId(Integer id) {
this.id = id;
}
/*------------------------------ title ------------------------*/
private String title;
#Column(nullable = false)
public String getTitle() {
return title;
}
#Column(nullable = false)
public void setTitle(String title) {
this.title = title;
}
/* [Note] I have two extra ids : event_id, eventId
- so these are not the case of the duplication. */
/*------------------- event_id -----------------------------*/
private String event_id;
public String getEvent_id() {
return event_id;
}
public void setEvent_id(String event_id) {
this.event_id = event_id;
}
/*-------------- eventId -------------------------------------*/
#Column(unique = true)
private String eventId;
public String getEventId() {
return eventId;
}
public void setEventId(String eventId) {
this.eventId = eventId;
}
/*------------------------------ publishedDate ------------------------------------------*/
private String publishedDate;
public String getPublishedDate() {
return publishedDate;
}
#Column(nullable = false)
public void setPublishedDate(String publishedDate) {
this.publishedDate = publishedDate;
}
/*--------------------------------- endTime -----------------------------------*/
private String endTime;
public String getEndTime() {
return endTime;
}
#Column(nullable = false)
public void setEndTime(String endTime) {
this.endTime = endTime;
}
/*-------------------------------- user ------------------------------------------*/
#ManyToOne
#JoinColumn(name="user_id")
private User user;
public User getUser() {
return user;
}
#Column(nullable = false)
public void setUser(User user) {
this.user = user;
}
Then when I check JPA diagram, it has duplication of several attributes.
I added my JPA diagram image(the red parts are duplicated)
This is my very first application with java programming.
so please understand, even I read documentation of the spring jpa,
It is difficult to figure out what exactly I did wrong in the code.
Any ideas? Thanks in advance.
The problem is that JPA expects either field level annotations or accessor (getters/setters) annotations. However you are using both, which basically isn't allowed. Remove all he annotations from the accessors and only put them on the fields.
Small hint on Java programming (styling) put your fields on top of the classes instead of between the accessors.
#Entity
public class Event {
#Id
#GeneratedValue
private Integer id;
#Column(unique = true)
private String eventId;
private String event_id;
#Column(nullable = false)
private String title;
#Column(nullable = false)
private String publishedDate;
#Column(nullable = false)
private String endTime;
#ManyToOne
#JoinColumn(name="user_id")
#Column(nullable = false)
private User user;
// Getters / Setters omitted
}
Remove the annotations from the accessors, also do you really want to set the id? I would expect not, so you might want to remove the setId method.
As mentioned in comments, your problem is that you are using two annotations for the same attribute, first in the field and then in its getter/setter, so you have to use only one of them, for example:
#Id
#GeneratedValue
private Integer id;
public Integer getId() {
return id;
}
#Column(nullable = false)
public void setId(Integer id) {
this.id = id;
}
Should be:
#Id
#GeneratedValue
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
And it's wrong to usnnotations here with both getter and setter:
#Column(nullable = false)
public String getTitle() {
return title;
}
#Column(nullable = false)
public void setTitle(String title) {
this.title = title;
}
Note:
So in order to avoid this, you have to choose between:
Using annotations with the field.
And using them with its setter.
Spring Boot 2.0.0.M5, JPA, Hibernate 5.2.11.Final
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "auto_gen")
#SequenceGenerator(name = "auto_gen", sequenceName = "customer_id_seq", allocationSize=1)
#Column(name = "id")
private Long id;
This is a working sample:
package hello;
import org.hibernate.annotations.Type;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
#Entity
#Table(name = "customer")
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "auto_gen")
#SequenceGenerator(name = "auto_gen", sequenceName = "customer_id_seq", allocationSize = 1)
#Column(name = "id")
private Long id;
#Column(name = "first_name")
//#Type(type="org.hibernate.type.StringType")
private String firstName;
#Column(name = "last_name")
//#Type(type="org.hibernate.type.StringType")
private String lastName;
protected Customer() {
}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
#Override
public String toString() {
return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName);
}
}