Convert a silmple Mysql to JPQL Queries - mysql

Good Morning everyone, after lookin everwhere, i come to you to ask for a help.
So i have a this mysql query
SELECT * FROM USER WHERE WORPLACE ='TECHNICIAN',
And here is my JQPL query
SELECT U FROM USER U WHERE U.WORPLACE =:+TECHNICIAN
But some how i get this error on Glassfish
java.lang.IllegalStateException: Query argument Technician not found in the list of parameters provided during query execution.
Here is the code of my arraylist on the managed Bean
public List<Users> getListUsers() {
return this.userService.getTechnicians("Technician");
}
So, what do i want specificlly. I want a query that can sort in a table list of user where there workplace are 'Technician'.
Thanks for your help and have a nice day.

In JPQL named query parameters start with a : followed by the name. So, if you want to call your query parameter Technician you need to reference it as :Technician in your query.
You can then call the setParameter method on the Query interface with the parameter name and its value.
Here's an example using your query:
public List<User> getTechnicians(String technician) {
TypedQuery<User> q = getEntityManager().createQuery("SELECT u FROM User u WHERE u.poste =:Technician", User.class );
q.setParameter("Technician", technician);
return q.getResultList();
}

Related

Hibernate3 criteria query selecting too many fields

I want to write a simple query to retrieve a list of USER with a simple restriction on CUSTOMER joined table.
I'm only interested by the USER entity.
If I write it using HPQL :
public List<Users> getAssociatedAdminObs(Integer pCustId) {
Criteria crit = getCriteriaForObsAdmin("USER");
crit.createCriteria("clients").add(Restrictions.eq("idCustomer", pCustId));
return crit.list();
StringBuilder hqlQuery = new StringBuilder().append("select u from Users as u join u.customers as c where c.idCustomer=:idCustomer");
Query q = getSessionAndManageFilter().createQuery(hqlQuery.toString());
q.setInteger("idCustomer", pCustId);
return q.list();
}
The SQL generated only Select all the fields from USER entity, as expected.
Now if I write it through Hibernate criteria API :
public List<Users> getAssociatedAdminObs(Integer pCustId) {
Criteria crit = getSession().createCriteria(Users.class);
crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
crit.createCriteria("customers").add(Restrictions.eq("idCustomer", pCustId));
return crit.list();
}
The SQL generated Select all the fields from USER entity but also from the CUSTOMER entity.
I'm using hibernate-core 3.3.1.GA.
I know I can use projection to work around the issue but my object will be transient, I also validated it works using a subquery to do my restrictions.
But I'm not happy with using workarounds and I do not understand why it would behave differently between the 2 code examples ?
It doesn't make sense to me to select fields outside of the asked entity.

Selecting multiple columns and set it to list of DTOs

I want to get multiple columns from database in a single query and set it to the corresponding DTO object fields.
Error message:
java.lang.IllegalStateException: No data type for node:
org.hibernate.hql.internal.ast.tree.IdentNode
+-[IDENT] IdentNode: 'payment' {originalText=payment}
Query:
TypedQuery<Object[]> query = entityManager.createQuery("SELECT
payment, createdOn,responseMessage FROM PaymentLog log WHERE log.id
=:personId", Object[].class);
query.setParameter("personId",new BigInteger(basicEntityDto.getId()));
List<Object[]> results = query.getResultList();
for (Object[] log : results) {
paymentTransaction.setAmount(log[0].toString());
paymentTransaction.setDate(log[1].toString());
paymentTransaction.setDescription(log[2].toString());
transactionList.add(paymentTransaction);
}
P.S. I know I can use JPA constructor expression. But as I have to add the DTOs in a list of DTO(i.e. transactionList), so is there a way with JPA construction expression where I can do that by running the query only one time instead in a loop for every single DTO?
You can have the JPA provider transform the result set for you by means of a constructor expression:
http://www.objectdb.com/java/jpa/query/jpql/select#Result_Classes_Constructor_Expressions_
https://en.wikibooks.org/wiki/Java_Persistence/JPQL#Constructors
This requires that the specified class has a constructor matching the select expression. This would then look something like the below:
TypedQuery<PaymentTransaction> query = entityManager.createQuery("SELECT new PaymentTransaction (log.payment, log.createdOn, log.responseMessage ) FROM PaymentLog log WHERE log.id
=:personId", PaymentTransaction.class);
query.setParameter("personId",new BigInteger(basicEntityDto.getId()));
List<PaymentTransaction> results = query.getResultList();
In JPA 2.1 you can also so like the below:
https://en.wikibooks.org/wiki/Java_Persistence/Querying#ConstructorResult_.28JPA_2.1.29
What you could do is:
TypedQuery<PaymentLog> query = entityManager.createQuery("SELECT log FROM PaymentLog log WHERE log.id =:personId", PaymentLog.class);
query.setParameter("personId",new BigInteger(basicEntityDto.getId()));
List<PaymentLog> results = query.getResultList();
for (PaymentLog log : results) {
paymentTransaction.setAmount(log.getPayment());
paymentTransaction.setDate(log.getCreatedOn());
paymentTransaction.setDescription(log.getResponseMessage());
transactionList.add(paymentTransaction);
}
It is not a good idea to select everything from the database if you are not going to use it. If the selected fields were the only columns in the table then approach above works.
If you had a lot more columns in the table, the previous would still work, but this might be better:
TypedQuery<PaymentTransaction> query = entityManager.createQuery("SELECT new PaymentTransaction (log.payment, log.createdOn, log.responseMessage) FROM PaymentLog log WHERE log.id =:personId", PaymentTransaction.class);
query.setParameter("personId",new BigInteger(basicEntityDto.getId()));
List<PaymentTransaction> results = query.getResultList();
The above query will return an already created list of PaymentTransactions. You have to note that the class PaymentTransactionshould have a constructor that accept these fields in the given order. Otherwise it will cause an exception

sqlexception index out of bounds with correct sql-statement

i've got an sql statement that works pretty well. but on implementing in my webapp working with play 2.1 i get this error:
javax.persistence.PersistenceException: Query threw SQLException:Column Index out of range, 0 < 1.
i found this question here: Error executing MySQL query via ebean using RawSql
but then i got other exceptions.
i'm trying to get tagged threads that contains a list of tags (same as stack overflow does).
here the sql statement
SELECT t.topic
FROM topic t
WHERE 3 = (SELECT COUNT( DISTINCT ta.id )
FROM topic_tag tt
INNER JOIN tag ta ON ta.id = tt.tag_id
WHERE ta.name IN ('children', 'spain','new')
AND tt.topic_id = t.id )
in play i do this:
RawSql rawSql = RawSqlBuilder.unparsed(sqlString).create();
result = find.setRawSql(rawSql).findList();
then, i got the out of bounds exception. after that i try to set column mappings:
RawSql rawSql = RawSqlBuilder.unparsed(sqlString)
.columnMapping("t.topic","topic")
.columnMapping("t.id","id")
.columnMapping("ta.name","tagList.name")
.columnMapping("ta.id","tagList.id")
.create();
now i get a null pointer exception. probably because ebean can't create a query from that.
here some code from my models:
#Entity
public class Topic extends Model{
#Id
public Long id;
#Required
public String topic;
#ManyToMany
public List<Tag> tagList;
}
#Entity
public class Tag extends Model {
#Id
public long id;
#Required
public String name;
}
after a lot of trying and frustrating i hope that somebody got a hint or a solution for this.
I just wasted few hours with similar problem, I actually managed to solve it by only mapping id field for certain kind of model and selecting lesser amount of fields, other values were automatically loaded after that - So basically, error occurred if I tried to select values like:
.. select e.id, e.name, e.description from exampleTable e .. and use mappings like:
RawSql rawSql = RawSqlBuilder.parse(sql)
// map the sql result columns to bean properties
.columnMapping("e.id", "exampleModel.id")
.columnMapping("e.name", "exampleModel.name")
.columnMapping("e.description", "exampleModel.description")
.create();
When I changed to select only e.id and map:
RawSql rawSql = RawSqlBuilder.parse(sql)
// map the sql result columns to bean properties
.columnMapping("e.id", "exampleModel.id")
.create();
It loaded also e.name and e.description to model values and errors disappeared.
(Of course my own query had several joins and were bit more complicated than this, but basics are the same.)
So to summarize: when this problem occurs, check that you are not loading anything twice (columnMapping), use System.out.println(""); or similar to check which values are already loaded for your model. Remember to also check annotations such as "#JoinColumn" which might load more data under same model - just based on given e.id value. If you dont select and set e.id as columnMapping value, then you might need to list all needed fields separately as .. e.name, e.description ..
Hopefully these findings helps someone out.

How to pass one of the mysql query results in the model from controller?

In my controller I have called a model that makes a mysql query to fetch information from table. It is working okay but now under the same function I want to call another model and make a query based on one of the results from the previous mysql query. (The field name which I want to get the result of is "batch") . I have tried to get the value (batch) right in my controller, pass it into the model and then tried to make the second query but it seems like the second model is not getting the value from the controller and hence its not working. Would you please kindly help me with this?
Thanks in Advance :)
Here is my Controller
function Get($id){
$this->load->model('mod_studentprofile');
$data['query']= $this->mod_studentprofile->student_get($id);
// To get the batch name
$batch= $query ['batch']; // This I get from the above query result.
$this->load->model('batchname');
$data['query1']= $this->batchname->batchname($batch);
$data['tab'] = "Student Profile";
$data['main_content']='studentprofile';
$this->load->view('includes/template',$data);
}
Here is my model number 1
function student_get($id)
{
$query=$this->db->get_where('student',array('studentid'=>$id));
return $query->row_array();
}
Here is my model number 2
function batchname($batch)
{
$query1=$this->db->get_where('batch',array('batchid'=>$batch));
return $query1->row_array();
}
Well, you're not actually assigning anything to $batch, how about this:
$batch= $data['query'];
This now passes the variable along. As a side note, you can pass it as a paramater and be done with it in a single line, dependency injection style:
$data['query1']= $this->batchname->batchname($this->mod_studentprofile->student_get($id));
Are you getting a value back from the first query?
I would log the value you are getting back from the first query in your controller.
log_message('debug', 'Batch value is '.$batch);
And also put in some debug to see what the query that is being ran.
function batchname($batch)
{
$query1=$this->db->get_where('batch',array('batchid'=>$batch));
$str = $this->db->last_query();
log_message('debug', 'Batchname Query: '.$str);
return $query1->row_array();
}

How to alter this LINQ to SQL so it doesn't bomb at runtime?

public IQueryable<Story> FindAllStories(){
var stories = (from s in db.Stories
orderby s.DateEntered descending
select new Story
{
Title = s.Title,
UserName = s.aspnet_User.UserName
}
);
return stories;
}
I need to pass this as IQueryable so the pagination helper I found online can only pull the items I need. The problem is that at runtime when the helper tries to do source.Count(); the compiler isn't a happy camper because it's an 'explicit contruction of an entity type query'.
How would I alter this LINQ to SQL method so this does not happen?
Also, to help me grasp this, why does the previous code not work and this one does?
public IQueryable<Story> FindAllStories(){
var stories = (from s in db.Stories
orderby s.DateEntered descending
select s);
return stories;
}
Update
I'm beginning to think the way to accomplish this (verified it works) is to create a POCO called UserStory. The new class has 2 properties: one of type Story and the other string UserName. I can then return an IQueryable of UserStory without a problem.
That's great; however, I still don't get why that method would work and my other doesn't. The other is adding a property of string UserName to my partial class Story and passing that object between layers. What's the difference?
The following link is to a blog post tat describes an issue similar to yours. It seems like the solution was to return a type that inherets from Story instead of a Story type:
http://devlicio.us/blogs/derik_whittaker/archive/2008/04/25/linq2sql-explicit-construction-of-entity-exception.aspx
Hope this helps.