I have the following hibernate query string:
String queryString = "select \r\n" +
"cms.my_status_id as 'myStatusId',\r\n" +
"cms.status_label as 'statusLabel',\r\n" +
"csl.status_id as 'companyStatusLabel'\r\n" +
"from "+client+".corresponding_status cms \r\n" +
"join "+client+".company_status_label csl on csl.status_id = cms.my_status_id";
My Corresponding Entity is:
#Entity(name = "corresponding_status")
#Table(name = "corresponding_status")
public class CorrespondingStatus implements Serializable {
#Id
#JsonProperty
#Column(name = "my_status_id")
private Integer myStatusId;
// varchar(255)
#JsonProperty
#Column(name = "status_label")
private String statusLabel;
#JsonProperty
#Transient
private String companyStatusLabel;
However when I run the query I get:
Column 'my_status_id' not found
even though it is definitely in the DB.
What is the issue here?
In HQL you must use properties instead of database column names. Change your HQL to
String queryString = "select \r\n" +
"cms.myStatusId as 'myStatusId',\r\n" +
"cms.statusLabel as 'statusLabel',\r\n" +
"csl.status_id as 'companyStatusLabel'\r\n" +
"from "+client+".corresponding_status cms \r\n" +
"join "+client+".company_status_label csl with csl.status_id = cms.myStatusId";
EDIT:
You probably need to change company_status_label entity accordingly
EDIT2: Changed to WITH
Instead of building JPA queries by hand, I would suggest the criteria API. Your query above would change from:
String queryString = "select \r\n" +
"cms.my_status_id as 'myStatusId',\r\n" +
"cms.status_label as 'statusLabel',\r\n" +
"csl.status_id as 'companyStatusLabel'\r\n" +
"from "+client+".corresponding_status cms \r\n" +
"join "+client+".company_status_label csl on csl.status_id = cms.my_status_id";
to something akin to:
Session session = HibernateUtil.getHibernateSession();
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<Entity> cq = cb.createQuery(Entity.class);
Root<Entity> root = cq.from(Entity.class);
cq.select(root);
Query<Entity> query = session.createQuery(cq);
List<Entity> results = query.getResultList();
Related
Why does this HQL throw me the unexpected token? I've searched elsewhere for answers, but I can't really see where's the error in my syntax (it's probably a hql syntax error).
String hql = "from employee";
if(jCheckBox1.isSelected()){ //NAME
hql = "from employee where employee.name = "+nameField.getText();
if(jCheckBox2.isSelected()){
int value = (Integer)ageSpinner.getValue();//AGE
hql = "from employee where employee.name = "+nameField.getText() + " and where employee.age = "+value;
if(jCheckBox3.isSelected()){//ADDRESS
hql = "from employee where employee.name = "+nameField.getText() + " and where employee.age = "+value+" and where employee.address = " + addressField.getText();
if(jCheckBox4.isSelected()){//SALARY
hql = "from employee where employee.name = "+nameField.getText() + " and where employee.age = "+value+" and where employee.address = " + addressField.getText()+" and where employee.salary = " + jSlider1.getValue();
}
}
}
}
If someone was wondering what the actual error was: it was the punctuation.
I've written where employee.name = value instead of where employee.name = 'value'
I want to have a Spring Boot #Query in JpaRepository which returns me entities with a set of other entities. I know that I can use findAll() method, and then take only those rows that I'm interested in, but I think that this is much slower. The problem is that my entity Booster contains a Set of other entities Boost, and when i try to query it, I get an error. So, this is my Query:
#Query( "select new app.model.Booster(" +
" B.id, " +
" B.active, " +
" B.games, " +
" B.ownerAccount, " +
" B.boosts, " +
" B.boosterNickname, " +
" B.additionalInformation) " +
"from " +
" Booster B " +
" left join Boost Bo on B.id = Bo.boostingAccount.id " +
"where " +
" B.games like %?1% " +
" and Bo.finished = true " +
"group by " +
" B.id")
List<Booster> findBoostersForOverview(String game);
These are my entity classes:
#Data
#Entity(name = "Booster")
public class Booster {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private boolean active;
private String games;
#OneToOne(mappedBy = "boosterAccount", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Account ownerAccount;
#OneToMany(mappedBy = "boostingAccount", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Boost> boosts;
private String boosterNickname;
private String additionalInformation;
#Data
#Entity(name = "Boost")
public class Boost {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id",nullable=false,unique=true)
private long id;
private Date dateCreated;
private Date dateFinished;
private Date dateLastModification;
private boolean finished;
private boolean paused;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "boosted_account_id", referencedColumnName = "id")
private Account boostedAccount;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "boosting_account_id", referencedColumnName = "id")
private Booster boostingAccount;
#OneToMany(mappedBy = "boost", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Game> games;
private String game;
private String additionalInformation;
private String server;
This is what console shows:
Hibernate:
select
booster0_.id as col_0_0_,
booster0_.active as col_1_0_,
booster0_.games as col_2_0_,
booster0_.id as col_3_0_,
. as col_4_0_,
booster0_.booster_nickname as col_5_0_,
booster0_.additional_information as col_6_0_
from
booster booster0_
//HERE IS SOME MORE LOGS THAT ARE UNNECESSARY HERE
And this is error i get:
java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '. as col_4_0_, booster0_.booster_nickname as col_5_0_, booster0_.additional_info' at line 1
I know that I can query without Set of Boost, and then in another query get specific Boosts, but in my app there will be a lot of SQL and my code will turn to spaghetti. Is there a simple way to solve my problem?
Can you add the following to your repository without any #Query annotation and see?
List<Booster> findByGamesLikeAndBoostsFinishedIsTrue(String game);
The problem here, you are using GROUP BY. When you are using Group By you have use aggregate functions (COUNT, MAX, MIN, SUM, AVG) to group the result-set by one or more columns in the select column. Aggregate functions are mandatory when using GROUP BY function.
In your case, I hope Group By is not required. Modify your code like below.
#Query( "select new app.model.Booster(" +
" B.id, " +
" B.active, " +
" B.games, " +
" B.ownerAccount, " +
" B.boosts, " +
" B.boosterNickname, " +
" B.additionalInformation) " +
"from " +
" Booster B " +
" left join Boost Bo on B.id = Bo.boostingAccount.id " +
"where " +
" B.games like %?1% " +
" and Bo.finished = true")
List<Booster> findBoostersForOverview(String game);
I have this structure:
public enum SaleItemType {
CRUISE,
DAILY_HOSTING
}
public class Estimate {
...
private List<SaleItemType> interestedSaleItemTypes;
#Column(name = "sale_item_type")
#CollectionTable(name = "estimate_sale_item_type", joinColumns = #JoinColumn(name = "estimate_id"))
#ElementCollection(targetClass = SaleItemType.class)
#Enumerated(EnumType.STRING)
public List<SaleItemType> getInterestedSaleItemTypes() {
return interestedSaleItemTypes;
}
}
And i'm trying to do a simple query:
String q = "FROM " + Estimate.class.getSimpleName() + " e" + " WHERE e.interestedSaleItemTypes IN :a";
TypedQuery<Estimate> query1 = getEm().createQuery(q, Estimate.class);
query1.setParameter("a", EnumSet.of(SaleItemType.CRUISE));
query1.getResultList();
I'm getting this query(and error) on the log:
DEBUG SQL:92 - select estimate0_.id as id1_25_, estimate0_.average_ticket as average_2_25_, estimate0_.description as descript3_25_, estimate0_.end_date as end_date4_25_, estimate0_.pax_quantity as pax_quan5_25_, estimate0_.start_date as start_da6_25_ from estimate estimate0_ cross join estimate_sale_item_type interested1_ where estimate0_.id=interested1_.estimate_id and (. in (?))
DEBUG SqlExceptionHelper:124 - could not extract ResultSet [n/a]
org.postgresql.util.PSQLException: No value specified for parameter 1.
Why hibernate is doing this query?
Im using Hibernate 5.1 Final
The IN expression can be used to test if a value is in a collection but interestedSaleItemTypes is not a simple value but itself a collection. Therefore use MEMBER OF:
String q = "FROM Estimate e WHERE :a MEMBER OF e.interestedSaleItemTypes";
TypedQuery<Estimate> query1 = getEm().createQuery(q, Estimate.class);
query1.setParameter("a", SaleItemType.CRUISE);
Did you try to put parenthesis in your IN clause?
I don't know if it's required, but in all tutorials that I found, always had the parenthesis. http://www.postgresqltutorial.com/postgresql-in/
Also, as the IN clause is expecting a list of values you can use the setParameterList instead of setParameter.
Try this:
String q = "FROM " + Estimate.class.getSimpleName() + " e" + " WHERE e.interestedSaleItemTypes IN (:a)";
TypedQuery<Estimate> query1 = getEm().createQuery(q, Estimate.class);
query1.setParameterList("a", EnumSet.of(SaleItemType.CRUISE));
query1.getResultList();
Using Postgres Tables created by Ebean, I would like to query these tables with a hand-written statement:
SELECT r.name,
r.value,
p.name as param1,
a.name as att1,
p2.name as param2,
a2.name as att2
FROM compatibility c
JOIN attribute a ON c.att1_id = a.id
JOIN attribute a2 ON c.att2_id = a2.id
JOIN PARAMETER p ON a.parameter_id = p.id
JOIN PARAMETER p2 ON a2.parameter_id = p2.id
JOIN rating r ON c.rating_id = r.id
WHERE p.problem_id = %d
OR p2.problem_id = %d
Each of the joined tables represent one of my model classes.
The query executes fine, but I don't know how I would proceed:
How do I even execute the query using Play 2.2. and Ebean?
How can I map this query to an iterable object? Do I need to create a Model class which contains all the fields from the query, or can I use some sort of HashMap?
How can I parameterize the query in a safe way?
To execute this query you need to use RawSql class. You will also have to create class to which results will be casted.
Here is a code of exemplary result class:
import javax.persistence.Entity;
import com.avaje.ebean.annotation.Sql;
#Entity
#Sql
public class Result {
String name;
Integer value;
String param1;
String param2;
String att1;
String att2;
}
And example of executing this query:
String sql
= " SELECT r.name,"
+ " r.value,"
+ " p.name as param1,"
+ " a.name as att1,"
+ " p2.name as param2,"
+ " a2.name as att2"
+ " FROM compatibility c"
+ " JOIN attribute a ON c.att1_id = a.id"
+ " JOIN attribute a2 ON c.att2_id = a2.id"
+ " JOIN PARAMETER p ON a.parameter_id = p.id"
+ " JOIN PARAMETER p2 ON a2.parameter_id = p2.id"
+ " JOIN rating r ON c.rating_id = r.id"
+ " WHERE p.problem_id = %d"
+ " OR p2.problem_id = %d"
RawSql rawSql =
RawSqlBuilder
.parse(sql)
.columnMapping("r.name", "name")
.columnMapping("r.value", "value")
.create();
Query<Result> query = Ebean.find(Result.class);
query.setRawSql(rawSql)
.where().gt("amount", 10);
List<Result> list = query.findList();
I have following entities, and need to update a field that is in a specific field and its removedDate is null. But the following code returns exception.
#Entity
public class Cart implements Serializable {
#Id
#GeneratedValue
private Long id;
#OneToMany(cascade = CascadeType.ALL)
#LazyCollection(LazyCollectionOption.FALSE)
private List<CartItem> items;
public Cart() {
}
getters and setters
}
#Entity
public class CartItem {
#Id
#GeneratedValue
private long id;
#ManyToOne
private Product pro;
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
private Date addedDate;
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
private Date removedDate;
getters and setters
}
Hibernate Code 1
Query query = session.createQuery("UPDATE CartItem SET removedDate = :currentDateTime "
+ " WHERE CartItem.id IN (Select Cart.items.id From Cart"
+ " WHERE Cart.id = :cartId"
+ " AND Cart.items.pro.id = :pro"
+ " AND Cart.items.removedDate is null)");
query.setParameter("currentDateTime", dt.getCurrentDateTime());
query.setParameter("cartId", cartId);
query.setParameter("pro", proId);
int result = query.executeUpdate();
Exception of Code 1
SEVERE: org.hibernate.QueryException: Unable to resolve path [CartItem.id], unexpected
token [CartItem] [UPDATE com.myproject.CartItem SET removedDate =
:currentDateTime WHERE CartItem.id IN (Select Cart.items.id From
com.myproject.Cart WHERE Cart.id = :cartId AND cart.items.pro.id = :proId
AND Cart.items.removedDate is null))]
at org.hibernate.hql.internal.ast.tree.IdentNode.resolveAsNakedComponentPropertyRefLHS(IdentNode.java:245)
at org.hibernate.hql.internal.ast.tree.IdentNode.resolve(IdentNode.java:110)
at org.hibernate.hql.internal.ast.tree.DotNode.resolveFirstChild(DotNode.java:177)
at org.hibernate.hql.internal.ast.HqlSqlWalker.lookupProperty(HqlSqlWalker.java:577)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.addrExpr(HqlSqlBaseWalker.java:4719)
Hibernate Code 2
Query query = session.createQuery("UPDATE CartItem SET removedDate = :currentDateTime "
+ " WHERE id IN (Select items.id From Cart"
+ " WHERE id = :CartId"
+ " AND items.pro.id = :pro"
+ " AND items.removedDate is null)");
Exception of Code 2
SEVERE: org.hibernate.QueryException: illegal attempt to dereference collection
[{synthetic-alias}{non-qualified-property-ref}items] with element property
reference [id] [UPDATE com.myproject.CartItem SET removedDate =
:currentDateTime WHERE id IN (Select items.id From com.myproject.Cart WHERE
id = :cartId AND items.pro.id = :pro AND items.removedDate is null)]
at org.hibernate.hql.internal.ast.tree.DotNode$1.buildIllegalCollectionDereferenceException(DotNode.java:68)
at org.hibernate.hql.internal.ast.tree.DotNode.checkLhsIsNotCollection(DotNode.java:550)
at org.hibernate.hql.internal.ast.tree.DotNode.resolve(DotNode.java:246)
at org.hibernate.hql.internal.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:118)
at org.hibernate.hql.internal.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:114)
Why don't you make your association bidirectional?
Add this to your CartItem entity:
#ManyToOne
private Cart cart;
Set the mappedBy on your cartItem fied in Cart:
#OneToMany(cascade = CascadeType.ALL, mappedBy="cart")
#LazyCollection(LazyCollectionOption.FALSE)
private List<CartItem> items;
The resulting HQL would be much simpler (and should work):
"UPDATE CartItem c SET c.removedDate = :currentDateTime "
+ " WHERE c.cart.id = :cartId"
+ " AND c.pro.id = :pro"
+ " AND c.removedDate is null"
Try this by adding an alias in the inner select query.
Query query = session.createQuery("UPDATE CartItem SET removedDate = :currentDateTime "
+ " WHERE id IN (Select cart.items.id From Cart cart"
+ " WHERE cart.id = :CartId"
+ " AND cart.items.pro.id = :pro"
+ " AND cart.items.removedDate is null)");
EDIT 2
I did a bit of reading and found out that the object.collection.id works only for a 1:1 or an N:1 relation, not for a 1:N relation, which is what you have. Try this.
SELECT items.id
FROM Cart cart
LEFT JOIN cart.items items
WHERE cart.id = :CartId AND items.pro.id = :pro AND items.removedDate is null
Here is more info, info, info
Thanks to Hrishikesh's comment, I found the answer by providing the exact SQLQuery.
UPDATE cartItem SET removedDate = :currentDateTime"
+ " WHERE pro = :pro"
+ " AND removedDate IS NULL"
+ " AND id IN
( SELECT items_id from Cart_CartItem WHERE Cart_id = :CartId)
Try that:
Query query = session.createQuery("UPDATE CartItem SET removedDate = :currentDateTime "
+ " WHERE id IN (Select ci.id From Cart c inner join c.items ci"
+ " WHERE c.id = :cartId"
+ " AND ci.pro.id = :pro"
+ " AND ci.removedDate is null)");