I am doing the following query in JPA:
#NamedQuery(name = PlayerSkill.DELETE_ALL_BOT_DATA,
query = "DELETE FROM PlayerSkill s WHERE s.player.id " +
"IN (SELECT p.id FROM Player p WHERE p.team.id " +
"IN (SELECT t.id FROM Manager m JOIN m.teamInfo t WHERE m.localUserId IS NULL))")
And receiving the following exception when calling appropriate DAO function, which is calling the JPA named query using executeUpdate:
7818 [Thread-12] WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: 0, SQLState: 42601
7818 [Thread-12] ERROR o.h.e.jdbc.spi.SqlExceptionHelper - ERROR: syntax error at or near "cross"
Position: 30
7828 [Thread-12] ERROR c.m.s.threads.ServerInitializer - null
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute statement
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387) ~[AbstractEntityManagerImpl.class:4.2.8.Final]
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310) ~[AbstractEntityManagerImpl.class:4.2.8.Final]
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:1397) ~[AbstractEntityManagerImpl.class:4.2.8.Final]
at org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:111) ~[AbstractQueryImpl.class:4.2.8.Final]
at com.magnifi.pennantrace.dao.player.PlayerSkillDAO.deleteBotTeamsData(PlayerSkillDAO.java:25) ~[PlayerSkillDAO.class:na]
at com.magnifi.schedserv.seasonstartend.SeasonGeneration.deleteAllBotRelatedData(SeasonGeneration.java:1457) ~[SeasonGeneration.class:na]
at com.magnifi.schedserv.seasonstartend.SeasonGeneration.generateSeason(SeasonGeneration.java:109) ~[SeasonGeneration.class:na]
at com.magnifi.schedserv.threads.ServerInitializer.generateEndStart(ServerInitializer.java:161) [ServerInitializer.class:na]
at com.magnifi.schedserv.threads.ServerInitializer.initSystem(ServerInitializer.java:80) [ServerInitializer.class:na]
at com.magnifi.schedserv.threads.SchedulerThread.run(SchedulerThread.java:38) [SchedulerThread.class:na]
Caused by: org.hibernate.exception.SQLGrammarException: could not execute statement
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:123) ~[SQLStateConversionDelegate.class:4.2.8.Final]
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49) ~[StandardSQLExceptionConverter.class:4.2.8.Final]
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125) ~[SqlExceptionHelper.class:4.2.8.Final]
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110) ~[SqlExceptionHelper.class:4.2.8.Final]
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:189) ~[ResultSetReturnImpl.class:4.2.8.Final]
at org.hibernate.hql.internal.ast.exec.BasicExecutor.doExecute(BasicExecutor.java:108) ~[BasicExecutor.class:4.2.8.Final]
at org.hibernate.hql.internal.ast.exec.BasicExecutor.execute(BasicExecutor.java:77) ~[BasicExecutor.class:4.2.8.Final]
at org.hibernate.hql.internal.ast.exec.DeleteExecutor.execute(DeleteExecutor.java:124) ~[DeleteExecutor.class:4.2.8.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.executeUpdate(QueryTranslatorImpl.java:415) ~[QueryTranslatorImpl.class:4.2.8.Final]
at org.hibernate.engine.query.spi.HQLQueryPlan.performExecuteUpdate(HQLQueryPlan.java:282) ~[HQLQueryPlan.class:4.2.8.Final]
at org.hibernate.internal.SessionImpl.executeUpdate(SessionImpl.java:1215) ~[SessionImpl.class:4.2.8.Final]
at org.hibernate.internal.QueryImpl.executeUpdate(QueryImpl.java:116) ~[QueryImpl.class:4.2.8.Final]
at org.hibernate.ejb.QueryImpl.internalExecuteUpdate(QueryImpl.java:198) ~[QueryImpl.class:4.2.8.Final]
at org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:102) ~[AbstractQueryImpl.class:4.2.8.Final]
... 6 common frames omitted
Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near "cross"
Position: 30
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2161) ~[postgresql-9.3-1101.jdbc4.jar:na]
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1890) ~[postgresql-9.3-1101.jdbc4.jar:na]
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255) ~[postgresql-9.3-1101.jdbc4.jar:na]
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:559) ~[postgresql-9.3-1101.jdbc4.jar:na]
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:417) ~[postgresql-9.3-1101.jdbc4.jar:na]
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:363) ~[postgresql-9.3-1101.jdbc4.jar:na]
at org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:100) ~[tomcat-dbcp.jar:8.0.3]
at org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:100) ~[tomcat-dbcp.jar:8.0.3]
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:186) ~[ResultSetReturnImpl.class:4.2.8.Final]
... 15 common frames omitted
7832 [Thread-12] ERROR c.m.s.threads.SchedulerThread - null
javax.persistence.RollbackException: Transaction marked as rollbackOnly
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:72) ~[TransactionImpl.class:4.2.8.Final]
at com.magnifi.schedserv.threads.SchedulerThread.run(SchedulerThread.java:39) ~[SchedulerThread.class:na]
The real sql query on that exception is:
delete from bb_player_skills cross join bb_players player1_ where id in (select player2_.id from bb_players player2_ where player2_.team_id in (select teaminfo4_.id from bb_manager manager3_ inner join bb_team_info teaminfo4_ on manager3_.bb_team_info_id=teaminfo4_.id where manager3_.local_user_id is null))
I can't understand why its forming the query using "cross" as it says in the error log.
For a different table the same query works well:
#NamedQuery(name=PlayerStat.DELETE_BOT_DATA,
query = "DELETE FROM PlayerStat s WHERE s.player.id " +
"IN (SELECT p.id FROM Player p WHERE p.team.id " +
"IN (SELECT t.id FROM Manager m JOIN m.teamInfo t WHERE m.localUserId IS NULL))")
And real sql formed by this query is not containing "cross":
delete from bb_player_stat where bb_players_id in (select player1_.id from bb_players player1_ where player1_.team_id in (select teaminfo3_.id from bb_manager manager2_ inner join bb_team_info teaminfo3_ on manager2_.bb_team_info_id=teaminfo3_.id where manager2_.local_user_id is null))
The relation of tables is same also: player skill is one to one to players , same as player stat
EDIT:
for player skills (the one where cross is used) the entity:
#JSON(include=false)
private Player player;
#Id
#OneToOne(fetch=FetchType.LAZY)
#JoinColumn(name="bb_players_id", nullable=false)
public Player getPlayer() {
return this.player;
}
And for PlayerStat:
private Player player;
#OneToOne(fetch=FetchType.LAZY)
#JoinColumn(name="bb_players_id", nullable=false)
public Player getPlayer() {
return this.player;
}
In the Player entity:
#OneToOne(mappedBy="player", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
public PlayerSkill getPlayerSkill() {
return this.playerSkill;
}
#OneToOne(mappedBy="player", cascade=CascadeType.ALL)
public PlayerStat getPlayerStats() {
return this.playerStats;
}
Related
Spring DATA JPA question... I am trying to write a query to access the data in my sql join table.
I have my join table set up as follows:
#Entity
#Table(name="WritingCompany")
public class WritingCompany {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "companyId")
private Long id;
// private String companyName;
#ManyToMany
#JoinTable(name = "Join-WritingCo-Carrier",
joinColumns = #JoinColumn(name="writingCo"),
inverseJoinColumns = #JoinColumn(name="carrier")
)
private Set<CarrierAppointment> carriers;
//...getters and setters
}
public class CarrierAppointment {
// ...
#ManyToMany(
cascade=CascadeType.ALL,
mappedBy = "companyName"
)
private Set<WritingCompany> companies;
public Set<WritingCompany> getCompanies() {
return companies;
}
public void setCompanies(Set<WritingCompany> companies) {
this.companies = companies;
}
//...
}
I am unsure which class repository I need to write the query for... I am trying to find all the writingCo names from the join table that all have the same carrier id that matches one specific carrier.
The Join Table is set up through writing company but I feel like it should be accessed through CarrierAppointment Repository since I am matching carrier Id's.
This is what I've tried in the CarrierAppointmentrepository and it throws this error (unexpected token: Join near line 1, column 94):
#Query("Select companyName FROM WritingCompany INNER JOIN CarrierAppointment ON Join-WritingCo-Carrier.carrier= CarrierAppointment.CarrierAppointmentId")
List<CarrierAppointment> findCarrierAppoinmentFromJoin(CarrierAppointment carrier);
I've also tried:
#Query("SELECT writingCo FROM Join-WritingCo-Carrier WHERE carrier= CarrierAppointment.CarrierAppointmentId")
List<CarrierAppointment> findCarrierAppoinmentFromJoin(CarrierAppointment carrier);
Then I tried this in the writingCompanyRepository which also throws a similar error:
#Query("Select companyName FROM WritingCompany INNER JOIN CarrierAppointment ON Join-WritingCo-Carrier.carrier= CarrierAppointment.CarrierAppointmentId")
List<WritingCompany> findAllWithDescriptionQuery(CarrierAppointment carrier);
I am having a hard time understanding what this query is saying. Do I ever need to access the columns from the sql join table, or am I just querying around the join table by asking for each class that is making up the join columns in the join table? What is the right part of the statement, after INNER JOIN stating ? Could someone please provide a deeper explanation of why the query is written so I can figure out why it's not working? I've been reading a lot of inner join examples and just can't seem to figure it out.
I have some "SELECT n+1" issues with an HSQL query using Hibernate and Spring Data using the IN clause.
We have some organizations that published applications thought a PublishedApplication object.
The current model is (and it cannot be changed easily):
public class Application {
Organization organization;
...
}
public class Organization {
...
}
public class PublishedApplication extends ... {
#OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
private Application application;
#ManyToOne(cascade = CascadeType.REFRESH)
#JoinColumn(name="publishingorganization_uuid")
protected Organization publishingOrganization;
}
I want to list all apps that are published by one of my organizations.
So I'v write this query:
#Query(value = "SELECT DISTINCT p.application
FROM PublishedApplication p
WHERE p.publishingOrganization IN ?1")
List<Application> findAllByPublishedOrganizationIn(List<Organization> organizations);
This works well but when I enable SQL log, I see:
1 SELECT to get "publishedapplication.application": ok it's the main request.
3 SELECT to get "organization": I have access to 10 organizations but only 3 have published an application
Here is the code call:
log.debug("Before");
List<Application> applications = applicationRepository.findAllByPublishedOrganizationIn(organizations);
log.debug("After");
And here is the Log:
ApplicationService : Before
Hibernate: select distinct applicatio1_.uuid as uuid1_0_, applicatio1_.version as version2_0_, applicatio1_.description as descript3_0_, applicatio1_.lastversiondate as lastvers4_0_, applicatio1_.name as name5_0_, applicatio1_.organization_uuid as organiza6_0_ from publishedapplication publisheda0_ inner join applications applicatio1_ on publisheda0_.application_uuid=applicatio1_.uuid where publisheda0_.publishingorganization_uuid in (? , ? , ? , ? , ? , ? , ? , ? , ? , ?)
Hibernate: select organizati0_.uuid as uuid1_8_0_, organizati0_.version as version2_8_0_, organizati0_.description as descript3_8_0_, organizati0_.name as name4_8_0_ from organizations organizati0_ where organizati0_.uuid=?
Hibernate: select organizati0_.uuid as uuid1_8_0_, organizati0_.version as version2_8_0_, organizati0_.description as descript3_8_0_, organizati0_.name as name4_8_0_ from organizations organizati0_ where organizati0_.uuid=?
Hibernate: select organizati0_.uuid as uuid1_8_0_, organizati0_.version as version2_8_0_, organizati0_.description as descript3_8_0_, organizati0_.name as name4_8_0_ from organizations organizati0_ where organizati0_.uuid=?
ApplicationService : After
I suppose that the 3 'SELECT organization' are triggered by doing this "p.publishingOrganization IN".
Is it a way to resolve this problem using a single SELECT?
Something like this in SQL:
List<Organization> orgs = ...
List<String> orgsIds = ...
doSQL("SELECT *
FROM publishedApplication p
WHERE p.publishingOrganizationId IN (" + orgsIds.join(",") + ")");
Thanks
EDIT: I resolve this using:
SELECT DISTINCT p.application FROM PublishedApplication p JOIN FETCH p.application.organization WHERE p.publishingOrganization IN ?1
I have a studentinfo cache for StudentInfo class and a classinfo cache for ClassInfo,
These two classes are used to do join(Student has an attribute of classId)
With the following code snippet,
SqlFieldsQuery innerJoinSQL = new SqlFieldsQuery(
"select StudentInfo.studentId, StudentInfo.name, StudentInfo.classId from StudentInfo as a, " +
"\"class_cache\".ClassInfo as b where a.classId = b.classId");
cursor = studentCache.query(innerJoinSQL);
for (List data : cursor) {
System.out.println(String.format("studentId %s, studentName %s, classId %s, className %s", data.get(0), data.get(1), data.get(2), data.get(3)));
}
I got following exception:
Exception in thread "main" javax.cache.CacheException: Failed to parse query: select a.studentId, a.name, a.classId, b.name from StudentInfo a, 'class_cache'.ClassInfo b on a.classId = b.classId
at org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing.queryTwoStep(IgniteH2Indexing.java:1137)
at org.apache.ignite.internal.processors.query.GridQueryProcessor$2.applyx(GridQueryProcessor.java:732)
at org.apache.ignite.internal.processors.query.GridQueryProcessor$2.applyx(GridQueryProcessor.java:730)
at org.apache.ignite.internal.util.lang.IgniteOutClosureX.apply(IgniteOutClosureX.java:36)
at org.apache.ignite.internal.processors.query.GridQueryProcessor.executeQuery(GridQueryProcessor.java:1666)
at org.apache.ignite.internal.processors.query.GridQueryProcessor.queryTwoStep(GridQueryProcessor.java:730)
at org.apache.ignite.internal.processors.cache.IgniteCacheProxy.query(IgniteCacheProxy.java:700)
at ignite.sqlgrid.join.IgniteSQLJoinQueryTest.main(IgniteSQLJoinQueryTest.java:75)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:88)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:613)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "SELECT A.STUDENTID, A.NAME, A.CLASSID, B.NAME FROM STUDENTINFO A, 'class_cache'[*].CLASSINFO B ON A.CLASSID = B.CLASSID "; expected "identifier"; SQL statement:
select a.studentId, a.name, a.classId, b.name from StudentInfo a, 'class_cache'.ClassInfo b on a.classId = b.classId [42001-191]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.getSyntaxError(DbException.java:205)
at org.h2.command.Parser.readIdentifierWithSchema(Parser.java:3115)
at org.h2.command.Parser.readTableFilter(Parser.java:1202)
at org.h2.command.Parser.parseSelectSimpleFromPart(Parser.java:1884)
at org.h2.command.Parser.parseSelectSimple(Parser.java:2032)
at org.h2.command.Parser.parseSelectSub(Parser.java:1878)
at org.h2.command.Parser.parseSelectUnion(Parser.java:1699)
at org.h2.command.Parser.parseSelect(Parser.java:1687)
at org.h2.command.Parser.parsePrepared(Parser.java:443)
at org.h2.command.Parser.parse(Parser.java:315)
at org.h2.command.Parser.parse(Parser.java:287)
at org.h2.command.Parser.prepareCommand(Parser.java:252)
at org.h2.engine.Session.prepareLocal(Session.java:560)
at org.h2.engine.Session.prepareCommand(Session.java:501)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1188)
at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:73)
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:276)
at org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing.prepareStatement(IgniteH2Indexing.java:406)
at org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing.queryTwoStep(IgniteH2Indexing.java:1121)
... 12 more
Can some help where the problem is? Thanks!
Looks I figured out the problem.
My two pojo(StudentInfo and ClassInfo) for each cache has one same column named classId. Looks only one pojo can set index = true with annotation #QuerySqlField(index = true) on the classId field
But I am not sure that Ingite has such constraint. If someone knows, let confirm, thanks!
I just wrote an sql query :
DELETE FROM basisgegevens.gm_persoonburgstaat pbs
WHERE (pbs.ingangsdatum, pbs.id_persoon) in (
SELECT pbs2.ingangsdatum, pbs2.id_persoon
FROM basisgegevens.gm_persoonburgstaat pbs2
WHERE pbs2.ingangsdatum = pbs.ingangsdatum
AND pbs2.id_persoon = :persoonID
AND pbs2.id_persoonburgerlijkestaat > pbs.id_persoonburgerlijkestaat);
I need to rewrite it to JPQL, but am getting stuck with the subquery refrencing the outer query.
public class PersoonBurgerlijkeStaatEntity {
#Column(name = "id_persoonburgerlijkestaat"
private Long identifier;
private Date ingangsdatum;
#ManyToOne
#JoinColumn(name = "id_persoon", referencedColumnName = "id_persoon", nullable = false)
private PersoonEntity persoon;
}
The persoon entity has an identifier
Can someone help me rewrite this?
Thanks
Not sure about this but give a try.
DELETE FROM persoonburgstaat person where (person.ingangsdatum, person identifier) in
(select p.ingangsdatum, p.identifier from persoonburgstaat p
left join p.persoon per where per.id_persoon = :persoonID
AND per.id_persoonburgerlijkestaa > p.identifier)
the left join will make the outer query
But to be more sure post PersoonEntity entity as I think " id_persoonburgerlijkestaa " is the name of the column not the property and query will fail based on that.
I want to try change my sql code to active record, here is the original code and active record try. And the error message. Please tell me where is my wrong? Thanks.
SELECT `emlakilan`.`id`, `emlakdurum`.`durum`,`emlaktip`.`tip`,`semtler`.`semt`,`emlakilan`.`fiyat`,`emlakilan`.`tarih`,`resim`.`r1` FROM ucburcak.`emlakilan`
INNER JOIN `semtler` ON `emlakilan`.`semtId` = `semtler`.`semtid`
INNER JOIN `emlaktip` ON `emlakilan`.`emlakTipId` = `emlaktip`.`id`
INNER JOIN `emlakdurum` ON `emlakilan`.`emlakDurumId` =`emlakdurum`.`id`
LEFT JOIN `resim` ON `emlakilan`.`resimId` = `resim`.`id`
WHERE `emlakdurumId`=3 ORDER BY `emlakilan`.`id` DESC LIMIT 4;
//and here active record function
public function kucuk_ilan($durum ='3') // $durum:1=>tümü 2=>kiralık 3=>satılık 4=>takas
{
$query = $this->db->select('emlakilan.id, emlakdurum.durum, emlaktip.tip, semtler.semt, emlakilan.fiyat, emlakilan.tarih, resim.r1')
->from('emlakilan')
->join('semtler','emlakilan.semtId' === 'semtler.semtid','inner')
->join('emlaktip','emlakilan.emlakTipId'==='emlaktip.id','inner')
->join('emlakdurum','emlakilan.emlakDurumId'==='emlakdurum.id','inner')
->join('resim','emlakilan.resimId'==='resim.id','left')
->where('emlakdurumId'===$durum)
->order_by('emlakilan.id','desc')
->limit(4);
$query = $this->db->get('emlakilan');
return $query->result_array();
}
And, error message:
Error Number: 1066
Not unique table/alias: 'emlakilan'
SELECT emlakilan.id, emlakdurum.durum, emlaktip.tip, semtler.semt, emlakilan.fiyat, emlakilan.tarih, resim.r1 FROM (emlakilan, emlakilan) INNER JOIN semtler ON INNER JOIN emlaktip ON INNER JOIN emlakdurum ON LEFT JOIN resim ON WHERE 0 IS NULL ORDER BY emlakilan.id desc LIMIT 4
Filename: C:\Program Files\EasyPHP-12.1\www\3burcak\system\database\DB_driver.php
Line Number: 330
Thanks for help.
So 1. remove the 'from' line
2. the joins where wrong
try this:
public function kucuk_ilan($durum ='3') // $durum:1=>tümü 2=>kiralık 3=>satılık 4=>takas
{
$query = $this->db->select('emlakilan.id, emlakdurum.durum, emlaktip.tip, semtler.semt, emlakilan.fiyat, emlakilan.tarih, resim.r1')
->from('emlakilan')
->join('semtler','emlakilan.semtId = semtler.semtid','inner')
->join('emlaktip','emlakilan.emlakTipId = emlaktip.id','inner')
->join('emlakdurum','emlakilan.emlakDurumId = emlakdurum.id','inner')
->join('resim','emlakilan.resimId = resim.id','left')
->where('emlakdurumId', $durum)
->order_by('emlakilan.id','desc')
->limit(4);
$query = $this->db->get('emlakilan');
return $query->result_array();
}