JPA Named query with INNER JOIN condition is failing - java

I'm trying to create a Named query with the inner join condition in the Entity class.
However the application is failing to start with an exception.
Entity:
#Entity
#Table(name = "fooentry")
#NamedQuery(name="query1", query="SELECT foo.id, foo.name, foo.type, foo.action, foo.createdDateTime FROM FooEntity foo " +
"INNER JOIN (SELECT name, type, MAX(createdDateTime) AS recenttime FROM FooEntity GROUP BY name, type) recententry " +
"ON (foo.name = recententry.name AND foo.type = recententry.type) AND createdDateTime = recenttime AND isExported = false",
lockMode=PESSIMISTIC_WRITE)
public class FooEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name")
#NotNull
private String msisdn;
#Column(name = "type")
#NotNull
private String iccid;
#Column(name = "action")
#NotNull
private Long inventoryActionId;
#NotNull
#Column(name = "is_exported")
private Boolean isExported;
#Column(name = "created_date_time")
#NotNull
private LocalDateTime createdDateTime;
//setter and getter
}
Exception:
Application is failing to start with the following exception.
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.HibernateException: Errors in named queries:
query1 failed because of: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 161

You can try query like below. It should return expected result
SELECT foo.id, foo.name, foo.type, foo.action, foo.createdDateTime
FROM FooEntity foo
WHERE
foo.isExported = false AND
EXISTS(
SELECT recententry.name, recententry.type, MAX(recententry.createdDateTime) AS recenttime
FROM FooEntity recententry
WHERE recententry.name = foo.name AND recententry.type = foo.type
GROUP BY recententry.name, recententry.type
HAVING recententry.recenttime = foo.createdDateTime
)

Related

SQL Grammar Exception in Spring Boot H2

I'v got a problem in my Spring Boot with H2 project. I got a get method for listing elements from the SQL table and the SQL command working. In the H2 database I can execute and see the results but I can't get the values from Postman. My GET post went wrong. My SQL codes are also in here.
I also uploaded my project to github. If you want to see all classes Here is my GitHub project link
UrunEntity class
#Entity
#Table(name = "urunler")
public class UrunEntity{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "urun_id")
private int urunId;
#Column(name = "hayvan_kupe_no")
private int hayvanKupeNo;
#Column(name = "hayvan_adi")
private String hayvanAdi;
#Column(name = "dogum_sekli")
private String dogumSekli;
#Column(name = "hayvan_resmi")
private String hayvanResmi;
#Column(name = "hayvan_cinsiyet")
private String hayvanCinsiyet;
#Column(name = "hayvan_irki")
private String hayvanIrki;
#Column(name = "hayvan_anneAdi")
private String hayvanAnneAdi;
#Column(name = "dogum_tarihi")
private String dogumTarihi;
#Column(name = "dogum_agirligi")
private Double dogumAgirligi;
#Column(name = "tohuma_hazir")
private Boolean tohumaHazir;
#Column(name = "sut_miktari")
private Double sutMiktari;
#Column(name = "sut_tarihi")
private String sutTarihi;
#Column(name = "urun_tutar")
private Double urunTutar;
#Column(name = "user_id")
private Integer userId;
//getters and setters after that
Here is my UrunRepository
#Query(value="SELECT DOGUM_AGIRLIGI, DOGUM_SEKLI, DOGUM_TARIHI, HAYVAN_ADI, HAYVAN_ANNE_ADI, HAYVAN_CINSIYET, HAYVAN_IRKI, URUN_TUTAR FROM URUNLER d " +
"INNER JOIN kullanicilar k on d.user_id = k.user_id " +
"WHERE k.user_id=:userId AND HAYVAN_ADI IS NOT NULL",
nativeQuery=true)
List<UrunEntity> findHayvanAll(#Param("userId") String userId);
Here is the error code at backend
> 2021-01-12 17:58:39.357 WARN 19652 --- [nio-6161-exec-5] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 42122, SQLState: 42S22
2021-01-12 17:58:39.357 ERROR 19652 --- [nio-6161-exec-5] o.h.engine.jdbc.spi.SqlExceptionHelper : Column "urun_id" not found [42122-200]
2021-01-12 17:58:39.374 ERROR 19652 --- [nio-6161-exec-5] o.a.c.c.C.[.[.[.[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [/invoiceControl] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; SQL [SELECT DOGUM_AGIRLIGI, DOGUM_SEKLI, DOGUM_TARIHI, HAYVAN_ADI, HAYVAN_ANNE_ADI, HAYVAN_CINSIYET, HAYVAN_IRKI, URUN_TUTAR FROM URUNLER d INNER JOIN kullanicilar k on d.user_id = k.user_id WHERE k.user_id=? AND HAYVAN_ADI IS NOT NULL]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query] with root cause
org.h2.jdbc.JdbcSQLSyntaxErrorException: Column "urun_id" not found [42122-200]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:453) ~[h2-1.4.200.jar:1.4.200]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:429) ~[h2-1.4.200.jar:1.4.200]
at org.h2.message.DbException.get(DbException.java:205) ~[h2-1.4.200.jar:1.4.200]
at org.h2.message.DbException.get(DbException.java:181) ~[h2-1.4.200.jar:1.4.200]
at org.h2.jdbc.JdbcResultSet.getColumnIndex(JdbcResultSet.java:3169) ~[h2-1.4.200.jar:1.4.200]
at org.h2.jdbc.JdbcResultSet.get(JdbcResultSet.java:3268) ~[h2-1.4.200.jar:1.4.200]
at org.h2.jdbc.JdbcResultSet.getInt(JdbcResultSet.java:352) ~[h2-1.4.200.jar:1.4.200]
Here is the error from Postman:
"timestamp": "2021-01-12T14:30:50.458+0000",
"status": 500,
"error": "Internal Server Error",
"message": "could not execute query; SQL [SELECT SUT_MIKTARI, SUT_TARIHI, URUN_TUTAR FROM URUNLER d INNER JOIN kullanicilar k on d.user_id = k.user_id WHERE k.user_id=? AND SUT_MIKTARI IS NOT NULL]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query",
"trace": "org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; SQL [SELECT SUT_MIKTARI, SUT_TARIHI, URUN_TUTAR FROM URUNLER d INNER JOIN kullanicilar k on d.user_id = k.user_id WHERE k.user_id=? AND SUT_MIKTARI IS NOT NULL]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query\r\n\tat org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:281)\r\n\tat org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255)\r\n\tat org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)\r\n\tat org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)\r\n\tat org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)\r\n\tat org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)\r\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\r\n\tat org.springframework.data.jpa.repository.support
KullanicilarEntity class
#Entity
#Table(name = "kullanicilar")
public class KullaniciEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id")
private long userId;
#Column(name = "email")
private String email;
#Column(name = "kullanici_sifre")
private String kullaniciSifre;
#Column(name = "kullanici_adi")
private String kullaniciAdi;
#Column(name = "kullanici_soyadi")
private String kullaniciSoyadi;
#Column(name = "telefon_no")
private String telefonNo;
#Column(name = "enabled")
private boolean enabled;
#Column(name = "username")
private String username;
My Resource(endpoints) interface
#GetMapping(path = "/getSut")
public ResponseEntity<List<UrunEntity>> getSut(#RequestParam("userId") String userId) {
List<UrunEntity> urunEntities = ccAppService.findSutAll(userId);
return new ResponseEntity(urunEntities, HttpStatus.OK);
}
Seems like you want to materialize an entity from a native query, but the native query is not selecting the urun_id column which is required to materialize the entity. Try using HQL queries instead of native queries.
You are trying to map fields not fully fitting your entity. Try also selecting urun_id in your query or d.* in the selection part.
For more complex queries you can use SqlResultSetMapping. Check this link.
I create a new model class named HayvanDto and I created all of the UrunEntity entites inside of this.
public class HayvanDto {
private Double dogumAgirligi;
private String dogumSekli;
private String dogumTarihi;
private String hayvanAdi;
private String hayvanAnneAdi;
private String hayvanCinsiyet;
private String hayvanIrki;
private String hayvanResmi;
private Boolean tohumaHazir;
private Double urunTutar;
After that, in my implementation class, I wrote this code.
#Override
public List<HayvanDto> findHayvanAll(Integer userId) {
List<UrunEntity> urunEntities = urunRepository.findHayvanAll(userId);
List<HayvanDto> hayvanDtos = new ArrayList<>();
for (UrunEntity urunEntity : urunEntities) {
HayvanDto hayvanDto = new HayvanDto();
hayvanDto.setHayvanAdi(urunEntity.getHayvanAdi());
hayvanDto.setHayvanIrki(urunEntity.getHayvanIrki());
hayvanDto.setHayvanResmi(urunEntity.getHayvanResmi());
hayvanDto.setHayvanCinsiyet(urunEntity.getHayvanCinsiyet());
hayvanDto.setHayvanAnneAdi(urunEntity.getHayvanAnneAdi());
hayvanDto.setDogumAgirligi(urunEntity.getDogumAgirligi());
hayvanDto.setDogumSekli(urunEntity.getDogumSekli());
hayvanDto.setUrunTutar(urunEntity.getUrunTutar());
hayvanDto.setTohumaHazir(urunEntity.getTohumaHazir());
hayvanDtos.add(hayvanDto);
}
return hayvanDtos;
}
Then it worked. Thanks for the answers.

Hibernate HQL Map query

i have a class:
#Entity
#Table(name = "days")
public class DayEntry {
#Expose
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
.
.
#Expose
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "day_item_hours")
#MapKeyJoinColumn(name = "item_id")
#Column(name = "hours")
private Map<Item, Double> itemsHours;
.
.
}
I need to get from DB all DayEntries which contain specific Item in itemHours field.
I tried:
private final String FIND_BY_ACTIVITY = "from DayEntry d where :activity in index(d.itemsHours)";
#Override
public Collection<DayEntry> findByActivity(Item activity) {
Query query = entityManager.createQuery(FIND_BY_ACTIVITY);
query.setParameter("activity", activity);
return query.getResultList();
}
And get this:
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 75 [from ua.siemens.dbtool.model.timesheet.DayEntry d where :activity in index(d.itemsHours)]] with root cause
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 75 [from ua.siemens.dbtool.model.timesheet.DayEntry d where :activity in index(d.itemsHours)]
Not sure how to handle this.
Thanks!
UPDATE
For the moment i ended up with plain SQL Query:
private final String FIND_BY_ACTIVITY = "SELECT * FROM days where id = (SELECT DayEntry_id from day_item_hours where day_item_hours.item_id = :activityId)";
#Override
public Collection<DayEntry> findByActivity(Item activity) {
Query query = entityManager.createNativeQuery(FIND_BY_ACTIVITY_ID, DayEntry.class);
query.setParameter("activityId", activity.getId());
return query.getResultList();
}
but still i wonder how to do it with HQL.

My query does not work. Type "double" does not exist

I tried that:
#Query("SELECT AVG(a.unitPrice) FROM ConnectwiseAgreementAdditions a WHERE a.agreementId = :agreementId " +
"AND a.productId IN (SELECT p.id FROM ConnectwiseProductFindResult p " +
"WHERE LOWER(p.subCategory) LIKE LOWER('%server%') " +
"OR LOWER(p.subCategory) LIKE LOWER('%workstation%'))")
BigDecimal geAgreementDevicetUnitPrice(#Param("agreementId") Integer agreementId);
But i have exception:
2016-05-11 14:58:05.773 ERROR 28016 --- [main] o.h.e.j.s.SqlExceptionHelper : ERROR: type "double" does not exist
Position: 44
Exception in thread "main" org.springframework.orm.jpa.JpaSystemException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
What is wrong?
I use Postgresql driver.
UPDATE
My entity:
#Entity
#Table(name = "connectwise_agreement_additions")
public class ConnectwiseAgreementAdditions {
#Id
#Column
private Integer id;
#Column(columnDefinition = "DEFAULT false")
private boolean normalize = false;
#Column(name = "agreement_id", columnDefinition = "NUMERIC(18,2)")
private Integer agreementId;
#Column(name = "product_id")
private Integer productId;
#Column(name = "unit_price", columnDefinition = "NUMERIC(18,2)")
private BigDecimal unitPrice;
}

Error in Join on a relation ManyToOne. Using QueryDSL

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.

JPA how to query the database without creating a table

I am using JPA and Spring for my db tasks and I need to have a join query like below in the JPA Repo class
#Query("SELECT 1 as id, COUNT(bill) as bills, ba.resource, MAX(b.updatedAt) as latestdate FROM Bill b join b.billComp ba where ba.comp.comp = ?1 group by ba.resource")
public List<BillCalc> findByBills(Long comp);
My Entity class is as below
#Entity
public class BillCalc {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "latestdate", nullable = false)
private Date latestdate;
#Column(name = "bills", nullable = false)
private Long bills;
#Column(name = "resource", nullable = false)
private String resource;
I cannot create a table for this and can someone help me in getting the mapping to work? It gives me an error saying cannot cast from Object to BillCalc.
I tried #SubSelect but it does not take parameters
add a constructor to BillCalc.
BillCalc(Integer id, long bills, String resouce, Date latestdate) {...}
then use a Select new query:
SELECT new BillCalc(1, COUNT(bill), ba.resource, MAX(b.updatedAt))
FROM Bill b join b.billComp ba
WHERE ba.comp.comp = ?1 group by ba.resource")
#See Chapter 4.8.2 "Constructor Expressions in the SELECT Clause" in JSR-000220 Enterprise JavaBeans 3.0 Final Release (persistence)

Categories

Resources