How to combine JDBC statement with EntityManager? - java

I created the entity classes of my database with NetBeans. I believe I know how to use EntityManager
(Class) db.createNamedQuery(String name);
but I don't know where to put the statement (database link, login, password) so I learned how to query with
(JDBC4ResultSet) statement.executeQuery(String query);
but it returns the set which I don't know how to transform into Entity class... something like
(Class) statement.execureQuery(String query).toEntity(Class);
would be nice. ;-)

Ok, First you need to get an EntityManager from entity manager factory with your persistance unit name (which will be configured in persistance.xml). And then you create an EntityManager.
EntityManagerFactory emf=Persistence.createEntityManagerFactory("persistance_unit_name");
EntityManager em=emf.createEntityManager();
Query query = em.createNamedQuery("namedQueryName"); //this returns a query
List<ENTITIY> result = query.getResultList();
This is just an heads up, You can google 'jpa example' to find out more working examples.

Related

JPA update query without transaction - is transaction mandatory?

I'm trying to do insert via a native query with JPA, but I don't want to create a transaction:
Query query = em.createNativeQuery("INSERT INTO person (id, firstname, lastname) VALUES ('1','Ronnie','Dio')");
int count = query.executeUpdate();
this ends up with the TransactionRequiredException:
javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:99)
However, if I unwrap the Hibernate session and execute the same query - it works:
Session session = em.unwrap(Session.class);
Query query = session.createSQLQuery("INSERT INTO person (id, firstname, lastname) VALUES ('1','Ronnie','Dio')");
int count = query.executeUpdate();
So my question is - what am I doing wrong in the first sample? Is transaction really required to execute insert/update/delete queries in JPA?
If it is, is there any link to documentation that specifies it clearly? If it's not - what am I doing wrong?
It seems you are building an application that does not run inside a container supporting JTA managed transactions. In such an environment, you have to handle/manage transactions for yourself, i.e., you have to control when transactions are opened, committed or rolled back. This scenario is referred to as resource-local entity manager.
In section 7.5.2 Resource-local EntityManagers of the official JPA 2.2 specification (p. 345) we find:
An entity manager whose transactions are controlled by the application through the EntityTransaction
API is a resource-local entity manager. A resource-local entity manager transaction is mapped
to a resource transaction over the resource by the persistence provider. Resource-local entity managers
may use server or local resources to connect to the database and are unaware of the presence of JTA
transactions that may or may not be active
Further down in the spec document the EntityTransaction interface is given. It allows you to call
begin() to "Start a resource transaction"
commit() to "Commit the current resource transaction, writing any
unflushed changes to the database."
rollback() to "Roll back the current resource transaction." in case something went wrong on the database side while committing changes.
That's for the theory part.
For your code example, you might want to change it as follows:
EntityTransaction tx = null;
try {
tx = em.getTransaction();
// start a new transaction, i.e. gather changes from here on...
tx.begin();
// do your changes here
Query query = em.createNativeQuery("INSERT INTO person (id, firstname, lastname) VALUES ('1','Ronnie','Dio')");
int count = query.executeUpdate();
// write changes to database via commit
tx.commit();
} catch(RuntimeException re) {
if(tx != null && tx.isActive()) {
// ensure no semi-correct changes are pending => cleanup
tx.rollback();
}
// handle exception, log it somewhere...
}
This should avoid the TransactionRequiredException you encounter. Moreover, you should avoid the use createNativeQuery, as you are mis-using a fundamental concept of an Object-Relational-Mapper (ORM), i.e. the mapper will transform objects into tuples and vice versa for you. This - in general - should ease the pain of writing insert/update queries for a large amount of domain entities.
Have a look into section 3.1.1 EntityManager Interface (p. 65) of the spec document linked above and make use of the methods
persist(..) - "Make an instance managed and persistent." or
merge(..) - "Merge the state of the given entity into the current persistence context."
For more infos on the difference of both approaches see the posts here and here.
Hope it helps.
Instead of creating a native query , I would recommend to create a JPA entity for the person and with JPARepository you can use a save method for the person to insert any record.

Hibernate Query readOnly DAO

I'm using the following structure to perform db queries:
getHibernateTemplate().execute(new HibernateCallback<List<String>>() {
#Override
public List<String> doInHibernate(Session session) {
Query query = "select * from whatever";
query.setReadOnly(true);
return query.list();
}
}
Some mapping of attributes might occur in the ongoing hibernate session but those tables shouldn't be altered in any way. I've first tried to use evict(object) for those specific entities but readOnly seems like the better way and I'm loading these unmodifiable objects without anything else attached in a separate DAO. I can't touch the hibernate mapping itself, so any changes there aren't an option for me.
Basically my question is:
(1) Does using evict or setting readOnly make any difference in this case?
(2) Is there a neat way to set readOnly(true) for every call in a DAO? I'm afraid that new methods in the future might forget to set the readOnly part and mess up my db.

How to create native queries in Spring?

I have a spring application that should connect to an existing database and just query an entity for existence based on some attributes.
I don't want to create a #Entity class for this. But I still want to use the spring managed EntityManager etc.
When using Spring, what is the best approach to just query a select for that entity? Using em.createNamedQuery(QUERY); with String QUERY = "SELECT count(*) from my_table where username =: username AND email := email)";?
Answers from #predrag-maric and #pL4Gu33 are both correct but if you use JPA in your project (for example, Hibernate) you might consider using #NamedNativeQuery annotation as well.
More about named native queries.
simple example of native query
#PersistenceContext
EntityManager em;
public String test(Integer id)
{
Query query = em.createNativeQuery("SELECT name FROM Accounts where id=?");
query.setParameter(1,id);
return query.getSingleResult();
}
You can use this method from entitymanager. http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#createNativeQuery%28java.lang.String%29
Use em.createNativeQuery(QUERY). Also, you'll have to use positional parameters (?1) instead of named parameters (:email), because only positional parameters are supported by JPA in native queries.

Update specific field of table regardless of other fields in hibernate

I have table having lot of information. I am not loading all the information while updating this table from view page.
Below is my code to update the table using hibernate
HibernateTemplate hibernateTemplateObj = getHibernateTemplate();
hibernateTemplateObj.update(myEntityBean);
Above one was updating the fields but the fields which are not visible on my view page will be updated with blank.
So, I used below one...
HibernateTemplate hibernateTemplateObj = getHibernateTemplate();
hibernateTemplateObj.update("myRequiredField", myEntityBean);
As per documentation here it says if I use update("string",entity) it will update that fields. But it's not working as same.
Can any one please suggest something.
I found some posts.
post1
post2
It says, I need to create queries. But I don't know how to create queries from it?
If any one have any idea.. Please help. I think it's known issue from those posts.
You can create a query with the Session object like this.
SessionFactory factory= HibernateUtil.getSessionFactory();
session = factory.openSession();
session.beginTransaction();
Query query = session.createQuery("Select c.productList from Cart c Where c.cartId=:cartId");
query.setParameter("cartId", cart.getCartId());
List productList=(List) query.list();
session.getTransaction().commit();
While you know what kind of object should return from query you can cast it and use it.
You can write native query or hibernate query but I think hibernate query is easier.

How update the database using a web service and EclipseLink as JPA provider?

I have done a simple web service using EclipseLink as JPA provider. I am a beginner when coming to JPA, so I am wondering if this is the common way and most pure and secure way to make updates to the database:
EntityManager em = emf.createEntityManager();
if(!em.getTransaction().isActive()){
em.getTransaction().begin();
}
Query query = (Query)em.createNamedQuery("Person.updatePerson");
query.setParameter("personId", person.getPersonPK().getPersonId())
.setParameter("personName", name);
return query.executeUpdate();
Why don't I need to use em.getTransaction().commit(); after I have called em.getTransaction().begin()? query.executeUpdate() seems to update the database, not the commit call. Why is that so? What is recommended?
You need to call commit() to commit the transaction. Executing a query will not commit.
What type of transactions are you using? JTA or RESOURCE_LOCAL? If you are using JTA, then you must use JTA to begin a commit transactions.
Enable logging to get more details.
In general in JPA updates are normally done by reading the object and using its set methods, not executing raw queries.
Interesting question, I did some investigation with a non-jta-datasource:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("unit1");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// database: t.name='OLD'
Query query = em.createQuery("UPDATE Test t set t.name = 'NEW'");
query.executeUpdate();
// database: t.name='OLD'
TypedQuery<String> tq
= em.createQuery("SELECT t.name from Test t", String.class);
System.out.println(tq.getSingleResult());
// output: 'NEW'
// database: t.name='OLD'
em.getTransaction().commit();
// database: t.name='NEW'
My explanation approach (please correct me, if I am wrong):
The database holds 'OLD' value until em.getTransaction().commit().
The SELECT query returns 'NEW' from persistence context

Categories