Spring data jpa join query with multiple parameters - java

Hello I am trying to pull a record from MySql db using spring jpa.
Entity 1
#Entity #Table(name = "sku_warehouse") #Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) #Document(indexName = "skuwarehouse") public class SkuWarehouse extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "avail_qty")
private Integer availQty;
#Column(name = "effective_date")
private ZonedDateTime effectiveDate;
#Column(name = "expiration_date")
private ZonedDateTime expirationDate;
#ManyToOne
private SkuMaster skuMaster;
#ManyToOne
private Country country;
#ManyToOne
private Warehouse warehouse;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getAvailQty() {
return availQty;
}
public SkuWarehouse availQty(Integer availQty) {
this.availQty = availQty;
return this;
}
public void setAvailQty(Integer availQty) {
this.availQty = availQty;
}
public ZonedDateTime getEffectiveDate() {
return effectiveDate;
}
public SkuWarehouse effectiveDate(ZonedDateTime effectiveDate) {
this.effectiveDate = effectiveDate;
return this;
}
public void setEffectiveDate(ZonedDateTime effectiveDate) {
this.effectiveDate = effectiveDate;
}
public ZonedDateTime getExpirationDate() {
return expirationDate;
}
public SkuWarehouse expirationDate(ZonedDateTime expirationDate) {
this.expirationDate = expirationDate;
return this;
}
public void setExpirationDate(ZonedDateTime expirationDate) {
this.expirationDate = expirationDate;
}
public SkuMaster getSkuMaster() {
return skuMaster;
}
public SkuWarehouse skuMaster(SkuMaster skuMaster) {
this.skuMaster = skuMaster;
return this;
}
public void setSkuMaster(SkuMaster skuMaster) {
this.skuMaster = skuMaster;
}
public Country getCountry() {
return country;
}
public SkuWarehouse country(Country country) {
this.country = country;
return this;
}
public void setCountry(Country country) {
this.country = country;
}
public Warehouse getWarehouse() {
return warehouse;
}
public SkuWarehouse warehouse(Warehouse warehouse) {
this.warehouse = warehouse;
return this;
}
public void setWarehouse(Warehouse warehouse) {
this.warehouse = warehouse;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SkuWarehouse skuWarehouse = (SkuWarehouse) o;
if (skuWarehouse.id == null || id == null) {
return false;
}
return Objects.equals(id, skuWarehouse.id);
}
#Override
public int hashCode() {
return Objects.hashCode(id);
}
#Override
public String toString() {
return "SkuWarehouse{" +
"id=" + id +
", availQty='" + availQty + "'" +
", effectiveDate='" + effectiveDate + "'" +
", expirationDate='" + expirationDate + "'" +
'}';
} }
Entity 2 :
#Entity
#Table(name = "sku_master")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#Document(indexName = "skumaster")
public class SkuMaster extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "ordering_item")
private String orderingItem;
#NotNull
#Column(name = "sku_number", nullable = false)
private String skuNumber;
#Column(name = "sku_description")
private String skuDescription;
#Column(name = "brand_name")
private String brandName;
#Column(name = "item_status")
private String itemStatus;
#Column(name = "item_weight")
private Float itemWeight;
#Column(name = "item_tax_cd")
private String itemTaxCd;
#Enumerated(EnumType.STRING)
#Column(name = "vendor_ship_cd")
private Flag vendorShipCd;
#Column(name = "ltu_quantity")
private String ltuQuantity;
#ManyToMany
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#JoinTable(name = "sku_master_country",
joinColumns = #JoinColumn(name="sku_masters_id", referencedColumnName="id"),
inverseJoinColumns = #JoinColumn(name="countries_id", referencedColumnName="id"))
private Set<Country> countries = new HashSet<>();
#ManyToMany
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#JoinTable(name = "sku_master_warehouse",
joinColumns = #JoinColumn(name="sku_masters_id", referencedColumnName="id"),
inverseJoinColumns = #JoinColumn(name="warehouses_id", referencedColumnName="id"))
private Set<Warehouse> warehouses = new HashSet<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getOrderingItem() {
return orderingItem;
}
public SkuMaster orderingItem(String orderingItem) {
this.orderingItem = orderingItem;
return this;
}
public void setOrderingItem(String orderingItem) {
this.orderingItem = orderingItem;
}
public String getSkuNumber() {
return skuNumber;
}
public SkuMaster skuNumber(String skuNumber) {
this.skuNumber = skuNumber;
return this;
}
public void setSkuNumber(String skuNumber) {
this.skuNumber = skuNumber;
}
public String getSkuDescription() {
return skuDescription;
}
public SkuMaster skuDescription(String skuDescription) {
this.skuDescription = skuDescription;
return this;
}
public void setSkuDescription(String skuDescription) {
this.skuDescription = skuDescription;
}
public String getBrandName() {
return brandName;
}
public SkuMaster brandName(String brandName) {
this.brandName = brandName;
return this;
}
public void setBrandName(String brandName) {
this.brandName = brandName;
}
public String getItemStatus() {
return itemStatus;
}
public SkuMaster itemStatus(String itemStatus) {
this.itemStatus = itemStatus;
return this;
}
public void setItemStatus(String itemStatus) {
this.itemStatus = itemStatus;
}
public Float getItemWeight() {
return itemWeight;
}
public SkuMaster itemWeight(Float itemWeight) {
this.itemWeight = itemWeight;
return this;
}
public void setItemWeight(Float itemWeight) {
this.itemWeight = itemWeight;
}
public String getItemTaxCd() {
return itemTaxCd;
}
public SkuMaster itemTaxCd(String itemTaxCd) {
this.itemTaxCd = itemTaxCd;
return this;
}
public void setItemTaxCd(String itemTaxCd) {
this.itemTaxCd = itemTaxCd;
}
public Flag getVendorShipCd() {
return vendorShipCd;
}
public SkuMaster vendorShipCd(Flag vendorShipCd) {
this.vendorShipCd = vendorShipCd;
return this;
}
public void setVendorShipCd(Flag vendorShipCd) {
this.vendorShipCd = vendorShipCd;
}
public String getLtuQuantity() {
return ltuQuantity;
}
public SkuMaster ltuQuantity(String ltuQuantity) {
this.ltuQuantity = ltuQuantity;
return this;
}
public void setLtuQuantity(String ltuQuantity) {
this.ltuQuantity = ltuQuantity;
}
public Set<Country> getCountries() {
return countries;
}
public SkuMaster countries(Set<Country> countries) {
this.countries = countries;
return this;
}
public SkuMaster addCountry(Country country) {
this.countries.add(country);
return this;
}
public SkuMaster removeCountry(Country country) {
this.countries.remove(country);
return this;
}
public void setCountries(Set<Country> countries) {
this.countries = countries;
}
public Set<Warehouse> getWarehouses() {
return warehouses;
}
public SkuMaster warehouses(Set<Warehouse> warehouses) {
this.warehouses = warehouses;
return this;
}
public SkuMaster addWarehouse(Warehouse warehouse) {
this.warehouses.add(warehouse);
return this;
}
public SkuMaster removeWarehouse(Warehouse warehouse) {
this.warehouses.remove(warehouse);
return this;
}
public void setWarehouses(Set<Warehouse> warehouses) {
this.warehouses = warehouses;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SkuMaster skuMaster = (SkuMaster) o;
if (skuMaster.id == null || id == null) {
return false;
}
return Objects.equals(id, skuMaster.id);
}
#Override
public int hashCode() {
return Objects.hashCode(id);
}
#Override
public String toString() {
return "SkuMaster{" +
"id=" + id +
", orderingItem='" + orderingItem + "'" +
", skuNumber='" + skuNumber + "'" +
", skuDescription='" + skuDescription + "'" +
", brandName='" + brandName + "'" +
", itemStatus='" + itemStatus + "'" +
", itemWeight='" + itemWeight + "'" +
", itemTaxCd='" + itemTaxCd + "'" +
", vendorShipCd='" + vendorShipCd + "'" +
", ltuQuantity='" + ltuQuantity + "'" +
'}';
}
}
Method that pull the record
#Query("select sw from SkuWarehouse sw left join fetch Warehouse w where sw.warehouse = w.warehouseId AND w.warehouseId=:warehouseId AND sw.skuMaster=:skuMasterId")
SkuWarehouse findOneWithEagerRelationships(#Param("warehouseId") String warehouseId, #Param("skuMasterId") Long skuMasterId);
Actually SQL query that works
select * from sku_warehouse sw
join warehouse w on (sw.warehouse_id = w.id)
where w.warehouse_id='024'
and sw.sku_master_id='1072'
Error Log
Caused by: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private java.lang.Long com.company.wmapis.domain.SkuMaster.id] by reflection for persistent property [com.company.wmapis.domain.SkuMaster#id] : 1454
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:71)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:224)
at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4647)
at org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:4358)
at org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:226)
at org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:276)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:462)
at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:161)
at org.hibernate.param.NamedParameterSpecification.bind(NamedParameterSpecification.java:53)
at org.hibernate.loader.hql.QueryLoader.bindParameterValues(QueryLoader.java:628)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1956)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1909)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1887)
at org.hibernate.loader.Loader.doQuery(Loader.java:932)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)
at org.hibernate.loader.Loader.doList(Loader.java:2615)
at org.hibernate.loader.Loader.doList(Loader.java:2598)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2430)
at org.hibernate.loader.Loader.list(Loader.java:2425)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:502)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:371)
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:216)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1459)
at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1426)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1398)
at org.hibernate.query.internal.AbstractProducedQuery.getSingleResult(AbstractProducedQuery.java:1444)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:210)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:82)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:116)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:106)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:482)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:460)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
... 167 common frames omitted
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.Long field com.company.wmapis.domain.SkuMaster.id to java.lang.Long
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36)
at java.lang.reflect.Field.get(Field.java:393)
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:67)
... 206 common frames omitted
What is wrong in the Jpa query? I even tried passing the SkuMaster Object instead of Long but then I get MySql query exception.

It works after I changed my Jpa query and method as below
#Query(value="SELECT * FROM sku_warehouse sw JOIN warehouse w ON (sw.warehouse_id = w.Id) WHERE w.warehouse_id=?1 AND sw.sku_master_id=?2", nativeQuery = true)
SkuWarehouse findOneWithEagerRelationships(String warehouseId, Long skuMasterId);

Related

Why my custom Model mapper doesn't work properly?

I am creating a REST API using Spring Boot and for my update method I try to map a DTO Object to a domain one:
public ItemDTO updateItem(Long departmentId, Long itemId, ItemDTO itemDTO) throws ApiException {
Department department = departmentRepository.findById(departmentId).orElseThrow(
() -> new ApiException("Department with this id does not exist ",
HttpStatus.NOT_FOUND));
Item foundItem = validateItem(itemId);
Item convertedItem = mapper.convertToType(itemDTO, Item.class);
if (convertedItem.getStock() < 0) {
throw new ApiException("Stock must be a positive value", HttpStatus.BAD_REQUEST);
}
if (convertedItem.getStockThreshold() < 0) {
throw new ApiException("Stock threshold must be a positive value", HttpStatus.BAD_REQUEST);
}
itemDTO.setId(itemId);
itemDTO.setDepartment(mapper.convertToType(department, DepartmentDTO.class));
foundItem = mapper.convertToType(itemDTO, Item.class);
itemRepository.save(foundItem);
// ItemDTO returnItem = mapper.convertToType(convertedItem, ItemDTO.class);
logger.info("Updated item");
return itemDTO;
}
And this is my model mapper
#Component
public class Mapper {
private final ModelMapper modelMapper;
private final Logger logger = LoggerFactory.getLogger(ModelMapper.class);
public Mapper(ModelMapper modelMapper) {
this.modelMapper = modelMapper;
}
public <T> T convertToType(Object source, Class<T> resultClass) {
logger.debug("converted object from " + source.getClass().getSimpleName() + " to " + resultClass.getSimpleName());
return modelMapper.map(source, resultClass);
}
}
At this line foundItem = mapper.convertToType(itemDTO, Item.class); it's the problem, before this conversion my foundItem would have a department, after conversion, the department field is null.
Here are my domain and DTO classes
#NoArgsConstructor
#Getter
#Setter
public class DepartmentDTO {
private Long id;
private String description;
private List<Item> items;
public DepartmentDTO(long id, String description) {
this.id = id;
this.description = description;
}
#Override
public String toString() {
return "DepartmentDTO{" +
"id=" + id +
", description='" + description + '\'' +
", items=" + items +
'}';
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DepartmentDTO that = (DepartmentDTO) o;
return Objects.equals(id, that.id) && Objects.equals(description, that.description) && Objects.equals(items, that.items);
}
// #Override
// public int hashCode() {
// return Objects.hash(id, description, items);
// }
}
#NoArgsConstructor
#Entity
#Getter
#Setter
#Table(name = "DEPARTMENTS")
public class Department {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String description;
#OneToMany(mappedBy = "department", fetch = FetchType.EAGER,
cascade = CascadeType.ALL)
private List<Item> items;
public Department(Long id, String description) {
this.id = id;
this.description = description;
}
#Override
public String toString() {
return "Department{" +
"id=" + id +
", description='" + description + '\'' +
", items=" + items +
'}';
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Department)) return false;
Department that = (Department) o;
return id.equals(that.id) && Objects.equals(description, that.description) && Objects.equals(items, that.items);
}
#Override
public int hashCode() {
return Objects.hash(id, description, items);
}
}
#AllArgsConstructor
#NoArgsConstructor
#Setter
public class ItemDTO {
private Long id;
private String description;
private String price;
private int stock;
private int stockThreshold;
private DepartmentDTO department;
public Long getId() {
return id;
}
public String getDescription() {
return description;
}
public String getPrice() {
return price;
}
public int getStock() {
return stock;
}
public int getStockThreshold() {
return stockThreshold;
}
public Long getDepartment() {
return department.getId();
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ItemDTO itemDTO = (ItemDTO) o;
return stock == itemDTO.stock && stockThreshold == itemDTO.stockThreshold &&
id.equals(itemDTO.id) && description.equals(itemDTO.description) &&
price.equals(itemDTO.price) && department.equals(itemDTO.department);
}
#Override
public int hashCode() {
return Objects.hash(id, description, price, stock);
}
}
#AllArgsConstructor
#NoArgsConstructor
#Getter
#Setter
#Entity
#Table(name = "ITEMS")
public class Item {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private Long id;
private String description;
private String price;
private int stock;
private int stockThreshold = 5;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "department_id", nullable = false)
#OnDelete(action = OnDeleteAction.CASCADE)
#JsonIgnore
private Department department;
#Override
public String toString() {
return "Item{" +
"id=" + id +
", description='" + description + '\'' +
", price='" + price + '\'' +
", stock=" + stock +
", department=" + department +
'}';
}
}

JPQL Subquery - Exception this expression has an invalid table in this context

I have a (inneficient, but working) T-SQL (sub)query
SELECT * FROM DIAGE.ade.UorPos WHERE Prefixo IN
(SELECT PrefixoJurisdicionada FROM DIAGE.ade.Jurisdicionadas WHERE Prefixo =
(SELECT Prefixo FROM DIAGE.ade.Jurisdicionadas WHERE PrefixoJurisdicionada = 8922))
AND CodComissao IN (4345, 4346, 4347)
which I've build the correspondent JPQL
SELECT u FROM UorPos u WHERE u.prefixo IN
(SELECT j.prefixoJurisdicionada FROM Jurisdicionadas j WHERE j.prefixo =
(SELECT j.prefixo FROM Jurisdicionadas j WHERE j.prefixoJurisdicionada = :prefixo))
AND u.codComissao IN (4345, 4346, 4347)
Despite compiling, when running launches the Exception:
[...]
Caused by: Exception [EclipseLink-6069] (Eclipse Persistence Services -
2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.QueryException
Exception Description: The field [DIAGE.ade.Prefixos.Prefixo] in this
expression has an invalid table in this context.
Query: ReadAllQuery(name="UorPos.findUorPosExecutivosByPrefixo"
referenceClass=UorPos jpql="SELECT u FROM UorPos u WHERE u.prefixo IN
(SELECT j.prefixoJurisdicionada FROM Jurisdicionadas j WHERE j.prefixo =
(SELECT j.prefixo FROM Jurisdicionadas j WHERE j.prefixoJurisdicionada =
:prefixo)) AND u.codComissao IN (4345, 4346, 4347)") at
org.eclipse.persistence.exceptions.QueryException. invalidTableForFieldInExpression (QueryException.java:749)
at org.eclipse.persistence.internal.expressions.FieldExpression.validateNode(FieldExpression.java:296)
at org.eclipse.persistence.expressions.Expression.normalize(Expression.java:3275)
at org.eclipse.persistence.internal.expressions.DataExpression.normalize(DataExpression.java:369)
at org.eclipse.persistence.internal.expressions.FieldExpression.normalize(FieldExpression.java:223)
I've made some research and, in my understanding, my JPQL query is ok.
Can anyone help me to resolve this?
Some links I've researched:
item 2.5.15
How do I do a JPQL SubQuery?
item 5
item 10.2.5.15
Using IN with a subquery
I'm using EclipseLink version 2.5.2 (integrated with Netbeans 8.0.2), Glassfish 4.1, Java 1.7.0_71.
UPDATED
The UorPos entity:
#Entity
#Table(name = "UorPos", catalog = "DIAGE", schema = "ade")
#XmlRootElement
#NamedQueries({
#NamedQuery(name="UorPos.findXByY", query="SELECT u FROM UorPos u WHERE u.prefixo IN
(SELECT j.prefixoJurisdicionada FROM Jurisdicionadas j WHERE j.prefixo =
(SELECT j.prefixo FROM Jurisdicionadas j WHERE j.prefixoJurisdicionada = :prefixo))
AND u.codComissao IN (4345, 4346, 4347)")
})
public class UorPos implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 8)
#Column(name = "Matricula")
private String matricula;
#Size(max = 200)
#Column(name = "Nome")
private String nome;
#Size(max = 200)
#Column(name = "NomeGuerra")
private String nomeGuerra;
#Column(name = "CodComissao")
private Integer codComissao;
#Size(max = 25)
#Column(name = "NomeComissao")
private String nomeComissao;
#Size(max = 4)
#Column(name = "CodNivel")
private String codNivel;
#Size(max = 50)
#Column(name = "DescNivel")
private String descNivel;
#Size(max = 50)
#Column(name = "eMailFuncionario")
private String eMailFuncionario;
#Column(name = "DataCaptura")
#Temporal(TemporalType.TIMESTAMP)
private Date dataCaptura;
#Column(name = "DataPermissaoAcesso")
#Temporal(TemporalType.TIMESTAMP)
private Date dataPermissaoAcesso;
#ManyToMany(mappedBy = "uorPosCollection")
private Collection<Demandas> demandasCollection;
#ManyToMany(mappedBy = "uorPosCollection1")
private Collection<Demandas> demandasCollection1;
#ManyToMany(mappedBy = "uorPosCollection2")
private Collection<Demandas> demandasCollection2;
#JoinColumn(name = "UORpos", referencedColumnName = "UORpos")
#ManyToOne(optional = false)
private Divisoes uORpos;
#JoinColumn(name = "idPermissaoAcesso", referencedColumnName = "idPermissaoAcesso")
#ManyToOne
private PermissoesAcesso idPermissaoAcesso;
#JoinColumn(name = "Prefixo", referencedColumnName = "Prefixo")
#ManyToOne
private Prefixos prefixo;
#OneToMany(mappedBy = "matricula")
private Collection<Anotacoes> anotacoesCollection;
#OneToMany(mappedBy = "matricula")
private Collection<Log> logCollection;
public UorPos() {
}
public UorPos(String matricula) {
this.matricula = matricula;
}
public String getMatricula() {
return matricula;
}
public void setMatricula(String matricula) {
this.matricula = matricula;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getNomeGuerra() {
return nomeGuerra;
}
public void setNomeGuerra(String nomeGuerra) {
this.nomeGuerra = nomeGuerra;
}
public Integer getCodComissao() {
return codComissao;
}
public void setCodComissao(Integer codComissao) {
this.codComissao = codComissao;
}
public String getNomeComissao() {
return nomeComissao;
}
public void setNomeComissao(String nomeComissao) {
this.nomeComissao = nomeComissao;
}
public String getCodNivel() {
return codNivel;
}
public void setCodNivel(String codNivel) {
this.codNivel = codNivel;
}
public String getDescNivel() {
return descNivel;
}
public void setDescNivel(String descNivel) {
this.descNivel = descNivel;
}
public String getEMailFuncionario() {
return eMailFuncionario;
}
public void setEMailFuncionario(String eMailFuncionario) {
this.eMailFuncionario = eMailFuncionario;
}
public Date getDataCaptura() {
return dataCaptura;
}
public void setDataCaptura(Date dataCaptura) {
this.dataCaptura = dataCaptura;
}
public Date getDataPermissaoAcesso() {
return dataPermissaoAcesso;
}
public void setDataPermissaoAcesso(Date dataPermissaoAcesso) {
this.dataPermissaoAcesso = dataPermissaoAcesso;
}
#XmlTransient
public Collection<Demandas> getDemandasCollection() {
return demandasCollection;
}
public void setDemandasCollection(Collection<Demandas> demandasCollection) {
this.demandasCollection = demandasCollection;
}
#XmlTransient
public Collection<Demandas> getDemandasCollection1() {
return demandasCollection1;
}
public void setDemandasCollection1(Collection<Demandas> demandasCollection1) {
this.demandasCollection1 = demandasCollection1;
}
#XmlTransient
public Collection<Demandas> getDemandasCollection2() {
return demandasCollection2;
}
public void setDemandasCollection2(Collection<Demandas> demandasCollection2) {
this.demandasCollection2 = demandasCollection2;
}
public Divisoes getUORpos() {
return uORpos;
}
public void setUORpos(Divisoes uORpos) {
this.uORpos = uORpos;
}
public PermissoesAcesso getIdPermissaoAcesso() {
return idPermissaoAcesso;
}
public void setIdPermissaoAcesso(PermissoesAcesso idPermissaoAcesso) {
this.idPermissaoAcesso = idPermissaoAcesso;
}
public Prefixos getPrefixo() {
return prefixo;
}
public void setPrefixo(Prefixos prefixo) {
this.prefixo = prefixo;
}
#XmlTransient
public Collection<Anotacoes> getAnotacoesCollection() {
return anotacoesCollection;
}
public void setAnotacoesCollection(Collection<Anotacoes> anotacoesCollection) {
this.anotacoesCollection = anotacoesCollection;
}
#XmlTransient
public Collection<Log> getLogCollection() {
return logCollection;
}
public void setLogCollection(Collection<Log> logCollection) {
this.logCollection = logCollection;
}
#Override
public int hashCode() {
int hash = 0;
hash += (matricula != null ? matricula.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
if (!(object instanceof UorPos)) {
return false;
}
UorPos other = (UorPos) object;
if ((this.matricula == null && other.matricula != null) || (this.matricula != null && !this.matricula.equals(other.matricula))) {
return false;
}
return true;
}
#Override
public String toString() {
return "br.com.bb.uop.dcvipat.ade.entity.UorPos[ matricula=" + matricula + " ]";
}
}
The Jurisdicionadas entity:
#Entity
#Table(name = "Jurisdicionadas", catalog = "DIAGE", schema = "ade")
#XmlRootElement
#NamedQueries({
#NamedQuery(name="Jurisdicionadas.findAll", query="SELECT j FROM Jurisdicionadas j")})
public class Jurisdicionadas implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#Column(name = "PrefixoJurisdicionada")
private Integer prefixoJurisdicionada;
#Size(max = 200)
#Column(name = "NomePrefixoJurisdicionada")
private String nomePrefixoJurisdicionada;
#JoinColumn(name = "Prefixo", referencedColumnName = "Prefixo")
#ManyToOne
private Prefixos prefixo;
public Jurisdicionadas() {
}
public Jurisdicionadas(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getPrefixoJurisdicionada() {
return prefixoJurisdicionada;
}
public void setPrefixoJurisdicionada(Integer prefixoJurisdicionada) {
this.prefixoJurisdicionada = prefixoJurisdicionada;
}
public String getNomePrefixoJurisdicionada() {
return nomePrefixoJurisdicionada;
}
public void setNomePrefixoJurisdicionada(String nomePrefixoJurisdicionada) {
this.nomePrefixoJurisdicionada = nomePrefixoJurisdicionada;
}
public Prefixos getPrefixo() {
return prefixo;
}
public void setPrefixo(Prefixos prefixo) {
this.prefixo = prefixo;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
if (!(object instanceof Jurisdicionadas)) {
return false;
}
Jurisdicionadas other = (Jurisdicionadas) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "br.com.bb.uop.dcvipat.ade.entity.Jurisdicionadas[ id=" + id + " ]";
}
}
Thanks in advance.
After the great hint posted by htshame, I've researched about Eclipselink Native SQL Queries and workarounded the problem as below:
public List<UorPos> findUorPosExecutivosByPrefixo(Prefixos prefixo) {
return (List<UorPos>) getEntityManager().createNativeQuery("SELECT * FROM DIAGE.ade.UorPos WHERE prefixo IN (SELECT prefixoJurisdicionada FROM DIAGE.ade.Jurisdicionadas WHERE prefixo = (SELECT prefixo FROM DIAGE.ade.Jurisdicionadas WHERE prefixoJurisdicionada = ?)) AND codComissao IN (4345, 4346, 4347) ORDER BY nome, matricula", UorPos.class).setParameter(1, prefixo.getPrefixo()).getResultList();
}
But, if someone could resolve the JPQL named query issue, it will be better.

Problems join fetching with a where clause to same entity

I have the following query in my repository:
SELECT p FROM Project p JOIN p.users u WHERE u.login =:login
There is a Many To Many relationshio between user and project.
Everything works fine and it returns the user's projects, but I want it for each project to return the corresponding set of users. So updated it with a fetch join:
SELECT p FROM Project p JOIN FETCH p.users JOIN p.users u WHERE u.login =:login
But now i got the following exception:
nested exception is java.lang.IllegalArgumentException: Count query validation failed for method public abstract org.springframework.data.domain.Page com.example.app.repository.ProjectRepository.findAllByUserLo‌​gin(java.lang.String‌​,org.springframework‌​.data.domain.Pageabl‌​e)! org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list
Cannot find a workaround for it to execute the where clause and fetch the collection at the same time.
Project Entity:
#Entity
#Table(name = "project")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#Document(indexName = "project")
public class Project implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#NotNull
#Size(min = 10, max = 50)
#Column(name = "name", length = 50, nullable = false)
private String name;
#Size(max = 150)
#Column(name = "description", length = 150)
private String description;
#Column(name = "project_type")
private Integer projectType;
#Column(name = "is_active")
private Boolean isActive;
#Column(name = "date_created")
private ZonedDateTime dateCreated;
#Column(name = "date_updated")
private ZonedDateTime dateUpdated;
#ManyToMany
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#JoinTable(name = "project_user",
joinColumns = #JoinColumn(name="projects_id", referencedColumnName="ID"),
inverseJoinColumns = #JoinColumn(name="users_id", referencedColumnName="ID"))
private Set<User> users = new HashSet<>();
#OneToMany(mappedBy = "project")
#JsonIgnore
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Milestone> milestones = new HashSet<>();
#OneToMany(mappedBy = "project")
#JsonIgnore
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<TaskList> taskLists = new HashSet<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getProjectType() {
return projectType;
}
public void setProjectType(Integer projectType) {
this.projectType = projectType;
}
public Boolean isIsActive() {
return isActive;
}
public void setIsActive(Boolean isActive) {
this.isActive = isActive;
}
public ZonedDateTime getDateCreated() {
return dateCreated;
}
public void setDateCreated(ZonedDateTime dateCreated) {
this.dateCreated = dateCreated;
}
public ZonedDateTime getDateUpdated() {
return dateUpdated;
}
public void setDateUpdated(ZonedDateTime dateUpdated) {
this.dateUpdated = dateUpdated;
}
public Set<User> getOwners() {
return users;
}
public void setOwners(Set<User> users) {
this.users = users;
}
public Set<Milestone> getMilestones() {
return milestones;
}
public void setMilestones(Set<Milestone> milestones) {
this.milestones = milestones;
}
public Set<TaskList> getTaskLists() {
return taskLists;
}
public void setTaskLists(Set<TaskList> taskLists) {
this.taskLists = taskLists;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Project project = (Project) o;
if(project.id == null || id == null) {
return false;
}
return Objects.equals(id, project.id);
}
#Override
public int hashCode() {
return Objects.hashCode(id);
}
#Override
public String toString() {
return "Project{" +
"id=" + id +
", name='" + name + "'" +
", description='" + description + "'" +
", projectType='" + projectType + "'" +
", isActive='" + isActive + "'" +
", dateCreated='" + dateCreated + "'" +
", dateUpdated='" + dateUpdated + "'" +
'}';
}
}
User Entity:
#Entity
#Table(name = "user")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#Document(indexName = "user")
public class User extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#NotNull
#Pattern(regexp = Constants.LOGIN_REGEX)
#Size(min = 1, max = 100)
#Column(length = 100, unique = true, nullable = false)
private String login;
#JsonIgnore
#NotNull
#Size(min = 60, max = 60)
#Column(name = "password_hash",length = 60)
private String password;
#Size(max = 50)
#Column(name = "first_name", length = 50)
private String firstName;
#Size(max = 50)
#Column(name = "last_name", length = 50)
private String lastName;
#Email
#Size(max = 100)
#Column(length = 100, unique = true)
private String email;
#NotNull
#Column(nullable = false)
private boolean activated = false;
#Size(min = 2, max = 5)
#Column(name = "lang_key", length = 5)
private String langKey;
#Size(max = 20)
#Column(name = "activation_key", length = 20)
#JsonIgnore
private String activationKey;
#Size(max = 20)
#Column(name = "reset_key", length = 20)
private String resetKey;
#Column(name = "reset_date", nullable = true)
private ZonedDateTime resetDate = null;
#Column(name = "avatar", nullable = true)
private String avatar;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login.toLowerCase(Locale.ENGLISH);
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean getActivated() {
return activated;
}
public void setActivated(boolean activated) {
this.activated = activated;
}
public String getActivationKey() {
return activationKey;
}
public void setActivationKey(String activationKey) {
this.activationKey = activationKey;
}
public String getResetKey() {
return resetKey;
}
public void setResetKey(String resetKey) {
this.resetKey = resetKey;
}
public ZonedDateTime getResetDate() {
return resetDate;
}
public void setResetDate(ZonedDateTime resetDate) {
this.resetDate = resetDate;
}
public String getLangKey() {
return langKey;
}
public void setLangKey(String langKey) {
this.langKey = langKey;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
User user = (User) o;
if (!login.equals(user.login)) {
return false;
}
return true;
}
#Override
public int hashCode() {
return login.hashCode();
}
#Override
public String toString() {
return "User{" +
"login='" + login + '\'' +
", avatar='" + avatar + '\'' +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", activated='" + activated + '\'' +
", langKey='" + langKey + '\'' +
", activationKey='" + activationKey + '\'' +
"}";
}
}
Try to remove second join:
SELECT p FROM Project p JOIN FECTH p.users u WHERE u.login =:login
And if you want to get Projects which contains specified user by login then you can try this:
SELECT p FROM Project p JOIN FECTH p.users u WHERE :login in elements(u.login)

Vaadin JPAContainer: ManytoOne relation with EmbeddedID

There are questions similar but not quite. In those cases (and in the JPAContainer examples) the Entity part of the ManyToOne relationship has a single key. In my case it is an embedded id.
My code is based on the Address Book example.
Here are the three entities:
#Entity
#Table(name = "tutorial")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Tutorial.findAll", query = "SELECT t FROM Tutorial t"),
#NamedQuery(name = "Tutorial.findById", query = "SELECT t FROM Tutorial t WHERE t.tutorialPK.id = :id"),
#NamedQuery(name = "Tutorial.findByTutorialTypeId", query = "SELECT t FROM Tutorial t WHERE t.tutorialPK.tutorialTypeId = :tutorialTypeId"),
#NamedQuery(name = "Tutorial.findByMessage", query = "SELECT t FROM Tutorial t WHERE t.message = :message")})
public class Tutorial implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected TutorialPK tutorialPK;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 245)
#Column(name = "message")
private String message;
#JoinColumn(name = "tutorial_type_id", referencedColumnName = "id", insertable = false, updatable = false)
#ManyToOne(optional = false)
private TutorialType tutorialType;
public Tutorial() {
}
public Tutorial(TutorialPK tutorialPK) {
this.tutorialPK = tutorialPK;
}
public Tutorial(TutorialPK tutorialPK, String message) {
this.tutorialPK = tutorialPK;
this.message = message;
}
public Tutorial(int id, int tutorialTypeId) {
this.tutorialPK = new TutorialPK(id, tutorialTypeId);
}
public TutorialPK getTutorialPK() {
return tutorialPK;
}
public void setTutorialPK(TutorialPK tutorialPK) {
this.tutorialPK = tutorialPK;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public TutorialType getTutorialType() {
return tutorialType;
}
public void setTutorialType(TutorialType tutorialType) {
this.tutorialType = tutorialType;
}
#Override
public int hashCode() {
int hash = 0;
hash += (tutorialPK != null ? tutorialPK.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 Tutorial)) {
return false;
}
Tutorial other = (Tutorial) object;
if ((this.tutorialPK == null && other.tutorialPK != null) || (this.tutorialPK != null && !this.tutorialPK.equals(other.tutorialPK))) {
return false;
}
return true;
}
#Override
public String toString() {
return "games.jwrestling.server.game.db.persistence.Tutorial[ tutorialPK=" + tutorialPK + " ]";
}
}
And the EmbeddedId class:
#Embeddable
public class TutorialPK implements Serializable {
#Basic(optional = false)
#NotNull
#Column(name = "id")
private int id;
#Basic(optional = false)
#NotNull
#Column(name = "tutorial_type_id")
private int tutorialTypeId;
public TutorialPK() {
}
public TutorialPK(int id, int tutorialTypeId) {
this.id = id;
this.tutorialTypeId = tutorialTypeId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getTutorialTypeId() {
return tutorialTypeId;
}
public void setTutorialTypeId(int tutorialTypeId) {
this.tutorialTypeId = tutorialTypeId;
}
#Override
public int hashCode() {
int hash = 0;
hash += (int) id;
hash += (int) tutorialTypeId;
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 TutorialPK)) {
return false;
}
TutorialPK other = (TutorialPK) object;
if (this.id != other.id) {
return false;
}
if (this.tutorialTypeId != other.tutorialTypeId) {
return false;
}
return true;
}
#Override
public String toString() {
return "games.jwrestling.server.game.db.persistence.TutorialPK[ id=" + id + ", tutorialTypeId=" + tutorialTypeId + " ]";
}
}
And another one:
#Entity
#Table(name = "tutorial_type")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "TutorialType.findAll", query = "SELECT t FROM TutorialType t"),
#NamedQuery(name = "TutorialType.findById", query = "SELECT t FROM TutorialType t WHERE t.id = :id"),
#NamedQuery(name = "TutorialType.findByType", query = "SELECT t FROM TutorialType t WHERE t.type = :type"),
#NamedQuery(name = "TutorialType.findByDescription", query = "SELECT t FROM TutorialType t WHERE t.description = :description")})
public class TutorialType implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#GeneratedValue(strategy = GenerationType.TABLE, generator = "TutorialTypeGen")
#TableGenerator(name = "TutorialTypeGen", table = "jwrestling_id",
pkColumnName = "tablename",
valueColumnName = "last_id",
pkColumnValue = "tutorial_type",
allocationSize = 1,
initialValue = 1)
#Column(name = "id")
private Integer id;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "type")
private String type;
#Size(max = 245)
#Column(name = "description")
private String description;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "tutorialType")
private List<Tutorial> tutorialList;
public TutorialType() {
}
public TutorialType(Integer id) {
this.id = id;
}
public TutorialType(Integer id, String type) {
this.id = id;
this.type = type;
}
public TutorialType(String type, String desc) {
this.type = type;
this.description = desc;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#XmlTransient
public List<Tutorial> getTutorialList() {
return tutorialList;
}
public void setTutorialList(List<Tutorial> tutorialList) {
this.tutorialList = tutorialList;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.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 TutorialType)) {
return false;
}
TutorialType other = (TutorialType) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "games.jwrestling.server.game.db.persistence.TutorialType[ id=" + id + " ]";
}
}
I got the form set up and it works fine when I edit the items, but creating I get errors because the TutorialPK is null:
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.2.v20151217-774c696): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'tutorial_type_id' cannot be null
Here are the related Vaadin code:
public final class TutorialEditor extends Window implements Button.ClickListener,
FormFieldFactory {
private final Item tutorialItem;
private final Form editorForm;
private final Button saveButton;
private final Button cancelButton;
public TutorialEditor(Item tutorialItem) {
this.tutorialItem = tutorialItem;
editorForm = new Form();
editorForm.setFormFieldFactory(this);
editorForm.setBuffered(true);
editorForm.setImmediate(true);
editorForm.setItemDataSource(tutorialItem, Arrays.asList("message",
"tutorialType"));
saveButton = new Button("Save", this);
cancelButton = new Button("Cancel", this);
editorForm.getFooter().addComponent(saveButton);
editorForm.getFooter().addComponent(cancelButton);
setSizeUndefined();
setContent(editorForm);
setCaption("New Tutorial");
}
#Override
public void buttonClick(Button.ClickEvent event) {
if (event.getButton() == saveButton) {
editorForm.commit();
fireEvent(new EditorSavedEvent(this, tutorialItem));
} else if (event.getButton() == cancelButton) {
editorForm.discard();
}
close();
}
#Override
public Field<?> createField(Item item, Object propertyId, Component uiContext) {
Field field = DefaultFieldFactory.get().createField(item, propertyId,
uiContext);
if ("tutorialType".equals(propertyId)) {
field = new TutorialTypeSelector();
} else if (field instanceof TextField) {
((TextField) field).setNullRepresentation("");
}
field.addValidator(new BeanValidator(Tutorial.class, propertyId
.toString()));
return field;
}
public void addListener(EditorSavedListener listener) {
try {
Method method = EditorSavedListener.class.getDeclaredMethod(
"editorSaved", new Class[]{EditorSavedEvent.class});
addListener(EditorSavedEvent.class, listener, method);
} catch (final java.lang.NoSuchMethodException e) {
// This should never happen
throw new java.lang.RuntimeException(
"Internal error, editor saved method not found");
}
}
public void removeListener(EditorSavedListener listener) {
removeListener(EditorSavedEvent.class, listener);
}
public static class EditorSavedEvent extends Component.Event {
private final Item savedItem;
public EditorSavedEvent(Component source, Item savedItem) {
super(source);
this.savedItem = savedItem;
}
public Item getSavedItem() {
return savedItem;
}
}
public interface EditorSavedListener extends Serializable {
public void editorSaved(EditorSavedEvent event);
}
And another one:
class TutorialTypeSelector extends CustomField<TutorialType> {
private final JPAContainer<TutorialType> container;
private final ComboBox type = new ComboBox();
public TutorialTypeSelector() {
container = JPAContainerFactory.make(TutorialType.class,
"JWPUJNDI");
setCaption("Type");
type.setContainerDataSource(container);
type.setItemCaptionPropertyId("type");
type.addListener(new Property.ValueChangeListener() {
#Override
public void valueChange(
com.vaadin.data.Property.ValueChangeEvent event) {
/*
* Modify the actual value of the custom field.
*/
if (type.getValue() == null) {
setValue(null, false);
} else {
TutorialType entity = container
.getItem(type.getValue()).getEntity();
setValue(entity, false);
}
}
});
}
#Override
protected Component initContent() {
CssLayout cssLayout = new CssLayout();
cssLayout.addComponent(type);
return cssLayout;
}
#Override
public void setPropertyDataSource(Property newDataSource) {
super.setPropertyDataSource(newDataSource);
setTutorialType((TutorialType) newDataSource.getValue());
}
#Override
public void setValue(TutorialType newValue) throws ReadOnlyException,
Converter.ConversionException {
super.setValue(newValue);
setTutorialType(newValue);
}
private void setTutorialType(TutorialType type) {
this.type.setValue(type != null ? type.getId() : null);
}
#Override
public Class<? extends TutorialType> getType() {
return TutorialType.class;
}
}
Any idea on how to populate this field?
Update:
Error after using #MapsId
Exception [EclipseLink-46] (Eclipse Persistence Services - 2.6.2.v20151217-774c696): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: There should be one non-read-only mapping defined for the primary key field [tutorial.tutorial_type_id].
Descriptor: RelationalDescriptor(games.jwrestling.server.game.db.persistence.Tutorial --> [DatabaseTable(tutorial)])
Two ways. If using JPA 1.0, you will need to pull the value from the referenced tutorialType and manually add it to the tutorial.tutorialPK.tutorialTypeId. You didn't include the tutorialType entity, but if it's ID value is generated, you may need to persist it and flush before the value is assigned.
If using JPA 2.0, you can specify the #MapsId annotation in your entity, allowing JPA to set the tuturial.tutorialPK.tutorialTypeId value from the tutorial.tutorialType reference for you:
public class Tutorial implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected TutorialPK tutorialPK;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 245)
#Column(name = "message")
private String message;
#MapsId("tutorialTypeId")
#ManyToOne(optional = false)
private TutorialType tutorialType;
You will not be able to change the TutorialType associated to a tutorial once it is created though - the only option is to delete the existing one and create a new one with the new values.

Found two representations of same collection hibernate exception

I have a Spring MVC application that handle Users and Structures that can hosts one or more User.
I'm using Hibernate for the persistence and I'm having some issues with the One-To-Many relation between User and Structure.
This is my User model:
#Entity
#Table(name="USERS")
public class User extends DatabaseEntity {
#Id #GeneratedValue
private Long id = 0L;
#Column
#NotEmpty
private String firstName;
#Column
private String lastName;
#Column
private Date birthDate;
#Column
private String nation;
#Column
private String town;
#Column
private String idNumber;
#Column(unique = true)
private String email;
#Column String resetPasswordToken = "";
#Column
private String password;
#Column
private String avatarUrl;
#Column #Enumerated(EnumType.STRING)
private Role role;
#ManyToOne
#JoinColumn(name = "STRUCTURE_ID")
#Cascade({CascadeType.DETACH})
private Structure structure;
public enum Role {
ADMINISTRATOR,
SPECIALIST,
PATIENT,
DOCTOR,
CARE_GIVER
}
public User() {
birthDate = new Date();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public String getNation() {
return nation;
}
public void setNation(String nation) {
this.nation = nation;
}
public String getTown() {
return town;
}
public void setTown(String town) {
this.town = town;
}
public String getIdNumber() {
return idNumber;
}
public void setIdNumber(String idNumber) {
this.idNumber = idNumber;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAvatarUrl() {
return avatarUrl;
}
public void setAvatarUrl(String avatarUrl) {
this.avatarUrl = avatarUrl;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public Set<Group> getGroups() {
return null;
}
public void setGroups(Set<Group> groups) {
}
public Set<Group> getCreatedGroups() {
return null;
}
public void setCreatedGroups(Set<Group> createdGroups) {
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<HangoutUser> getHangoutUsers() {
return null;
}
public void setHangoutUsers(Set<HangoutUser> hangoutUsers) {
}
public String getResetPasswordToken() {
return resetPasswordToken;
}
public void setResetPasswordToken(String resetPasswordToken) {
this.resetPasswordToken = resetPasswordToken;
}
public Group getStructure() {
return structure;
}
public void setStructure(Structure structure) {
this.structure = structure;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
if (!email.equals(user.email)) return false;
if (!id.equals(user.id)) return false;
return true;
}
#Override
public int hashCode() {
Long res = id;
if(id == null)
res = 0L;
int result = res.hashCode();
result = 31 * result + email.hashCode();
return result;
}
}
And this is my Structure model:
#Entity
#Table(name = "STRUCTURES")
public class Structure extends DatabaseEntity {
#Id #GeneratedValue
Long id = 0L;
#Column
String name;
#Column
String address;
#Column
String city;
#Column
String state;
#OneToMany(mappedBy = "structure", fetch = FetchType.EAGER)
#Cascade({CascadeType.DELETE})
Set<User> users = new HashSet<User>();
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getAddress()
{
return address;
}
public void setAddress(String address)
{
this.address = address;
}
public String getCity()
{
return city;
}
public void setCity(String city)
{
this.city = city;
}
public String getState()
{
return state;
}
public void setState(String state)
{
this.state = state;
}
public Set<User> getUsers()
{
return this.users;
}
public void setUsers(Set<User> users)
{
this.users = users;
}
}
My issue is that when I try to find all the Users with the value STRUCTURE_ID evaluated, I get an Hibernate Exception, like this:
org.springframework.orm.hibernate3.HibernateSystemException: Found two representations of same collection: it.amtservices.livinglab.model.Group.users; nested exception is org.hibernate.HibernateException: Found two representations of same collection: it.amtservices.livinglab.model.Structure.users
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:690) ...
What should I do to solve this problem? I have already tried many ways but nothing solved.
I paste the abstract repository implementation for the UsersRepository and StructureRepository:
#Transactional
public abstract class AbstractRepository<Model extends DatabaseEntity>
{
Logger logger = Logger.getLogger(this.getClass().getSimpleName());
#PersistenceContext
EntityManager em;
protected Class<Model> ModelClass;
protected List<Model> findBy(String parameterName, Object parameterValue)
{
Query q = em.createQuery("select t from " + ModelClass.getSimpleName() + " t where t." + parameterName + " = :" + parameterName);
q.setParameter(parameterName, parameterValue);
List<Model> results = null;
try
{
results = q.getResultList();
}
catch (Exception e)
{
return null;
}
return results;
}
protected List<Model> findBy(Map<String, Object> parameters)
{
String whereClause = "";
for (String key : parameters.keySet())
{
if (!whereClause.equals("")) whereClause += " and ";
whereClause += "t." + key + " = :" + key;
}
Query q = null;
try
{
q = em.createQuery("select t from " + ModelClass.getSimpleName() + " t where " + whereClause);
}
catch (Exception e)
{
e.printStackTrace();
}
for (String key : parameters.keySet())
{
q.setParameter(key, parameters.get(key));
}
List<Model> results = null;
try
{
results = q.getResultList();
}
catch (Exception e)
{
return null;
}
return results;
}
protected Model findOneBy(String parameterName, Object parameterValue)
{
List<Model> results = findBy(parameterName, parameterValue);
if (results != null && results.size() > 0) return results.get(0);
return null;
}
protected Model findOneBy(Map<String, Object> parameters)
{
List<Model> results = findBy(parameters);
if (results != null && results.size() > 0) return results.get(0);
return null;
}
public Model findOne(Long id)
{
return findOneBy("id", id);
}
public List<Model> findAll()
{
Query q = em.createQuery("select t from " + ModelClass.getSimpleName() + " t");
List<Model> results = null;
try
{
results = q.getResultList();
}
catch (Exception e)
{
return null;
}
return results;
}
public boolean save(Model model)
{
try
{
Model newModel = em.merge(model);
if (model.getId() == 0L) model.setId(newModel.getId());
}
catch (Exception e)
{
logger.error(ModelClass.getSimpleName() + "Repository: " + e.getMessage());
return false;
}
return true;
}
public void save(List<Model> models)
{
for (Model model : models)
{
save(model);
}
}
public void delete(Model model)
{
delete(model.getId());
}
public void delete(Long id)
{
beforeDelete(findOne(id));
try
{
Query q = em.createQuery("delete from " + ModelClass.getSimpleName() + " t where t.id = :id").setParameter("id", id);
q.executeUpdate();
}
catch (Exception e)
{
logger.error(ModelClass.getSimpleName() + "Repository: " + e.getMessage());
}
}
public void delete(Collection<Model> models)
{
for (Model model : models)
{
delete(model.getId());
}
}
public void deleteAll()
{
for (Model model : findAll())
{
delete(model);
}
}
public abstract void beforeDelete(Model model);
public List<Model> find(List<Long> ids)
{
List<Model> models = new ArrayList<Model>();
for (Long id : ids)
{
Model model = findOne(id);
if (model != null) models.add(model);
}
return models;
}
}
Thank you!

Categories