#OneToMany With It's Self Class - java

All I need help i create this simple class where Category have list of Categories. When i try to save the list of sub categories with the Parent category it's show below error.
Json:-
{
"name": "n11111111",
"detail": "detail",
"status" : "AVAILABLE",
"subCategories": [3, 12, 100, 7, 11] // id of sub-cat
}
Class:-
#Entity
#Table(name = "category")
public class Category{
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
#Column(nullable = false, updatable = false, name = "category_id")
private Long id;
#Column(name = "name", nullable=false)
private String name;
#Column(name = "detail", nullable=false)
private String detail;
#Column(nullable = false, name = "status")
#Enumerated(EnumType.ORDINAL)
private Status status;
#OneToMany( targetEntity=Category.class, cascade=CascadeType.ALL)
private List<Category> subCategories;
}
ERROR:- "message": "could not execute statement; SQL [n/a]; constraint [UK_76grwe00i7mrj7awuvhc3kx0n]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement",
MYSQL ERROR:- #1062 - Duplicate entry
Code:- Convert from Vo to POJO
private Categorie getCatToPojo(CategorieVo categorieVo, String type) {
double startTime = System.nanoTime();
logger.info("Start Vo To Pojo Categorie");
// #:- case:-1 when no sub-cat there it save only below 3 attribute
this.categorie = new Categorie();
this.saveNameCat(categorieVo, type);
this.categorie.setDetail(categorieVo.getDetail());
this.categorie.setStatus(categorieVo.getStatus());
// #:- case:-2 when have list of sub-cat then will exe then next process
if((CollectionUtils.isNotEmpty(categorieVo.getSubCategories()) && categorieVo.getSubCategories().size() > 0) && type.equalsIgnoreCase("P")) {
logger.debug("Sub-Process....SubCategories...init");
// #:- S-Cat will be get and
List<Categorie> subCategories = this.businessServer.findAllById(categorieVo.getSubCategories())
.stream().filter(categorie1 -> categorie1.getName().startsWith("S-") == true ).collect(Collectors.toList());
// #:- if any wrong id pass it will not give you the list
if(CollectionUtils.isNotEmpty(subCategories) && subCategories.size() > 0) {
this.categorie.setSubCategories(subCategories);
}
logger.debug("Sub-Process....SubCategories...End " + categorieVo.getSubCategories().toString());
}
logger.debug(SecurityUtil.getPerfLog("Process Time For Convert the Vo to POJO", this.categorie.toString(), startTime));
logger.info("End Vo To Pojo Categorie");
return categorie;
}
private void saveNameCat(CategorieVo categorieVo, String type) {
switch (type) {
case "P":
// #:- P,S will join with name
this.categorie.setName(type + "-" + categorieVo.getName());
break;
case "S":
// #:- P,S will join with name
this.categorie.setName(type + "-" + categorieVo.getName());
break;
default:
logger.info("End Vo To Pojo Categorie With Exception");
// #:- will throw error bad request of type
throw new BadTypeException(" [ " + "Bad Request Type" + " ]--[ " + type + " ]");
}
}

Once I have to do exact same thing. Here is the working code for same purpose :
#Entity
#Data
#NoArgsConstructor
#Table(name = "categories")
public class Category {
#JsonProperty("Id")
#Id
private int id;
#JsonProperty("Code")
private String code;
#JsonProperty("Name")
private String name;
#JsonProperty("ParentId")
#Column(name = "parent_id")
private Integer parent;
#JsonProperty("NewAdminId")
private int newAdminId;
#JsonProperty("VolumetricWeight")
#Column(name = "volumetricWeight")
private Float volumetricWeight = 0.0f;
#JsonProperty("Nodes")
#OneToMany(
cascade = CascadeType.ALL,
fetch = FetchType.EAGER,
orphanRemoval = true)
#JoinColumn(name = "parent_id")
private List<Category> categories;
public Category(int id, String code, String name, int newAdminId, List<Category> categories) {
this.id = id;
this.code = code;
this.name = name;
this.newAdminId = newAdminId;
this.categories = categories;
}
}

insert into `db`.`category` values (1, 'a');
insert into `db`.`category` values (2, 'b');
insert into `db`.`category` values (3, 'c');
commit;
insert into `db`.`subcategory` values (1, 2);
insert into `db`.`subcategory` values (1, 3);
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
#Entity
#Table(name = "category")
public class Category {
#SuppressWarnings("unused")
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id")
private int id;
#Column(name="name")
private String name;
#ManyToMany(fetch=FetchType.EAGER)
#Cascade({CascadeType.ALL})
#JoinTable(name="subcategory",
joinColumns={#JoinColumn(name="idcategory")},
inverseJoinColumns={#JoinColumn(name="idsubcategory")})
private Set<Category> catlist;
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 Set<Category> getCatlist() {
return catlist;
}
public void setCatlist(Set<Category> catlist) {
this.catlist = catlist;
}
}

Related

ModelMapper issues converting DTO Objects to Entity

I have a simple spring-boot app where Product needs to be stored and conversion between DTO and Entity needs to happen. I am using the ModelMapper dependency. User can attach a ProductCategory to the Product or leave it empty. Similarly Product can have multiple ReplaceNumber or empty. If I dont attach category it gives error. If I attach category it saves the product with the attached category. If I leave the replaceNumbers array empty it saves. If I fill it it gives errors. Errors are described below.
ProductCategory
#Entity
#Table(name = "product_categories")
public class ProductCategory
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotBlank
#Column(name = "name", nullable = false)
#Size(max = 20)
private String name;
public ProductCategory()
{
}
public ProductCategory(String name)
{
this.name = name;
}
}
ReplaceNumber
#Entity
#Table(name = "replace_numbers")
public class ReplaceNumber
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotBlank
#Size(max = 20)
private String partNumber;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "product_id", nullable = false)
private Product product;
public ReplaceNumber()
{
}
public ReplaceNumber(String partNumber)
{
this.partNumber = partNumber;
}
}
Product
#Entity
#Table(name = "products", indexes = {#Index(name= "part_number_index", columnList = "part_number", unique = true)})
public class Product
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotBlank
#Column(name = "part_number", nullable = false)
#Size(max = 20)
private String partNumber;
#NotBlank
#Size(max = 255)
private String description;
#OneToMany(
mappedBy = "product",
cascade = CascadeType.ALL,
fetch = FetchType.EAGER,
orphanRemoval = true
)
#Fetch(FetchMode.SELECT)
private List<ReplaceNumber> replaceNumbers = new ArrayList<>();
#ManyToOne
#JoinColumn(name = "product_category_id", referencedColumnName = "id")
private ProductCategory category;
}
Following are the DTO Classes that need to be converted.
ReplaceNumberRequest
public class ReplaceNumberRequest
{
#NotBlank
#Size(max = 20)
private String partNumber;
public String getPartNumber()
{
return partNumber;
}
public void setPartNumber(String partNumber)
{
this.partNumber = partNumber;
}
}
ProductCategoryResponse
public class ProductCategoryResponse
{
private Long id;
private String name;
public ProductCategoryResponse()
{
}
public ProductCategoryResponse(String name)
{
this.name = name;
}
}
ProductRequest
public class ProductRequest
{
#NotBlank
#Size(max = 20)
private String partNumber;
#NotBlank
#Size(max = 255)
private String description;
private List<ReplaceNumberRequest> replaceNumbers = new ArrayList<>();
private ProductCategoryResponse category;
}
ProductService
#Service
public class ProductService
{
#Autowired
ProductRepository productRepository;
public Product create(ProductRequest productRequest)
{
Product product = new Product();
org.modelmapper.ModelMapper modelMapper = new org.modelmapper.ModelMapper();
modelMapper.map(productRequest, product);
return productRepository.save(product);
}
}
If I post the following JSON from Postman
{
"partNumber": "443455783",
"description": "443434",
"replaceNumbers": [],
"category": ""
}
It goes for saving the empty category and produces the following error.
org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : org.walana.GP.model.Product.category -> org.walana.GP.model.ProductCategory; nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : org.walana.GP.model.Product.category -> org.walana.GP.model.ProductCategory
If I post the following JSON from Postman
{
"partNumber": "443455783",
"description": "443434",
"replaceNumbers": [
{
"partNumber": "123455"
},
{
"partNumber": "343435"
}
],
"category": {
"id": 1,
"name": "Mounting"
}
}
It gives following error.
could not execute statement; SQL [n/a]; constraint [part_number_index]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

"Could not write JSON: failed to lazily initialize a collection of role" with springboot and hibernate search

I'm trying to have a Many-to-Many relation between two entities:
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.perso.ez.debate.tag.TagEntity;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.List;
#Entity
#Indexed
#Table(name = "data")
public class DataLightEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Field
#Column(name = "title")
private String title;
#Field
#Column(name = "subtitle")
private String subtitle;
#Field
#Column(name = "text", columnDefinition = "TEXT")
private String text;
#IndexedEmbedded
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "data_tags", joinColumns = #JoinColumn(name = "data_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "tag_id", referencedColumnName = "id"))
private List<TagEntity> tags;
#Column(name = "icon")
private String icon;
#Column(name = "date")
private LocalDateTime date = LocalDateTime.now();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSubtitle() {
return subtitle;
}
public void setSubtitle(String subtitle) {
this.subtitle = subtitle;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public LocalDateTime getDate() {
return date;
}
public void setDate(LocalDateTime date) {
this.date = date;
}
public List<TagEntity> getTags() {
return tags;
}
public void setTags(List<TagEntity> tags) {
this.tags = tags;
}
#Override
public String toString() {
return "DataLightEntity{" +
"id=" + id +
", title='" + title + '\'' +
", subtitle='" + subtitle + '\'' +
", text='" + text + '\'' +
", tags=" + tags +
", icon='" + icon + '\'' +
", date=" + date +
'}';
}
}
package com.perso.ez.debate.tag;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.perso.ez.debate.data.DataLightEntity;
import com.perso.ez.debate.tag.type.TagTypeEntity;
import org.hibernate.search.annotations.Field;
import javax.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
#Entity
#Table(name = "tag")
public class TagEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Field
#Column(name = "tag")
private String tag;
#ManyToOne
#JoinColumn(name = "type_id", nullable = false)
private TagTypeEntity type;
#ManyToMany(mappedBy = "tags")
#JsonIgnore
private List<DataLightEntity> datas = new ArrayList<>();
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public Long getId() {
return id;
}
public TagTypeEntity getType() {
return type;
}
public void setType(TagTypeEntity type) {
this.type = type;
}
public List<DataLightEntity> getDatas() {
return datas;
}
public void setDatas(List<DataLightEntity> datas) {
this.datas = datas;
}
}
I'm using the #Field and #IndexedEmbedded annotation for my research functionality and the #JsonIgnore to avoid an infinite loop.
But, I still getting this error when I'm trying to make a research:
Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: failed to lazily initialize a collection of role: com.perso.ez.debate.data.DataLightEntity.tags, could not initialize proxy - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.perso.ez.debate.data.DataLightEntity.tags, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.perso.ez.debate.data.DataLightEntity["tags"])]
I don't know what to do. I tried many things but I'm out of ideas.
If anyone has an idea, that would help me a lot.
Thanks!
Add fetch: Lazy to your DataLightEntity as below:
#IndexedEmbedded
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "data_tags", joinColumns = #JoinColumn(name = "data_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "tag_id", referencedColumnName = "id"))
private List<TagEntity> tags;
I think, as you have lazily fetch(by default), then while deserializing thhe resultset, you got that error. To overcome those, add this for lazy fetch entity(In this case, as you have many to many relation, add this line for both entity class level I mean after your #Table annotation in DataLightEntity and TagEntity class)
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
Hope this helps.

How can we sort the result by date in Hibernate?

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);

#ManyToOne with JOIN FetchMode generating inner join

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.

hibernate.QueryException: could not resolve property

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.

Categories