How to force Hibernate use AND in update query? - java

I am trying to update a raw by composite primary key by using hibernate.
Hibernate uses the next style for such updates:
update mytable set mycolumn=321 where (left_pk, right_pk) = (123, 456);
Is it possible to force hibernate to use the next style?:
update mytable set mycolumn=321 where left_pk = 123 and right_pk = 456;
Both queries work but with a huge difference (at least in MariaDB).
If we use repeatable read transaction then the first query locks the whole table for updates and the second query locks only the single row for updates.
I would prefer to lock only a single row, so I need to use the second query.

You can go for NamedQueries approach in Hibernate,
For example:
//Create Query
#NamedQueries({ #NamedQuery(name = " YOUR QUERY NAME",
query = "from DeptEmployee where department = :department and emp = :emp") })
// set multiple parameters
query.setParameter("department",department)
.setParameter("emp", emp)
Try giving this a shot.

Related

Calculate procedures or queries in hibernate in my entitys

I have a table called "Endoso", this table has the properties of "id", "numEndoso","endosos_por_dia". The "numEndoso" is the id of the envio(id of table EnvioRemesa), and the "endosos_por_dia" property is a calculated property as I put below.
select count(*)
from documento d
inner join remesa r
on r.id = d.remesa_id
inner join envio_remesa er
on r.id = er.remesa_id
where r.id=?
What I want and can't do, is that for example when I calculate endosos_por_dia if 8 documents turn out, create 8 different records in my database, increasing from 1 to 8.And how could I put my calculated property query on my entity Endoso and it will be reflected in the database? How can I do this in hibernate?
You can use a Formula:
#Formula("(select count(*) ... where r.id=numEndoso)")
public int getEndososPorDia() {
return endososPorDia;
}
Note that numEndoso in the SQL fragment refers to the ID of your entity, you might need to adapt it because I assumed that it was the name of the column.
This will make the endososPorDia field read-only as far as Hibernate is concerned, you will need to modify the underlying data (add new documents) and then refresh the entity to update the value

Update one single column in database using JPQL

How to write a JPQL query to update a single column in MySql DB :
Regular SQL update query :
Update NATAddress SET ordinal = ? WHERE ordinal = ? AND natId = ?
JPQL update query :
UPDATE NATAddress na SET na.ordinal = ?1 WHERE na.ordinal = ?2 AND na.networkDomain.natId =?3
Eclipse shows following error for above JPQL update query
Input parameters can only be used in the WHERE clause or HAVING clause of a query.
Looks like JPA specifications doesn't allow to set input parameters in update columns.
Is there any other way to update other than updating the whole JPA Entity using merge() method?
Update your query to be like this I assume this is the Class name and this is the name of its attributes
UPDATE NATAddress na SET na.ordinal = ? WHERE na.ordinal = ? AND na.networkDomain.natId =?
try this
String query = "Update NATAddress SET ordinal = '"+Parameter1+"' WHERE ordinal = '"+Parameter2+"' AND natId = '"+Parameter3+"'";

Java Hibernate : Update most recent entry in MySql database

This is my requirement. I have a bunch of rows with similar data. I want to update some columns on the LATEST entry. So I have written a hibernate query which goes like this
String hql = "UPDATE Studenttable T set T.timestamp=:time,T.Action=:action where T.StudentId=:studentId and T.teacherId=:TeacherId order by T.teacher_student_mapping_id DESC";
Query query = session.createQuery(hql);
query.setParameter("time",time);
query.setParameter("studentId", studentId);
query.setParameter("TeacherId", teacherId);
query.setParameter("action", action);
query.setMaxResults(1);
query.executeUpdate();
What this does is it updates all the rows which satisfies the condition and then returns the latest row. Instead I want it to fetch the latest row satisfying the conditions, and then update it. How can I do it? Any help is deeply appreciated.
P.S. the teacher_student_mapping_id is an auto-generated value, which is also a primary key.
Time is the current time.
Please don't try to make sense of the table, I have changed the names of the columns for confidentiality.
try
String hql = "UPDATE Studenttable T set T.timestamp=:time,T.Action=:action where T.StudentId=:studentId and T.teacherId=:TeacherId order by T.timestamp DESC LIMIT 1";
Since tagged hql you can try something like below. Updating only the latest one based on pk.
UPDATE Studenttable T set T.timestamp=:time,T.Action=:action where T.StudentId=:studentId and T.teacherId=:TeacherId
and T.pk = (select max(tb.pk) from Studenttable tb where tb.StudentId=:studentId and tb.teacherId=:TeacherId )

What's the fastest way to check if a row exists in DB using Hibernate & spring?

I need to check if a row exists in a database in a very fast way.
Let's say I've got the primary key.
I found this code snippet in Hibernate's FAQ website:
Integer count = (Integer) session.createQuery("select count(*) from ....").uniqueResult();
I just started using spring, so I have HibernateTemplate object injected into my class.
How do I translate this snippet to work with HibernateTemplate.
Does anyone knows a better/faster way than this ?
Thanks.
Long count = hibernateTemplate.execute(new HibernateCallback<Long>() {
#Override
public Long doInHibernate(Session session) {
return (Long) session.createQuery("select count(someEntity.id) from SomeEntiuty someEntity ...").uniqueResult();
}
});
Hibernate used Integer for count queries before, but now uses Long. Also, note that even if not deprecated, Spring recommends not to use HibernateTemplate anymore and use the Hibernate API directly (using sessionFactory.getCurrentSession()).
Fastest way of checking primary key exist or not in database.
public void exist(Long id) {
Session session = sessionFactory.getCurrentSession();
String queryString = "select 1 from Employee e where e.id= :id";
Query query = session.createQuery(queryString);
query.setParameter("id", 1l);
Integer result = (Integer) query.uniqueResult();
System.out.println(result);
}
Again this also depends on a lot on what engine that you are using MyISAM vs innodb.
select count(col1) from table; will return the number of rows where the column is not null.
select count(*) from table; will return the number of rows.
Depending upon the database that you are using , a select count(*) will be more expensive than reading it from meta data table or system level tables that keep track of the row count.
Just my 2 cents.
Depending upon various other factors like indexes and other information / joins / access privileges this may be faster
SELECT table_rows FROM `information_schema`.`TABLES` where table_schema = 'database_schema_name' and table_name = 'table_name';
I think it's better to get an specific representative field of the first row found (using the PK or at least another indexed field), than counting all of the possible records that would match your search criteria.
If you're using Spring it will throw EmptyResultDataAccessException if no record was found.

How to convert nested SQL to HQL

I am new to the Hibernate and HQL. I want to write an update query in HQL, whose SQL equivalent is as follows:
update patient set
`last_name` = "new_last",
`first_name` = "new_first"
where id = (select doctor_id from doctor
where clinic_id = 22 and city = 'abc_city');
doctor_id is PK for doctor and is FK and PK in patient. There is one-to-one mapping.
The corresponding Java classes are Patient (with fields lastName, firstName, doctorId) and Doctor (with fields doctorId).
Can anyone please tell what will be the HQL equivalent of the above SQL query?
Thanks a lot.
String update = "update Patient p set p.last_name = :new_last, p.first_name = :new_first where p.id = some (select doctor.id from Doctor doctor where doctor.clinic_id = 22 and city = 'abc_city')";
You can work out how to phrase hql queries if you check the specification. You can find a section about subqueries there.
I don't think you need HQL (I know, you ask that explicitly, but since you say you're new to Hibernate, let me offer a Hibernate-style alternative). I am not a favor of HQL, because you are still dealing with strings, which can become hard to maintain, just like SQL, and you loose type safety.
Instead, use Hibernate criteria queries and methods to query your data. Depending on your class mapping, you could do something like this:
List patients = session.CreateCriteria(typeof(Patient.class))
.createAlias("doctor", "dr")
.add(Restrictions.Eq("dr.clinic_id", 22))
.add(Restrictions.Eq("dr.city", "abc_city"))
.list();
// go through the patients and set the properties something like this:
for(Patient p : patients)
{
p.lastName = "new lastname";
p.firstName = "new firstname";
}
Some people argue that using CreateCriteria is difficult. It takes a little getting used to, true, but it has the advantage of type safety and complexities can easily be hidden behind generic classes. Google for "Hibernate java GetByProperty" and you see what I mean.
update Patient set last_name = :new_last , first_name = :new_first where patient.id = some(select doctor_id from Doctor as doctor where clinic_id = 22 and city = abc_city)
There is a significant difference between executing update with select and actually fetching the records to the client, updating them and posting them back:
UPDATE x SET a=:a WHERE b in (SELECT ...)
works in the database, no data is transferred to the client.
list=CreateCriteria().add(Restriction).list();
brings all the records to be updated to the client, updates them, then posts them back to the database, probably with one UPDATE per record.
Using UPDATE is much, much faster than using criteria (think thousands of times).
Since the question title can be interpreted generally as "How to use nested selects in hibernate", and the HQL syntax restricts nested selects only to be in the select- and the where-clause, I would like to add here the possibility to use native SQL as well. In Oracle - for instance - you may also use a nested select in the from-clause.
Following query with two nested inner selects cannot be expressed by HQL:
select ext, count(ext)
from (
select substr(s, nullif( instr(s,'.', -1) +1, 1) ) as ext
from (
select b.FILE_NAME as s from ATTACHMENT_B b
union select att.FILE_NAME as s from ATTACHEMENT_FOR_MAIL att
)
)
GROUP BY ext
order by ext;
(which counts, BTW, the occurences of each distinct file name extension in two different tables).
You can use such an sql string as native sql like this:
#Autowired
private SessionFactory sessionFactory;
String sql = ...
SQLQuery qry = sessionFactory.getCurrentSession().createSQLQuery(sql);
// provide an appropriate ResultTransformer
return qry.list();

Categories