HQL generated a incorrect SQL query - sql

I got [42000] You have an error in your SQL syntax error when I execute the HQL below:
update Status set result=18 where (userByUserId.userName like 'administrator')
And this is the corresponding SQL:
update
status cross
join
set
result=18
where
userName like 'administrator'
The results I am getting are incorrect.
But another similar query is in working order:
select count(*) from Status where (userByUserId.userName like 'administrator')
the corresponding SQL:
select
count(*) as col_0_0_
from
status status0_ cross
join
user user1_
where
status0_.userId=user1_.userId
and (
user1_.userName like 'administrator'
)
Does anyone know what happened?
Here is the code(partly):
Status.java
#Table(name = "status")
#Entity
#KeyField("statusId")
public class Status implements Serializable {
private Integer result;
#Column(name = "result", nullable = false, insertable = true, updatable = true
, length = 10, precision = 0)
#Basic
public Integer getResult() {
return result;
}
private Integer userId;
#Column(name = "userId", nullable = false, insertable = true, updatable = true
, length = 10, precision = 0)
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
private User userByUserId;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "userId", referencedColumnName = "userId", nullable = false,
insertable = false, updatable = false)
public User getUserByUserId() {
return userByUserId;
}
}
User.java
#Table(name = "user")
#Entity
#KeyField("userId")
public class User implements Serializable {
private String userName;
#Column(name = "userName", nullable = false, insertable = true, updatable = true, length = 24,
precision = 0, unique = true)
#Basic
public String getUserName() {
return userName;
}
private Collection<Status> statusesByUserId;
#OneToMany(mappedBy = "userByUserId", cascade = CascadeType.ALL)
public Collection<Status> getStatusesByUserId() {
return statusesByUserId;
}
}

Related

JPA query returns duplicate objects

I have this relationship in db. In the Item table the primary keys are Item_id and site. ItemPart table's primary keys are also them and there are other 2 primary keys as well. These tables are join by item_id and site as one to many relationships.
These are the 2 entity classes.
public class Item {
#Id
#Column(name = "item_id", updatable = false, nullable = false)
private String itemId;
#Id
#Column(name = "site", updatable = false, nullable = false)
private String site;
#OneToMany(mappedBy = "item")
private List<ItemPart> itemPart;
...
public class ItemPart {
#Id
#Column(name = "item_id", updatable = false, nullable = false)
private String itemId;
#Id
#Column(name = "site", updatable = false, nullable = false)
private String site;
#ManyToOne
#JoinColumns({
#JoinColumn(name = "item_id", referencedColumnName = "item_id", insertable = false, updatable = false),
#JoinColumn(name = "site", referencedColumnName = "site", insertable = false, updatable = false)
})
private Item item;
...
What I want is when giving an item_id return a result like below. If I give item_id = "100" and there is one item with item_id = 100 and 2 itemParts with item_id =100 and site=S01.
{
"Item":[
{
"item_id":"100",
"site":"S01",
"itemPart":[
{
"item_id":"100",
"site":"S01",
"another_pk": "x"
},
{
"item_id":"100",
"site":"S01",
"another_pk": "y"
}
],
...
}
]
But actually, it returns 2 similar item objects with each of them 2 itemPart objects. Like this.
{
item:
itemPart:[
{...},
{...}
]
},
{
item:
itemPart:[
{...},
{...}
]
}
I want to fix this and I'm using JPA. Can anyone find where is the problem here.
#Query("SELECT p FROM Item p JOIN fetch p.ItemPart n WHERE
p.item_id = ?1 ")
List<Item> findAllByItemId(String itemId);
You should correct your query like this:
#QueryHints(value = {
#QueryHint(name = org.hibernate.jpa.QueryHints.HINT_PASS_DISTINCT_THROUGH, value = "false")
})
#Query("select distinct p from Item p join fetch p.itemPart where p.itemId = :itemId ")
List<Item> findAllByItemId(#Param("itemId") String itemId);
See also this section of hibernate documentation.
I put 'distinct' in the #Query then the problem was solved.
#Query("SELECT distinct p FROM Item p JOIN fetch p.ItemPart n WHERE
p.item_id = ?1 ")
List<Item> findAllByItemId(String itemId);

Nested query in JPQL

I have 2 entities -
#Table(name = "MM_MONITORING_CARD")
#Entity(name = "mm_MonitoringCard")
public class MonitoringCard extends StandardEntity {
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "CLIENT_ID")
private Counterparty client;
#Column(name = "START_DATE")
private LocalDate startDate;
#Column(name = "END_DATE")
private LocalDate endDate;
...otherColumn
}
and
#DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
#Table(name = "MM_COUNTERPARTY")
#Entity(name = "mm_Counterparty")
#DiscriminatorValue("COUNTERPARTY")
#NamePattern("%s|name")
public class Counterparty extends StandardEntity {
#Column(name = "TYPE", insertable=false, updateable=false)
private String type;
...otherColumn
I need get all examples monitoringCard with condition - 1) between start date and end date 2) with Counterparty type = 'someType'
I do method -
List<MonitoringCard> monitoringCardList = dataManager.load(MonitoringCard.class)
.query("select distinct cm from mm_MonitoringCard m join mm_Counterparty cm where (m.current_date between cm.startDate and cm.endDate) and cm.type = :type")
.parameter("type", "someType")
.list();
but i get error, how can i make a correct request?
thanks
Your query is not correct. It should use a join like this:
select distinct m.Counterparty from mm_MonitoringCard m
where (m.current_date between m.Counterparty.startDate and m.Counterparty.endDate)
and m.Counterparty.type = :type
In JPA you don't need to do an explicit join when navigating on a ToOne relationship.

EclipseLink- JPQL join tables through query

I have problem with my JPQl. this is a one to many relationship with TrainRoute and TrainRouteStation. I'm trying to create a inner join and fetch the data. native SQL query working when I used mysql workbeanch and I'm trying convert it to JPQL. also, I was trying to fix from 2 days.
Error : Object comparisons can only be used with OneToOneMappings. Other mapping comparisons must be done through query keys or direct attribute level comparisons.
Class: TrainRoute
#Basic(optional = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
#Column(name = "train_route_id", unique = true, nullable = false)
public Long getTrainRouteId() {
return this.trainRouteId;
}
public void setTrainRouteId(Long trainRouteId) {
this.trainRouteId = trainRouteId;
}
#OneToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER, mappedBy = "trainRoute")
public List<TrainRouteStationData> getTrainRouteStations() {
return this.trainRouteStations;
}
public void setTrainRouteStations(List<TrainRouteStationData> trainRouteStations) {
this.trainRouteStations = trainRouteStations;
}
Class: TrainRouteStation
#Basic(optional = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
#Column(name = "train_route_station_id", unique = true, nullable = false)
public Long getTrainRouteStationId() {
return this.trainRouteStationId;
}
public void setTrainRouteStationId(Long trainRouteStationId) {
this.trainRouteStationId = trainRouteStationId;
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "train_route_id", nullable = false)
public TrainRouteData getTrainRoute() {
return this.trainRoute;
}
JPQL :"SELECT s FROM TrainRouteData t inner join TrainRouteStationData s ON t.trainRouteId=s.trainRoute where s.stationSeqN >=1 AND s.stationSeqN <=3 AND t.trainRouteDescX='Test1-Test2' order by s.stationSeqN asc"
Native SQL : SELECT train_route_station.* FROM train_route inner join train_route_station ON train_route.train_route_id=train_route_station.train_route_id where train_route_station.station_seq_n >= 1 AND train_route_station.station_seq_n <= 3 AND train_route.train_route_desc_x='Test1-Test2' order by train_route_station.station_seq_n asc
And it throw an error:
Exception Description: Object comparisons can only be used with OneToOneMappings. Other mapping comparisons must be done through query keys or direct attribute level comparisons.
Mapping: [org.eclipse.persistence.mappings.DirectToFieldMapping[trainRouteId-->train_route.train_route_id]]
Expression: [
Query Key trainRouteId
How can I change that query?
That's not how joins work in JPQL.
The correct query is
select s from TrainRouteData t inner join t.trainRouteStations s
where s.stationSeqN >= 1
and s.stationSeqN <= 3
and t.trainRouteDescX = 'Test1-Test2'
order by s.stationSeqN asc

Problems with a JPA query

I have a problem when performing a query in an HQL.
ORM
Persona
#Entity
#Table(name = "persona")
#Inheritance(strategy = InheritanceType.JOINED)
#DynamicUpdate
#SelectBeforeUpdate(value = false)
#SelectBeforeUpdate(value = false)
#NamedQueries({
#NamedQuery(name = "PersonasByRfc", query = "FROM Persona p WHERE p.rfc = :rfc "),
#NamedQuery(name = "PersonasPorTipoPersona", query = "FROM Persona p WHERE p.tipoPersona = :tipoPersona "),
#NamedQuery(name = "PersonaByClienteId", query = " SELECT c.persona FROM Cliente c WHERE c.clienteId = :clienteId "),
#NamedQuery(name = "PersonaMoralActiva", query = "SELECT c.persona FROM Cliente c WHERE c.persona.regimenFiscal = 'MORAL' AND c.estatus = 'ACTIVO' ")
})
public class Persona extends CommonBusinessProperties {
private static final long serialVersionUID = 2846894501470704239L;
private Long personaId;
private CatTipoPersona tipoPersona;
private String descripcionTipoPersona;
private String nombres;
private String apellidoMaterno;
private String apellidoPaterno;
private RegimenFiscal regimenFiscal;
private Nacionalidad nacionalidad;
private String rfc;
private String curp;
private Genero genero;
private Date fechaNacimiento;
private Boolean esCliente;
private Boolean esContratante;
private Boolean esPagador;
private Boolean esMontoPagar;
private BigDecimal montoPagar;
private Boolean esPorcentajePagar;
private String porcentajePagar;
private String origenPersona;
private String parentesco;
private Parentesco tranParentesco;
private Cliente cliente;
private ExpedientePersona expedientePersona;
private List<Domicilio> domicilios = new ArrayList<>(0);
private List<Telefono> telefonos = new ArrayList<>(0);
private List<Correo> correos = new ArrayList<>(0);
/**
* Constructor <br>
* Crea una nueva instancia de Persona. <br>
*
* #author Orlando Adrián Ramos Galván (oramos#legosoft.com.mx, orlandoa.ramos#outlook.com)<br>
*/
public Persona() {
super();
}
/**
* Constructor <br>
* Crea una nueva instancia de Persona. <br>
*
* #param personaId
* #author Orlando Adrián Ramos Galván (oramos#legosoft.com.mx, orlandoa.ramos#outlook.com)<br>
*/
public Persona(Long personaId) {
super();
this.personaId = personaId;
}
/**
* Constructor <br>
* Crea una nueva instancia de Persona. <br>
*
* #param personaBuilder
* #author Orlando Adrián Ramos Galván (oramos#legosoft.com.mx, orlandoa.ramos#outlook.com)<br>
*/
public Persona(PersonaBuilder personaBuilder) {
this.tipoPersona = personaBuilder.getTipoPersona();
this.descripcionTipoPersona = personaBuilder.getDescripcionTipoPersona();
this.nombres = personaBuilder.getNombresORazonSocial();
this.apellidoMaterno = personaBuilder.getApellidoMaterno();
this.apellidoPaterno = personaBuilder.getApellidoPaterno();
this.setRegimenFiscal(personaBuilder.getRegimenFiscal());
this.setNacionalidad(personaBuilder.getNacionalidad());
this.setRfc(personaBuilder.getRfc());
this.curp = personaBuilder.getCurp();
this.genero = personaBuilder.getGenero();
this.fechaNacimiento = personaBuilder.getFechaNacimiento();
this.esCliente = personaBuilder.getEsCliente();
this.esContratante = personaBuilder.getEsContratante();
this.esPagador = personaBuilder.getEsPagador();
this.esMontoPagar = personaBuilder.getEsMontoPagar();
this.montoPagar = personaBuilder.getMontoPagar();
this.esPorcentajePagar = personaBuilder.getEsPorcentajePagar();
this.porcentajePagar = personaBuilder.getPorcentajePagar();
this.domicilios = personaBuilder.getDomicilios();
this.telefonos = personaBuilder.getTelefonos();
this.correos = personaBuilder.getCorreos();
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "persona_id", unique = true, nullable = false, updatable = false)
public Long getPersonaId() {
return this.personaId;
}
public void setPersonaId(Long personaId) {
this.personaId = personaId;
}
#ManyToOne(fetch = FetchType.EAGER, targetEntity = CatTipoPersona.class)
#JoinColumn(name = "tipo_persona_id")
#Fetch(FetchMode.SELECT)
public CatTipoPersona getTipoPersona() {
return this.tipoPersona;
}
public void setTipoPersona(CatTipoPersona tipoPersona) {
this.tipoPersona = tipoPersona;
}
#Column(name = "tipo_persona", length = 50)
public String getDescripcionTipoPersona() {
return this.descripcionTipoPersona;
}
public void setDescripcionTipoPersona(String tipoPersona) {
this.descripcionTipoPersona = tipoPersona;
}
#Column(name = "origen_persona", length = 50)
public String getOrigenPersona() {
return this.origenPersona;
}
#Column(name = "nombres", length = 100)
public String getNombresORazonSocial() {
return this.nombres;
}
public void setNombresORazonSocial(String nombres) {
this.nombres = nombres;
}
#Column(name = "apellido_materno", length = 100)
public String getApellidoMaterno() {
return this.apellidoMaterno;
}
public void setApellidoMaterno(String apellidoMaterno) {
this.apellidoMaterno = apellidoMaterno;
}
#Column(name = "apellido_paterno", length = 100)
public String getApellidoPaterno() {
return this.apellidoPaterno;
}
public void setApellidoPaterno(String apellidoPaterno) {
this.apellidoPaterno = apellidoPaterno;
}
#Transient
public String getNombreCompleto() {
return this.nombres + " " + this.apellidoMaterno + " " + this.apellidoPaterno;
}
#Column(name = "regimen_fiscal", length = 100)
#Enumerated(EnumType.STRING)
public RegimenFiscal getRegimenFiscal() {
return this.regimenFiscal;
}
public void setRegimenFiscal(RegimenFiscal regimenFiscal) {
this.regimenFiscal = regimenFiscal;
}
#Column(name = "nacionalidad", length = 100)
#Enumerated(EnumType.STRING)
public Nacionalidad getNacionalidad() {
return this.nacionalidad;
}
public void setNacionalidad(Nacionalidad nacionalidad) {
this.nacionalidad = nacionalidad;
}
#Column(name = "rfc", length = 13)
public String getRfc() {
return this.rfc;
}
public void setRfc(String rfc) {
this.rfc = rfc;
}
#Column(name = "curp", length = 45)
public String getCurp() {
return this.curp;
}
public void setCurp(String curp) {
this.curp = curp;
}
#Column(name = "genero", length = 1)
#Convert(converter = GeneroConverter.class)
public Genero getGenero() {
return this.genero;
}
public void setGenero(Genero genero) {
this.genero = genero;
}
#Temporal(TemporalType.DATE)
#Column(name = "fecha_nacimiento", length = 10)
public Date getFechaNacimiento() {
return this.fechaNacimiento;
}
public void setFechaNacimiento(Date fechaNacimiento) {
this.fechaNacimiento = fechaNacimiento;
}
#Column(name = "es_cliente")
public Boolean isCliente() {
return this.esCliente;
}
public void setIsCliente(Boolean esCliente) {
this.esCliente = esCliente;
}
#Column(name = "es_contratante")
public Boolean esContratante() {
return this.esContratante;
}
public void setEsContratante(Boolean esContratante) {
this.esContratante = esContratante;
}
#Column(name = "es_pagador")
public Boolean isEsPagador() {
return this.esPagador;
}
public void setEsPagador(Boolean esPagador) {
this.esPagador = esPagador;
}
#Column(name = "es_monto_pagar")
public Boolean getEsMontoPagar() {
return this.esMontoPagar;
}
public void setEsMontoPagar(Boolean esMontoPagar) {
this.esMontoPagar = esMontoPagar;
}
#Column(name = "monto_pagar", precision = 16, scale = 4)
public BigDecimal getMontoPagar() {
return this.montoPagar;
}
public void setMontoPagar(BigDecimal montoPagar) {
this.montoPagar = montoPagar;
}
#Column(name = "es_porcentaje_pagar")
public Boolean getEsPorcentajePagar() {
return this.esPorcentajePagar;
}
public void setEsPorcentajePagar(Boolean esPorcentajePagar) {
this.esPorcentajePagar = esPorcentajePagar;
}
#Column(name = "porcentaje_pagar", length = 6)
public String getPorcentajePagar() {
return this.porcentajePagar;
}
public void setPorcentajePagar(String porcentajePagar) {
this.porcentajePagar = porcentajePagar;
}
public void setOrigenPersona(String origenPersona) {
this.origenPersona = origenPersona;
}
#OneToOne(fetch = FetchType.EAGER, mappedBy = "persona", targetEntity = ExpedientePersona.class, optional = true)
protected ExpedientePersona getExpedientePersona() {
return this.expedientePersona;
}
protected void setExpedientePersona(ExpedientePersona expedientePersonas) {
this.expedientePersona = expedientePersonas;
}
/**
* #return parentesco
*/
#Column(name = "parentesco", length = 50)
public String getParentesco() {
return parentesco;
}
/**
* #param parentesco
*/
public void setParentesco(String parentesco) {
this.parentesco = parentesco;
}
#OneToOne(fetch = FetchType.EAGER, mappedBy = "persona", targetEntity = Cliente.class, cascade = {
CascadeType.MERGE, CascadeType.DETACH })
#Fetch(FetchMode.SELECT)
public Cliente getCliente() {
return this.cliente;
}
public void setCliente(Cliente cliente) {
this.cliente = cliente;
}
/**
* #return si la persona esta relacionada al contratante y es una familiar este campo idnica que
* parentesco tienen.
*/
#Transient
public Parentesco getTranParentesco() {
return tranParentesco;
}
/**
* #param tranParentesco
*/
public void setTranParentesco(Parentesco tranParentesco) {
this.tranParentesco = tranParentesco;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "persona", targetEntity = Domicilio.class, cascade = {
CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE, CascadeType.REFRESH })
#Fetch(FetchMode.SELECT)
#OrderBy
protected List<Domicilio> getDomicilios() {
return this.domicilios;
}
protected void setDomicilios(List<Domicilio> domicilios) {
this.domicilios = domicilios;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "persona", targetEntity = Telefono.class, cascade = {
CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE, CascadeType.REFRESH })
#Fetch(FetchMode.SELECT)
#OrderBy
protected List<Telefono> getTelefonos() {
return this.telefonos;
}
protected void setTelefonos(List<Telefono> telefonos) {
this.telefonos = telefonos;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "persona", targetEntity = Correo.class, cascade = {
CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE, CascadeType.REFRESH })
#Fetch(FetchMode.SELECT)
#OrderBy
protected List<Correo> getCorreos() {
return this.correos;
}
protected void setCorreos(List<Correo> correos) {
this.correos = correos;
}
}

JPA with Hibernate: .... org.hibernate.QueryException: illegal attempt to dereference collection

I have a #ManyToMany relationship described as follows:
FOO
-----------------------
FOO_ID
........
FOO_BARS
--------------------
BAR_ID
FOO_ID
BAR
--------------------
BAR_ID
.......
#Entity
#Table(name = "FOO")
public class FOO
{
#Id
#SequenceGenerator(....)
#GeneratedValue(...)
#Column(name = "FOO_ID", unique = true, nullable = false, precision = 10)
private int fooId;
public int getFooId()
{
......
}
public void setFooId(final int fooId)
{
......;
}
.....
##ManyToMany()
#JoinTable(name = "FOO_BARS", joinColumns = { #JoinColumn(name = "FOO_ID", nullable = false) }, inverseJoinColumns = { #JoinColumn(name = "BAR_ID", nullable = false) })
private List<Bar> bars;
public List<Bar> getBars()
{
......
}
public void setBars(final List<Bar> bars)
{
......
}
public Bar addBar(Bar value)
{
.....
}
......
}
#Entity
#Table(name = "BAR")
public class Bar
{
#Id
#SequenceGenerator(...)
#GeneratedValue(...)
#Column(name = "BAR_ID", unique = true, nullable = false, precision = 9)
private int barid;
public int getBard()
{
.....
}
public void setBarId(final int barId)
{
.....
}
.....
#ManyToMany(mappedBy = "bar")
private List<Foo> foos;
public List<Foo> getFoos()
{
....
}
public void setFooList(final List<Foo> foos)
{
....
}
public Foo addFoo(final Foo foo)
{
.......
}
.....
}
I have an sql query which I can successfully run to select ALL foos matching a list of provided barIds. This changes according to the provided barIds but is of the format:
SELECT f.* FROM foo f
WHERE
.....
AND f.foo_id IN
(
SELECT fb.foo_id FROM foo_bars fb
WHERE fb.bar_id IN ( 69, 332)
GROUP BY fb.foo_id
HAVING COUNT(DISTINCT fb.bar_id) = 2
);
As entitities don't use a linking table, my issue is in translating this into a query to run using hibernate syntax.
I have tried the following:
SELECT f FROM Foo AS f
WHERE
.....
AND f.fooId IN
(
SELECT b.foos.fooId FROM f.bars b
WHERE b.barid IN (:barids)
GROUP BY b.foos.fooId
HAVING COUNT ( DISTINCT b.barid ) = 2
)
This results in the following error.
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.QueryException: illegal attempt to dereference collection [bar2_.BAR_ID.foos] with element property reference [fooId]
Any help would be greatly appreciated.