I am using Hibernate/JPA to execute native MySql queries. I want to get the value of the counter.
For example the following query crash:
"SELECT sizeList FROM myCounter WHERE myColA=?1 AND myColB=?2 AND LIMIT 1"
Error:
java.lang.IllegalArgumentException: Parameter with that name [1] did not exist
Sources:
Method:
#Override
public Long getSizeList(String myColA, String myColB) {
Query q = em.createNativeQuery("MyCounter.getSizeList");
q.setParameter(1, myColA);
q.setParameter(2, myColB);
return (Long) q.getSingleResult();
}
Entity:
#Entity
#Table(name = "myCounter")
#XmlRootElement
#NamedNativeQueries({
#NamedNativeQuery(name = "MyCounter.getSizeList", query = "SELECT sizeList FROM myCounter WHERE myColA=?1 AND myColB=?2 AND LIMIT 1", resultClass = MyCounter.class)})
public class MyCounter implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected MyCounterPK myCounterPK;
#Column(name = "sizeList")
private BigInteger sizeList;
public PostListCounterPTTESLTTT() {
}
...
public BigInteger getSizeList() {
return sizeList;
}
}
Embeddable:
#Embeddable
public class MyCounterPK implements Serializable {
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 255)
#Column(name = "myColA")
private String myColA;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 50)
#Column(name = "myColB")
private String myColB;
public MyCounterPK() {
}
...
}
Does anyone know how to use setParameter() in this case ?
I tried with:
//case 1:
"SELECT sizeList FROM myCounter WHERE myColA=?1 AND myColB=?2 AND LIMIT 1"
q.setParameter(1, myColA); //the same error
//case 2:
"SELECT sizeList FROM myCounter WHERE myColA=?1 AND myColB=?2 AND LIMIT 1"
q.setParameter("1", myColA); //the same error
//case 3:
"SELECT sizeList FROM myCounter WHERE myColA=:myColA AND myColB=:myColB AND LIMIT 1"
q.setParameter("myColA", myColA); //the same error
Instead of
Query q = em.createNativeQuery("MyCounter.getSizeList");
Try this:
Query q = em.createNamedQuery("MyCounter.getSizeList");
Related
I am working on a spring boot project and using JPA for querying the database with Entity manager.
i.e.
Query query = entityManager.createNativeQuery("SELECT * FROM TABLE_NAME WHERE ID = 1"); // SUPPOSE
List<Object[]> result = (List<Object[]>) query.getResultList();
now after this what I want to achieve here is creating an Object of that corresponding result.
i.e. ResultObject obj = (ResultObject) result.get(0);
// here ResultObject is user defined.
but this type of casting is not possible directly.
so what I am currently doing is:
ResultObject obj = new ResultObject();
obj.setArribute1((String) obj[0]);
obj.setArribute2((Integer) obj[1]);
...
and on average i will be having 15 attributes per object. so its really tiresome...
I have tried using:
List<ResultObject> obj = (List<ResultObject>)query.getResultList();
but doesn't work.
Either use ConstructorResult (JPA) or ResultTransformer (Hibernate) or QLRM.
ConstructorResult is JPA standard and you have to create a Annotation with the column mapping:
#SqlResultSetMapping(
name = "BookValueMapping",
classes = #ConstructorResult(
targetClass = BookValue.class,
columns = {
#ColumnResult(name = "id", type = Long.class),
#ColumnResult(name = "title"),
#ColumnResult(name = "version", type = Long.class),
#ColumnResult(name = "authorName")}))
From https://thorben-janssen.com/result-set-mapping-constructor-result-mappings/
And ResultTransformer is Hibernate proprietary and you must use the Hibernate session:
List<PersonSummaryDTO> dtos = session.createNativeQuery(
"SELECT p.id as \"id\", p.name as \"name\" " +
"FROM Person p")
.setResultTransformer( Transformers.aliasToBean( PersonSummaryDTO.class ) )
.list();
From https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#sql-dto-query
Or QLRM is a library that maps the result to a DTO using the constructor:
JpaResultMapper jpaResultMapper = new JpaResultMapper();
Query q = em.createNativeQuery("SELECT ID, NAME FROM EMPLOYEE");
List<EmployeeTO> list = jpaResultMapper.list(q, EmployeeTO.class);
https://github.com/72services/qlrm
if you have set up a DatabaseConfig like this tutorial then you can simply create a class that you annotate with #Entity and #Table(name = "yourDatabaseTableName") Don't forget to define:
#Id
#Column(name = "ID")
private Long id;
and annotate all your colums with #Column(name = "databaseColumnName")
Then, create an interface that you annotate with #Repository which extends JpaRepository<YourEntityClass, Long>where the Long-parameter is the type you've given to the id-variable of your Entity.
Now you can use simple JPA-methodqueries like findAll() or you can create your own JPQL-queries like:
#Query("SELECT e FROM Entity e "
+ "WHERE e.id = :id")
Optional<Entity> findById(#Param("id") Long id);
It's even possible to use NativeQueries in this way:
#Query(value = "SELECT e FROM Entity e "
+ "WHERE e.id = :id",
nativeQuery = true)
Optional<Entity> findById(#Param("id") Long id);
Id suggest creating a POJO that can be mapped to your table you're retrieving values from:
#Entity
#Table(name = "MyTable")
#NamedQueries({
#NamedQuery(name = "MyTable.findAll", query = "SELECT m FROM MyTable m")})
public class MyTable implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Basic(optional = false)
#Column(name = "name")
private String name;
#Basic(optional = false)
#Column(name = "display_name")
private String displayName;
public MyTable() {
}
public MyTable(Integer id) {
this.id = id;
}
public MyTable(Integer id, String name, String displayName) {
this.id = id;
this.name = name;
this.displayName = displayName;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
#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 MyTable)) {
return false;
}
MyTable other = (MyTable ) 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 "MyTable[ id=" + id + " ]";
}
}
Obviously fill in the fields as you need with the corresponding database datatype repersentation.
Notice how i have NamedQueries we can now take advantage of those named queries to do our fetches
TypedQuery<MyTable> query = entityManager.createNamedQuery("MyTable.findAll", MyTable.class);
List<MyTable> results = query.getResultList();
this will do all the casting and conversions for you. You can add all the named queries you want.
https://www.objectdb.com/java/jpa/query/named
UPDATE
If you need to dynamically create a query you can do the following:
String query = "SELECT m FROM MyTable m Where m.id =:id and m.name=:name";
///modify the query as needed based off of other conditions)
TypedQuery<MyTable > query = em.createQuery(query, MyTable .class);
query.setParameter("id", id);
query.setParameter("name", name);
List<MyTable> results = query.getResultList();
https://www.objectdb.com/java/jpa/query/api
trying to run a native query however I'm getting The column name sb_modelid is not valid. when attempting to map the return object to my model object in java? I have verified all the column names are correct.
1) Why is it referring to my column name as sb_modelid and not sbModelID?
2) Why is not being mapped to my POJO correctly?
Thanks!
Model Object:
package com.dish.wfm.linkingTickets.model.repository;
public class Model {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "sbModelID")
private Long sbModelId;
#Column(name = "modelID")
private String modelID;
#Column(name = "serialNumber")
private String serialNumber;
#Column(name = "serviceContractNumber")
private String serviceContractNumber;
}
Repo:
#Repository
public interface SBModelRepo extends JpaRepository<Model, Long> {
#Query(value = "select m.sbModelID, m.modelID, m.serialNumber, m.serviceContractNumber from sb.Model m where m.modelID = ?1 and m.serialNumber = ?2", nativeQuery = true)
Model findTopByModelIDAndSerialNumber(String modelID, String serialNumber);
}
try {
LOG.debug("Entering readDb at {}",
System.currentTimeMillis());
Session session =
transactionManager.getSessionFactory().getCurrentSession();
Query query = null;
ReturnTrackerEntity rtEntity = null;
List<ReturnTrackerEntity> rtEntityList = null;
query = session.createQuery("SELECT r FROM org.hx.api.returns.model.entity.ReturnTrackerEntity r WHERE r.hxinRefId = :hxinRefId AND r.rtnTyp = :rtnTyp AND r.rtnPrd = :rtnPrd");
if (query != null) {
query.setString("hxinRefId", key.gethxinRefId());
query.setString("rtnTyp", key.getRtnTyp());
query.setString("rtnPrd", key.getRtnPeriod());
LOG.debug("Query Parameters are {} {} {}", key.gethxinRefId(), key.getRtnTyp(), key.getRtnPeriod());
rtEntityList = query.list();
if(rtEntityList != null && !rtEntityList.isEmpty()) {
rtEntity = (ReturnTrackerEntity) query.list().get(0);
}
LOG.debug("Data from readDb at :{}", rtEntity);
}
return rtEntity;
When executing the above method I'm getting following exception;
java.lang.IllegalArgumentException: Parameter hxinRefId does not exist as a named parameter in [SELECT r FROM org.hx.api.returns.model.entity.ReturnTrackerEntity r WHERE r.hxinRefId = :hxinRefId AND r.rtnTyp = :rtnTyp AND r.rtnPrd = :rtnPrd]
I have tried using setParameters still it shows error:
org.hibernate.QueryParameterException: could not locate named parameter [hxinRefId]
This is the enitity class followed by getter setter:
#Entity
#Table(name = "RTN_TRACKER")
#NamedQuery(
name = "ReturnTrackerEntity.getReturnTracker",
query = "SELECT r FROM org.hx.api.returns.model.entity.ReturnTrackerEntity r WHERE r.hxinRefId = :hxinRefId AND r.rtnTyp = :rtnTyp AND r.rtnPrd = :rtnPrd")
public class ReturnTrackerEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID")
private int id;
#Column(name = "HXIN_REF_ID")
private String hxinRefId;
#Column(name = "RTN_TYP")
private String rtnTyp;
#Column(name = "RTN_PRD")
private String rtnPrd;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "LATEST_SAVE_END")
private Date lastSaveEndTmpStmp;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "LATEST_START")
private Date lastStartTmpStmp;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "INSERT_TMSTMP")
private Date insertTmpStmp;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "UPDATE_TMSTMP")
private Date updateTmpStmp;
#Column(name = "STATE_CD")
private String stateCd;
Also I have tried passing only the Entity class name without whole location still getting error.
please help with this stuck for so long in this.
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.
I'm trying to do a select using a join in CriteriaBuilder, but I'm getting this error in Eclipse. How can I fix it?
Hibernate version: hibernate-jpa-2.0-api<br />
Java Version: 1.8
fonte cannot be solved or is not a field
NotificacaoDao.java
#Stateless
public class NotificacaoDao {
#PersistenceContext(unitName = "PostgreSQLDS")
private EntityManager em;
#EJB
private NotificacaoDao NotificacaoDao;
public List<Notificacao> getResultList(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) throws ApplicationException{
try {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Notificacao> cq = cb.createQuery(Notificacao.class);
Metamodel m = em.getMetamodel();
EntityType<Notificacao> Notificacao_ = m.entity(Notificacao.class);
Root<Notificacao> myObj = cq.from(Notificacao_);
Join<Notificacao, Fonte> fontes = myObj.join(Notificacao_.fonte); // HERE I'M GETTING THE ERROR
cq.where(NotificacaoDao.getFilterCondition(cb, myObj, filters));
Predicate filterCondition = NotificacaoDao.getFilterCondition(cb, myObj, filters);
filterCondition = cb.and(filterCondition, cb.equal(myObj.get("excluido"), "N"));
cq.where(filterCondition);
if (sortField != null) {
if (sortOrder == SortOrder.ASCENDING) {
cq.orderBy(cb.asc(myObj.get(sortField)));
} else if (sortOrder == SortOrder.DESCENDING) {
cq.orderBy(cb.desc(myObj.get(sortField)));
}
}
return em.createQuery(cq).setFirstResult(first).setMaxResults(pageSize).getResultList();
} catch(Exception e) {
throw new ApplicationException("myException", e);
}
}
Notificacao.java
#Entity
#Table(name = "tb_notificacao", schema = "indicadores")
#NamedQuery(name = "Notificacao.findAll", query = "SELECT n FROM Notificacao n")
#FilterDef(name="notificacaoNaoExcluido", defaultCondition="excluido = 'N'")
public class Notificacao implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name = "tb_notificacao_codnotificacao_seq", sequenceName = "TB_NOTIFICACAO_CODNOTIFICACAO_SEQ", schema = "indicadores", allocationSize = 1)
#GeneratedValue(generator = "tb_notificacao_codnotificacao_seq")
#Column(name = "codnotificacao", nullable = false)
private Integer codnotificacao;
private String descricao;
private String excluido;
private String nome;
// bi-directional many-to-one association to CargaNotificacao
#OneToMany(mappedBy = "notificacao")
private List<CargaNotificacao> cargaNotificacoes;
// bi-directional many-to-one association to Fonte
#Inject
#ManyToOne
#JoinColumn(name = "codfonte")
private Fonte fonte;
// bi-directional many-to-one association to UsuarioNotificacao
#OneToMany(mappedBy = "notificacao")
#Filter(name="usuarioNaoExcluido", condition="excluido = 'N'")
private List<UsuarioNotificacao> usuarioNotificacoes;
public Notificacao() {
}
// getters and setters
}
Fonte.java
#Entity
#Table(name = "tb_fonte", schema = "indicadores")
#NamedQuery(name = "Fonte.findAll", query = "SELECT f FROM Fonte f")
public class Fonte implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name = "tb_fonte_codfonte_seq", sequenceName = "TB_FONTE_CODFONTE_SEQ", schema = "indicadores", allocationSize = 1)
#GeneratedValue(generator = "tb_fonte_codfonte_seq")
#Column(name = "codfonte", nullable = false)
private Integer codfonte;
private String nome;
// bi-directional many-to-one association to Indicador
#OneToMany(mappedBy = "fonte")
#Filter(name="indicadorNaoExcluido", condition="excluido = 'N'")
private List<Indicador> indicadores;
// bi-directional many-to-one association to Notificacao
#OneToMany(mappedBy = "fonte")
#Filter(name="notificacaoNaoExcluido", condition="excluido = 'N'")
private List<Notificacao> notificacoes;
public Fonte() {
}
// getters and setters
}
Well, on Metamodels there are basically three approaches to use:
Using IDE based metamodel generation tools
Using Static Canonical Metamodel Classes
Using em.getMetamodel() API i.e. the one you are using.
The solution I am proposing for you to use which is closer to what you were doing is on Point 3.
Point 3 Solution :
Replace the below code :
Metamodel m = em.getMetamodel();
EntityType<Notificacao> Notificacao_ = m.entity(Notificacao.class);
Root<Notificacao> myObj = cq.from(Notificacao_);
Join<Notificacao, Fonte> fontes = myObj.join(Notificacao_.fonte); // HERE I'M GETTING THE ERROR
With new code :
Metamodel m = em.getMetamodel();
EntityType<Notificacao> notificacao_ = m.entity(Notificacao.class);
Root<Notificacao> myObj = cq.from(notificacao_);
Join<Notificacao, Fonte> fontes = myObj.join(notificacao_.getSingularAttribute("fonte",Fonte.class));
Points 1 & 2 Solutions
Please note the Notificacao_ must be a class either static or generated and must never be an instance of em.getMetamodel(). Also note in your case before Notificacao_ was a variable instead of a class as shown:
EntityType<Notificacao> Notificacao_ = m.entity(Notificacao.class);
If you need more info, let me know please.