I have problems using join with QUeryDSL. I'm trying to receive a list of "Clube" which has a ManyToOne relation with "Federacao".
Could someone help me?
Thanks.
The relation is between the classes below.
#Entity
#Table(name = "federacoes")
#SequenceGenerator(name = "idgen", sequenceName = "federacoes_id_federacao_seq", allocationSize = 1)
#AttributeOverride(name = "id", column = #Column(name = "id_federacao"))
public class Federacao extends AbstractEntity{
private String sigla;
private String uf;
private String nome;
...
}
#Entity
#Table(name = "clubes")
#SequenceGenerator(name = "idgen", sequenceName = "clubes_id_clube_seq", allocationSize = 1)
#AttributeOverride(name = "id", column = #Column(name = "id_clube"))
public class Clube extends AbstractEntity{
private Federacao federacao;
...
#ManyToOne
#JoinColumn(name = "id_federacao")
#Column(name = "federacao")
public Federacao getFederacao() {
return federacao;
}
...
}
I'm using QueryDSL and in the repository class which extends QueryDslRepositorySupport I'm doing this:
...
#PersistenceContext
private EntityManager em;
private static final QClube qClube = QClube.clube;
private static final QFederacao qFederacao = QFederacao.federacao;
#Override
public List<Clube> findAll(FilterClubeDTO filterClubeDTO) {
JPAQuery query = new JPAQuery(em);
return query.from(qClube)
.innerJoin(qFederacao).on(qClube.federacao.eq(qFederacao))
.orderBy(qClube.id.desc())
.list(qClube);
}
I'm receiving this exception:
2016-04-12 12:32:38.485 ERROR 2853 --- [ qtp36627152-15] o.h.hql.internal.ast.ErrorCounter : Path expected for join!
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join! [select clube
from br.com.cbfm.core.models.Clube clube
inner join Federacao federacao with clube.federacao = federacao
order by clube.id desc]; nested exception is java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join! [select clube
from br.com.cbfm.core.models.Clube clube
inner join Federacao federacao with clube.federacao = federacao
order by clube.id desc]
This should work as expected:
JPAQuery query = new JPAQuery(em);
return query.from(qClube)
.innerJoin(qClube.federacao, qFederacao)
.orderBy(qClube.id.desc())
.list(qClube);
The query provided by Meiko is right. I've downloaded your project and found some issues related with the relations of the models.
Don't use the following code,
#ManyToOne
#JoinColumn(name = "id_federacao")
#Column(name = "federacao")
public Federacao getFederacao() {
return federacao;
}
But use,
#ManyToOne
#JoinColumn(name = "federacao")
private Federacao federacao;
Use the name "federacao" instead "id_federacao" because the column you want to join is clubes.federacao and not clubes.id_federacao.
You can't use #Column with #ManyToOne.
That should solve you're problem. I've also modified some little things, but that shouldn't affect the code to work.
The problem was in my mapping. I just fixed it doing it:
Class Clube
#ManyToOne
#JoinColumn(name="id_federacao", nullable=false)
private Federacao federacao;
and Class Federacao
#OneToMany(mappedBy="federacao")
private Set<Clube> clubes;
I have now another problem that I'll post right now.
Thanks everyone.
Related
I wrote native query but I'm getting an error:
The column name covidSymptomId is not valid.
What's wrong?
There are table in mssql
Error picture
CovidSymptom.java
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name="CovidSymptom")
public class CovidSymptom {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "covidSymptomId")
private int id;
#ManyToOne
#JoinColumn(name = "covidId")
private Covid covidSymptom;
#Column(name = "symptom")
private String symptom;
}
CovidSymptomDao.java
#Query(nativeQuery = true,value = "Select symptom From CovidSymptom GROUP BY symptom order by count(covidSymptomId) desc")
List<CovidSymptom> getMost3SymptomOffCovid();
You need to include all columns that are mapped in your query. So:
Select covidSymptomId, symptom....
I'm not sure why you're getting a column name problem, since your select query returns a list of "symptom"(String), whilst your method provides a list of "CovidSymptom" (Object).
I have tow classes, the "Article" which contains a #ManyToOne reference to a "SurchargeGroup" which specifies the surcharge for that article.
#Entity
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode(doNotUseGetters = true)
#Audited
public final class Article {
#Id
#GeneratedValue(generator = "increment")
#GenericGenerator(name = "increment", strategy = "increment")
#Getter(onMethod_ = {#Key(PermissionKey.ARTICLE_ID_READ)})
#Setter(onMethod_ = {#Key(PermissionKey.ARTICLE_ID_WRITE)})
private int id;
#JoinColumn(nullable = false)
#ManyToOne
#Getter(onMethod_ = {#Key(PermissionKey.SURCHARGE_TABLE_SUPPLIER_READ)})
#Setter(onMethod_ = {#Key(PermissionKey.SURCHARGE_TABLE_SUPPLIER_WRITE)})
private SurchargeGroup surchargeGroup;
}
The other class "SurchargeGroup" contains a parent object reference which can inherit the surcharge to the "SurchargeGroup" if it isn't set the case that no surcharge is provided by any parent is not possible.
#Table
#Entity
#EqualsAndHashCode(doNotUseGetters = true)
#Audited
public class SurchargeGroup implements Serializable, Cloneable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column
#Getter(onMethod_ = {#Key(PermissionKey.SURCHARGE_TABLE_ID_READ)})
#Setter(onMethod_ = {#Key(PermissionKey.SURCHARGE_TABLE_ID_WRITE)})
private int id;
#Column
#Setter(onMethod_ = {#Key(PermissionKey.SURCHARGE_TABLE_SURCHARGE_WRITE)})
private Double surcharge;
#Column
#Getter(onMethod_ = {#Key(PermissionKey.SURCHARGE_TABLE_NAME_READ)})
#Setter(onMethod_ = {#Key(PermissionKey.SURCHARGE_TABLE_NAME_WRITE)})
private String name;
#JoinColumn
#ManyToOne(fetch = FetchType.EAGER)
#Getter(onMethod_ = {#Key(PermissionKey.SURCHARGE_TABLE_SUPPLIER_READ)})
#Setter(onMethod_ = {#Key(PermissionKey.SURCHARGE_TABLE_SUPPLIER_WRITE)})
private SurchargeGroup parent;
public double getSurcharge() {
if (surcharge == null) {
return parent == null
? supplier == null
? Setting.SURCHARGE_DEFAULT.getDoubleValue()
: supplier.getDefaultSurcharge()
: parent.getSurcharge();
} else return surcharge;
}
#JoinColumn
#ManyToOne
#Getter(onMethod_ = {#Key(PermissionKey.SURCHARGE_TABLE_SUPPLIER_READ)})
#Setter(onMethod_ = {#Key(PermissionKey.SURCHARGE_TABLE_SUPPLIER_WRITE)})
private Supplier supplier;
}
My problem is now that if I call the "getSurcharge()" method I get this exception which I cannot explain to myself because I marked the surcharge group to fetch eager
Exception in thread "AWT-EventQueue-0" org.hibernate.LazyInitializationException: could not initialize proxy [kernbeisser.DBEntities.SurchargeGroup#1046] - the owning Session was closed
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:172)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:309)
at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:45)
at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95)
at kernbeisser.DBEntities.SurchargeGroup$HibernateProxy$cdTAuBkS.getSurcharge(Unknown Source)
I asked myself if this could get caused by the #Audited annotation? Any ideas? Thanks a lot!
Note: the #Key annotations have no effect to this scenario.
Here is what the debugger shows (Sorry for the German toString() functions):
Hibernate needs to stop eagerly fetching associations at some point, otherwise it would need to join an infinite number of times the SurchargeGroup entity (since it references itself).
The depth these fetches can be controlled application wide using the hibernate.max_fetch_depth property.
The source of the error was the AuditReader it doesn't fetch all eager properties even if they are annotated as Fetch.EAGER
It looks like the AuditReader only fetches one level of eager relations:
Article -> SurchargeGroup -> SurchargeGroup -> ...
(fetched) (fetched) (not fetched)
I am working on setting up some entities for a project that I am working on. My issue is that I am getting an invalid identifier error on my hibernate filters. Below is a simplified example:
#Data
#Entity
#Table(name = "###")
public class C1 {
#OneToMany(mappedBy = "###")
#Filter(name = "C2.set1Filter")
private Set<C2> set1;
#OneToMany(mappedBy = "###")
#Filter(name = "C2.set2Filter")
private Set<C2> set2;
#OneToMany(mappedBy = "###")
#Filter(name = "C2.set3Filter")
private Set<C2> set3;
}
#Data
#Entity
#Table(name = "###")
#FilterDefs({
#FilterDef(
name = "set1Filter"
defaultCondition = "c3.value = 'One'"
),
#FilterDef(
name = "set2Filter"
defaultCondition = "c3.value = 'Two'"
),
#FilterDef(
name = "set3Filter"
defaultCondition = "c3.value = 'Three'"
)
})
public class C2 {
#ManyToOne
#JoinColumn(name = "ID")
C3 c3;
}
#Data
#Entity
#Table(name = "###")
public class C3 {
#Id
#Column(name = "ID")
private Long id;
#Column(name = "VALUE")
private String value;
}
When the filters are off, they don't run, and therefore I don't get an error. However, when they are on, I am getting an error saying that c3.value is an invalid identifier.
I am obviously doing something wrong here. Is it possible to get the above to work?
As it stated in the documentation:
The #Filter condition uses a SQL condition and not a JPQL filtering predicate.
So, you should use actual tables and columns names.
#Filter(
name="setFilter",
condition="{c3}.VALUE = :val",
aliases = {
#SqlFragmentAlias( alias = "c3", table= "C3_TABLE_NAME")
}
)
As it stated here:
When using the #Filter annotation and working with entities that are mapped onto multiple database tables, you will need to use the #SqlFragmentAlias annotation if the #Filter defines a condition that uses predicates across multiple tables.
I'm trying to create List of expressions for my elementCollection defined in an embeddable using the criteria builder, but it's always throwing:
Caused by: org.hibernate.MappingException: Unknown collection role: be.fgov.health.gift.action.domain.potentialdonorfile.patient.GeneralPatientInformation.causesOfDeath
Has anyone got any idea to work around this problem?
This is my code:
The entities :
#Entity
#Table(name = "POTENTIAL_DONOR_FILE")
#SequenceGenerator(name = Domain.SEQUENCE_GENERATOR_NAME, sequenceName = "PDF_SEQUENCE")
//Domain contains the Id
public class PotentialDonorFile extends Domain {
#Embedded
private GeneralPatientInformation generalPatientInformation;
}
#Embeddable
public class GeneralPatientInformation {
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "CAUSES_OF_DEATH",
joinColumns = #JoinColumn(name = PDF_ID_JOIN_COLUMN_NAME))
#Column(name = "CAUSE_OF_DEATH")
#Enumerated(EnumType.STRING)
#Fetch(FetchMode.SELECT)
private List<CauseOfDeath> causesOfDeath;
}
The repository layer :
Expression<List<CauseOfDeath>> listExpression = getGeneralPatientInformationPath(potentialDonorFileRoot).get(GeneralPatientInformation_.causesOfDeath);
private Path<GeneralPatientInformation> getGeneralPatientInformationPath(Root<PotentialDonorFile> potentialDonorFileRoot) {
return potentialDonorFileRoot.get(PotentialDonorFile_.generalPatientInformation);
}
So to summarize:
When i'm calling "xxx.get(GeneralPatientInformation_.causesOfDeath);" I'm getting the MappingException.
EDIT:
As test I've moved the ElementCollection to the PotentialDonorFile itself (so outside of the embeddable), and now it seems to be working.. Can't consider this as a solution, but put I've it here as an extra comment.
I hava a problem with mapping embedded fields in Hibernate.
This is the code:
#Entity
#Table(name="CAR")
#SqlResultSetMapping(name = "carMapping",
entities = {
#EntityResult(entityClass = Car.class,
fields = {
#FieldResult(name = "id", column = "ID"),
#FieldResult(name = "producer", column = "PRODUCER"),
#FieldResult(name = "model", column = "MODEL"),
#FieldResult(name="bookNumber",column="SERVICE_BOOK_NUMBER"),
#FieldResult(name="owner", column="SERVICE_BOOK_OWNER")
}
)})
public class Car {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="ID")
private Long id;
#Column(name="PRODUCER")
private String producer;
#Column(name="MODEL")
private String model;
#Embedded
#AttributeOverrides({
#AttributeOverride(name="bookNumber", column=#Column(name="SERVICE_BOOK_NUMBER")),
#AttributeOverride(name="owner", column=#Column(name="SERVICE_BOOK_OWNER")),
})
private ServiceBook serviceBook;
When I try to retrive a Car I get the following error:
javax.ejb.EJBTransactionRolledbackException: The transaction has been marked rollback only
because the bean encountered a non-application exception :javax.persistence.PersistenceException :
org.hibernate.exception.SQLGrammarException: Column 'SERVICE4_0_0_' not found
My question is: is it possible to use #SqlResultSetMapping and #Embedded together?
Create a new #EntityResult to ServiceBook such as you did with Car.class. I usually do this to bind columns to the attributes.