I am new with hibernate and I was trying to update a mapped object with the following code, but it does not update
factory = config.buildSessionFactory();
session = factory.getCurrentSession();
Transaction t = session.beginTransaction();
String hql = "UPDATE "+tableName+" SET "+columnName+" = '"+columnValue+"' WHERE id ="+id+";";
Query query=session.createSQLQuery(hql);
t.commit();
Am I missing something? It do not crash nor update the record.
NOTE: I am using Hibernate3 and Mysql
You're missing query.executeUpdate();
Also, if you're updating a mapped object I would recommend you to make the changes to the java object, and let Hibernate do the update for you. Or at least use a hql query, not a native one.
Make sure that your persistence.xml file has show_sql set to true and watch the log to see if the update is executed.
<property name="hibernate.show_sql" value="true"/>
You need to use query.executeUpdate() to run the query.
Also it is suggested that you use parameters instead of inline arguments. For eg. if the columnName = O'Reilly then the whole query will go wrong.
Also if it is a mapped object you can use HQL rather than SQL query
Instead you can use this
//entity is your hibernate entity obj
String hql = "UPDATE " + entity.getClass().getName + " as entity SET entity." + fieldName + "= :columnValue WHERE entity = :entity";
Query query=session.createQuery(hql).setParameter("columnValue", columnValue).setParameter("entity", entity);
query.executeUpdate();
Notice that you don't need to use single quotes. setParameter handles it.
Related
I am familiar with Java but really new with ORM and Hibernate.
I am using the following query to get the resultset of all columns of a table in hibernate.
(List<Neighborhood>)session.createSQLQuery("SELECT * FROM Neighborhood").addEntity(Neighborhood.class).list();
I want to get only two specific column from this table. I looked up over the internet but not able to find the solution which can be used as a modification of above statement.
I tried the below query but getting - SQLGrammarException: could not extract ResultSet
(List<Neighborhood>)session.createSQLQuery("SELECT neighborhoodName,educationYouth FROM Neighborhood").addEntity(Neighborhood.class).list();
Edit:
Two more attempted queries after #scaryWombat's suggestion. Both give the same exception
First
List list = session.createSQLQuery("SELECT neighborhoodName,educationYouth FROM Neighborhood").list();
Second
String sql = "SELECT neighborhoodName,educationYouth FROM Neighborhood";
SQLQuery query = session.createSQLQuery(sql);
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List results = query.list();
Edit2:
After #Tehmina's solution, I am getting one error - java.sql.SQLException: Column 'educationYouth' not found because educationYouth is an object of class name "EducationYouth".
In the Neighborhood table there is no column with name educationYouth but all the column from EducationYouth class.
Try this
(List<Neighborhood>)session.createSQLQuery("SELECT * FROM Neighborhood").list();
To avoid the overhead of using ResultSetMetadata, or simply to be more explicit in what is returned, one can use addScalar():
(List<Neighborhood>)session.createSQLQuery("SELECT * FROM Neighborhood").addScalar("neighborhoodName", Hibernate.STRING).addScalar("educationYouth", Hibernate.STRING);
Or try this
Hibernate automatically converts the data into appropriate type. The automatic conversion does not work in all cases and in that case we have an overloaded version of addScalar():
SQLQuery q = session.createSQLQuery("SELECT * FROM Neighborhood");
q.addScalar("neighborhoodName");
q.addScalar("educationYouth");
List<Object[]> rows = q.list();
for (Object[] row : rows) {
System.out.println(row[0] + " " + row[1] );
Don't forget to check in the hibernate config file
<!--hibernate.cfg.xml -->
<property name="show_sql">true</property>
I hope it would resolve your error.
I have an Update Query that looks like this
UPDATE
table_name
SET
column_name = ?
WHERE
column_name = ? AND id in (?)
So the JPA transaction is
em.createNativeQuery(Update_QUERY)
.setParameter(1, updatedStatus)
.setParameter(2, currentStatus)
.setParameter(3, ids)
.executeUpdate();
The Input to the method is List id, currentStatus, and updatedStatus
How do I pass the List as a single parameter, if I convert the List to a comma-separated String I get the error Specified text is not number as strings is not allowed in the In clause.
How do I pass the List as a single parameter
An example approach:
String jpql = "UPDATE NameEntity ne " +
"SET ne.valstring = :updated_status " +
"WHERE ne.valstring = :current_status AND ne.id IN :ids";
em.createQuery(jqpl)
.setParameter("updated_status", updatedStatus)
.setParameter("current_status", currentstatus)
.setParameter("ids", Arrays.asList(ids))
.executeUpdate();
Three simple rules:
Use native SQL for bulk update / delete on tables that are not mapped to entities.
Native SQL queries work directly on database tables bypassing the persistence context (a set of managed entities), so it is safe to use such queries if a given database table has no corresponding entity.
Use JPQL for bulk update / delete on tables that are mapped to entities
In case of a given database table is mapped by an entity, using a SQL update / delete will lead to inconsistency between persistence context and the underlying database, so use JQPL counterparts instead and the persistence provider will take care of consistency.
Bulk update / delete should be executed as the first operation within the transaction or ideally in its own transaction.
Setting a List parameter
The JPA Query interface setParameter method that accepts an Object parameter:
Query setParameter(String name, Object value)
can take a List as the parameter value.
This works in the same way for JPQL, Criteria API, or bulk update and delete queries:
List<Post> posts = entityManager.createNativeQuery("""
UPDATE
post
SET
status = :newStatus
WHERE
status = :oldStatus AND
id IN :ids
""", Post.class)
.setParameter("oldStatus", PostStatus.PENDING)
.setParameter("newStatus", PostStatus.APPROVED)
.setParameter("ids", List.of(1L, 2L, 3L))
.executeUpdate();
For more details about executing bulk update and delete statements with JPA and Hibernate, check out this article as well.
How to get which properties were updated after hibernate update?
For example if I got
SomeEntity se = new SomeEntity();
getHibernateTemplate().save(se);
//then in some other method
se.setProp1("some new value");
//then in 3th method
getHibernateTemplate().update(se);
If you tell hibernate to do dynamic update it will know witch properties were changed and update only them. Is there a way to get the ones that were changed or to check is specific property was changed?
Ended up doing native sql query to compare the state in the db with the state in the entity before flush the session.
Query query = session.createSQLQuery(
"select t.someProp1 from someTable t where t.id = :entityId")
.setParameter("entityId", entity.getId());
List result = query.list();
I am using Hibernate to accessing data from sql server 2008.while executing the following code
Session session = sessionFactory.openSession();
String qry="select Form_Id,SUBSTRING(
(SELECT ( '' + t2.Form_Layout_Txt) FROM Form_Layout_Info t2
WHERE t1.Form_Id = t2.Form_Id " +
" GROUP BY Form_Layout_Txt FOR XML path('') ), 1,1000000000)
FROM Form_Layout_Info t1 GROUP BY Form_Id";
SQLQuery query = session.createSQLQuery(qry);
recordList = query.list();
My Hibernate properties is
hibernate.connection.driver_class=com.microsoft.sqlserver.jdbc.SQLServerDriver
hibernate.connection.url=jdbc:sqlserver://localhost:1433;databaseName=abc;integratedSecurity=false;
hibernate.dialect=org.hibernate.dialect.SQLServerDialect
hibernate.connection.username=sa
hibernate.connection.password=p123asc
i received the following error
No Dialect mapping for JDBC type: -9
How to fix the issue.
You need to provide hibernate.dialect=org.hibernate.dialect.SQLServerDialect in configuration for sql server.
Either provide it in hibernate.cfg.xml as :
<hibernate-configuration>
<session-factory name="session-factory">
.....
<property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>
....
</session-factory>
</hibernate-configuration>
or in properties file as :
hibernate.dialect=org.hibernate.dialect.SQLServerDialect
I don't know which way you are using, so posted both I know.
I found 2 solutions for your problem here:
try changing your driver to jTDS
using the ms sql server jdbc driver provided by microsoft can cause this issue while jTDS does not give this complaint.
you may need to explicitly “addScalar” to your hibernate query. You might have something like this:
sess.createSQLQuery("SELECT * FROM CATS");
// try changing to:
sess.createSQLQuery("SELECT * FROM CATS")
.addScalar("ID", Hibernate.LONG)
.addScalar("NAME", Hibernate.STRING)
.addScalar("BIRTHDATE", Hibernate.DATE)
This issue is related to type mapping done while returning data. And mapping for that particular data type not exists in Dialect.
https://forum.hibernate.org/viewtopic.php?f=1&t=959583
Hibernate Data types -
http://docs.jboss.org/hibernate/orm/3.6/javadocs/org/hibernate/type/StandardBasicTypes.html
The error means hibernate doesn’t know how to map the JDBC type “NVARCHAR” to a hibernate type.
Solution 1:
Using addScalar like this:
Session session = sessionFactory.openSession();
String qry="select Form_Id,SUBSTRING(
(SELECT ( '' + t2.Form_Layout_Txt) as formLayoutTxt FROM Form_Layout_Info t2
WHERE t1.Form_Id = t2.Form_Id " +
" GROUP BY Form_Layout_Txt FOR XML path('') ), 1,1000000000)
FROM Form_Layout_Info t1 GROUP BY Form_Id";
SQLQuery query = session.createSQLQuery(qry).addScalar("formLayoutTxt", StringType.INSTANCE);
recordList = query.list();
Solution 2: Register the Hibernate Type in Dialect
public class MySQLServerDialect extends SQLServerDialect {
public MySQLServerDialect() {
super();
// Register mappings
registerHibernateType(Types.NVARCHAR, StringType.INSTANCE.getName());
}
}
For more details, check out this.
I am new in hibernate. I am using hibernate 3 in my application using hibernate annotations , I am developing application in struts 1.3.
My question is :
I have googled a lot but could not understand how to call a stored procedure in hibernate using annotations , I have a simple scenario : suppose I have 2 fields in my jsp say 1) code 2) name , I have created a stored procedure in database for inserting those records into table. Now my problem is that how to execute it
List<MyBean> list = sessionFactory.getCurrentSession()
.getNamedQuery("mySp")
.setParameter("code", code)
.setParameter("name", name)
I don't know the exact code how to do this. But I guess something like that actually I come from jdbc background therefore have no idea how to do this and same thing I want when selecting the data from database using stored procedure.
Hibernate provides many simple ways to call a SP like
Native SQL
Named Query in native SQL as Annotation/XML mapping file
Following link shows how each of above can be implemented
http://www.mkyong.com/hibernate/how-to-call-store-procedure-in-hibernate/
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querysql.html#sp_query
Sample to run native SQL query using hibernate:
Session session = getSession();
SQLQuery sqlQuery = session.createSQLQuery("SELECT COUNT(id) FROM tableName WHERE external_id = :external_id");
sqlQuery.setParameter("external_id", idValue);
int count = ((BigInteger) sqlQuery.uniqueResult()).intValue();
releaseSession(session);
You can execute your stored procedure using Hibernate's SQLQuery with the same SQL as when you call it against the database. For example, in postgreSQL:
String query = "select schema.procedure_name(:param1)";
SQLQuery sqlquery = sessionFactory.getCurrentSession().createSQLQuery(query);
sqlquery.setInteger("param1", "this is first parameter");
sqlQuery.list();
Hope it helps.