Thanks for looking at this. I have a tomcat spring boot application using JPA/Hibernate with mysql database back end. There are REST controllers exposed and various service methods are annotated with "#Transactional".
There are entity and repo objects used by JPA/Hibernate to persist and query data from the mysql database. The SQL queries are generated by JPA Hibernate entity and repo objects, like as follows:
public interface FooRepo extends JpaRepository < Foo, String > {
}
The above means that there is a table Foo which has a primary key of type String. There is also a separate class Foo.
While using the above FooRepo to query a single row in the table I see the following SQL queries
set session transaction read
select * from Foo where id='IdToQuery';
set session transaction read write
I understand the select SQL statement but not able to understand why "set session transaction read" is being executed?
Thanks,
ash
After Googling, the only suggestion that I found was to implement a separate read-only transaction connection pool.
From: http://256stuff.com/gray/docs/misc/performance_optimizing_spring_hibernate_transactions/
Related
I have plain JDBC code which is doing transaction management using Connection Interface. I wanted to switch to Spring Transaction Management in small steps.
Firstly I want to provide PlatformTransactionManager for my datasource and annotate my class / methods with #Transaction and keep my other logic same ie. using connection / PreparedStatement etc.
All the examples, which I see use JdbcTemplate. I was wondering can Spring Transaction be used without JdbcTemplate?
Technically it is possible to use #Transactional without JdbcTemplate . But if you try to do it , you will sooner or later find that you are re-inventing what the things that are already done by JdbcTemplate.
What #Transactional does is that before executing a #Transactional method , it will help you to get a JDBC Connection from the DataSource , and start a transaction on this Connection .The JDBC Connection will then stored in a ThreadLocal.
That means if you do it without JdbcTemplate , you have to manually get this Connection from that ThreadLocal such that you can create a JDBC Statement from it for executing your SQL. Not to mention you have to manually release the JDBC resources such Statement , ResultSet etc. properly by yourself which all of these things are already take care by JdbcTemplate.
But if you have already implemented these JDBC codes manually and just want to let #Transactional to handle the transaction , you could try to inject the DataSource to your bean and then use the following method to get the Connection for your JDBC codes use :
Connection connection = DataSourceUtils.getConnection(dataSource);
Also checkout JdbcTemplate#execute(ConnectionCallback<T> action) , it is useful for migrating the existing JDBC codes that expects a JDBC Connection to work on to JdbcTemplate.
Yes it's possible. Adding a #Transactional annotation to your methods, as long as they follow the correct procedure should make your methods transactional. But as others have mentioned if you're in the process of updating your app you might as well ditch plain JDBC and move across to Spring JPA/JDBC (depending on which version of Spring you're using).
I'm trying to get the url that the Connection uses to connect the database as following :
getEntityManager().unwrap(SessionImplementor.class).connection().getMetaData().getURL();
But I get this error :
java.lang.IllegalStateException: No transactional EntityManager available
How can I solve this ?
Edit:
I don't understand why this question was considered as duplicated to a Hibernate solution, I'm using JPA, so I'm trying to get the url using entityManager and not sessionFactory.
The solution was to add the #Transactional annotation.
The SessionImplementor Interface is form Hibernate, so which JPA Implementation are you using then?
We have an application which uses multiple databases to store the same data for different countries.
For example a Subscription object might be associated with Germany or Spain. If it's a German subscription, it needs to be stored in a different database to the Spanish subscriptions. The databases are identical in structure, but they have different contents.
We are running on jboss 5, and have a different datasource config (*ds.xml) file for each one, generated dynamically at startup. They are stored in JNDI - so we have DataSourceDE, DataSourceES, etc.
Here's how it should work: if a request comes in saying 'fetch subscription 17 for Germany' then I calculate that the datasource should be DataSourceDE and use JPA / hibernate to go fetch that object from the correct database. There will be a subscription 17 in the Spanish database too, which I don't want in this example.
I can generate the persistence.xml automatically to create the extra persistence units for the datasources, but the Subscription class is annotated with the following:
#PersistenceContext(unitName="core")
This is not going to work - how can I set the persistence context on the java object dynamically?
What you are trying to achieve is known as Multi-Tenancy. Here is a perfectly suitable tutorial for your question to make it work.
The main idea is to use a Stateless session bean which has a reference to both persistence units. Depending on what has to be done, this bean does a lookup to call the corresponding EntityManager. Furthermore here:
Multi-Tenancy With EJB 3.1 and JPA 2.0
You can change the persistence context for the EntityManager at runtime like this:
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(persistenceUnitName);
EntityManager em = emf.createEntityManager();
I had a web software running in a Jboss AS 7 container witch saves our data in a PostgreSQL 9.1 database via JPA, an its configuration delegated to JTA.
Last year it was adapted to run at AWS EC2 cloud. As the user demand grown our database usage growed too. As expected our database server becomes busy at rush times, an it affected the usage experience from our users.
After some replication researches on PostgreSQL we realise that PGPool2 could be a nice replication solution for our case: it offers Load Balancing for SELECT queries, and Replication for CUD operations ( UPDATE, INSERT and DELETE ) as well.
So far so good, except that it turns the software slow. If fact, as explicited in PGPool2 documentation, SELECT queries will not be load balanced if it was defined in explicit BEGIN/END transaction.
For a query to be load balanced, all the following requirements must be met:
- PostgreSQL version 7.4 or later
- the query must not be in an explicitly declared transaction (i.e. not in a BEGIN ~ END block)
- it's not SELECT nextval or SELECT setval
- it's not SELECT INTO
- it's not SELECT FOR UPDATE nor FOR SHARE
- it starts with "SELECT" or one of COPY TO STDOUT, EXPLAIN, EXPLAIN ANALYZE SELECT...
- ignore_leading_white_space = true will ignore leading white space.
Two questions:
How I could figure out our SELECT queries that was running in explicit transactions?
Does _javax.ejb.TransactionAttributeType.NOT_SUPPORTED_ fix the transaction scopes, granting that my SELECT method will be running as "transaction-free"?
How I could figure out our SELECT queries that was running in explicit transactions?
Turn on pgpool2 logging of SQL and connections:
Put the following statements into pgpool.conf (which you can setup via cp $prefix/etc/pgpool.conf.sample $prefix/etc/pgpool.conf):
log_per_node_statement
log_connections
Alternatively, turn on log tracing of JPA:
This requires a different method depending or your JPA implementation ( How to view the SQL queries issued by JPA? , JPA 2.0 (logging and tracing through) with Glassfish 3.0.1 and NetBeans 6.9.1: ).
This will log SQL, but will not log transaction start/commit/rollback.
Additionally, put your own debug logging code into methods which start & end transactions, so that you can see when transaction start/commit/rollback.
Does _javax.ejb.TransactionAttributeType.NOT_SUPPORTED_ fix the transaction scopes, granting that my SELECT method will be running as "transaction-free"?
If you are using Container Managed Transactions (annotations #TransactionManagement(CONTAINER) and #TransactionAttribute), then NOT_SUPPORTED will temporarily disassocate the JTA transaction from the current thread. Then the method will run with no transaction context.
Your subsequent JPA query will run outside of the JTA transaction - because the JTA transaction is not available for it to use.
If you already use a Transaction-Scoped EntityManager
Within your Stateless Session Bean you have an EntityManager annotated
#PersistenceContext(type=PersistenceContextType.TRANSACTION), or
annotated #PersistenceContext without type attribute (because
TRANSACTION is the default):
then that EM will lose it's persistence context within the NOT_SUPPORTED method because the PC is associated with the current transaction, which is no longer accessible
so you cannot use such an EM in the method (e.g. to run queries or lookup cached objects)
so you must use an additional application-managed EM within the NOT_SUPPORTED method
you must create the app-managed EM from an EntityManagerFactory in a place where no JTA transaction is active (e.g. in the NOT_SUPPORTED method), because the app-managed EM will automatically associate itself with the current thread's JTA transaction during creation
any objects returned from queries by the new app-managed EM will be in a different persistence context from the original EM, so you need great care to cleanly detach such objects from the PC (e.g. appMgdEM.clear() or appMgdEM.close() or appMgdEM.detach(someEntity)) if you are to modify/merge them with the original EM.
If you already use an Extended-Scoped EntityManager
Within your Stateful Session Bean you have an EntityManager annotated #PersistenceContext(type=PersistenceContextType.EXTENDED).
then that EM will still have it's persistence context within the NOT_SUPPORTED method because the PC is associated with the stateful session bean
but the EM is using a connection that is already in the middle of a "live" transaction
so if you want to run queries outside of a transaction, you cannot use such an EM in the method
so again, you must use an additional application-managed EM within the NOT_SUPPORTED method (same points apply as above).
Example
#Stateless
public class DepartmentManagerBean implements DepartmentManager {
#PersistenceUnit(unitName="EmployeeService")
EntityManager txScopedEM;
#PersistenceUnit(unitName="EmployeeService")
EntityManagerFactory emf;
#TranactionAttribute(REQUIRED)
public void modifyDepartment(int deptId) {
Department dept = txScopedEM.find(Department.class, deptId);
dept.setName("New Dept Name");
List<Employee> empList = getEmpList();
for(Employee emp : empList) {
txScopedEM.merge(emp);
dept.addEmployee(emp);
}
dept.setEmployeeCount(empList.size());
}
#TranactionAttribute(NOT_SUPPORTED)
public void getEmpList() {
EntityManager appManagedEM = emf.createEntityManager();
TypedQuery<Employee> empQuery = appManagedEM.createQuery("...", Employee.class);
List<Employee> empList = empQuery.getResultList();
// ...
appManagedEM.clear();
return empList;
}
}
Alternative/Adjusted Approach
The above has some restrictions on how you query and how you use resulting objects. It requires creating an EM "on the fly", if you use stateless session beans, and also requires entityManager.merge() to be called. It may not suit you.
A strong alternative is to redesign your application, so that you run all queries before the transaction starts. Then it should be possible to use a single Extended-Scoped EntityManager. Run the queries in "NOT_SUPPORTED" method 1 (no transaction), using extended-scope EM. Then run modifications in "REQUIRED" method 2 (with transaction), using the same extended-scope EM. A Transaction-Scoped EntityManaged wouldn't work (it would try to be transactional from the very start, and would have no PC in NOT_SUPPORTED methods).
Cheers :)
You may want to consider partitioning in JPA using EclipseLink data partitioning,
http://java-persistence-performance.blogspot.com/2011/05/data-partitioning-scaling-database.html
I am currently using version 3.3 of hibernate.
Currently the setting of hibernate is such that it will autocommit after each persistence of individual object.
I want to wrap a transaction around it, so it will only commit after end of a batch.
The code is in question:
getHibernateTemplate().saveOrUpdateAll(collectionOfObject);
I have consulted the documentation here, but want to see if there is alternative (other than rewriting it to use HSQL)
EDIT
My goal is to have a transaction around a bunch of insert. Currently it is auto-commit per insert
If you want to use transaction management in Spring read here on how to do it.
Also, Use should not be using HibernateTemplate use the Session object instead as below.
sessionFactory = getHibernateTemplate().getSessionFactory();
Session session = sessionFactory.getCurrentSession();
for (Bean bean : listBeans) {
session.saveOrUpdate(bean );
}
As there is no way to save the collection at one shot in session. This will commit the data after method exit.