I am just learning JTA and can't understand if I should use it if I have only one database. Currently I use hibernate 5 as JPA provider and if I need to use one transaction between methods I just pass EntityManager as argument.
However, I don't like this method as I need to remember if transaction is opened or not. I would like to find any library that will help me to control transactions (but without Spring) in SE environment. So, should I use JTA in my situation or should I use something different?
Normally when talking about JTA , it refers to the distributed transaction across multiple systems (e.g. across two databases , one database and one JMS compliant message broker). If you only have one database , it is not necessary to use JTA transaction although it should also work. Instead, use a local transaction for one database which should theoretically faster than using JTA transaction.
On the other hands , if you are just talking about #Transactional defined in the JTA , which allow you to declaratively control the transaction boundary by annotating it on a method and without passing the EntityManager between methods , you should look into which frameworks support it.
Under the cover , a proxied EntityManager is injected into different classes such that when it is invoked , it will get the actual EntityManager from the ThreadLocal. So every class in the same thread will get the same EntityManager which prevent you from passing the EntityManager around the methods. A new EntityManager instance will be set to the ThreadLocal just before the #Transactional method is executed using some sort of AOP technique.
Please note that #Transcational is nothing to do with the underlying transaction is JTA or local transaction. It should work for both transaction type.
I would use a framework that support #Transactional such as Spring , Quarkus or Micronaut etc , and configure Hibernate to use local transaction but not JTA transaction for single database.
Related
I am new to JTA and I need a method to retrieve some some elements from the database. I can do this through EntityManager but that works only for ResourceLocal.
I want to know how can I do this:
Query q = em.createNamedQuery("AnyQuery");
q.getResultList();
without the use of EntityManager.
Any ideas?
The question itself shows that you don't understand any of the technologies you try to work with. You probably need to study some more general stuff before you do any actual development.
you are probably confusing JTA and JPA,
your statement about RESOURCE_LOCAL is not true (and irrelevant) - there are JTA and RESOURCE_LOCAL transactions and in Java EE you usually use the former,
your thought of using Named JPA queries without EntityManager is plain absurd and probably stems from misunderstanding of some kind (what would be the point of using named queries without an entity manager?),
saying "some elements from database" shows that you can't really tell the difference between records and mapped objects, in which case you probably should not use JPA at all.
I am not really expecting that you accept this answer. That's just my frustration taking over.
EDIT
OK, now that you mentioned JSF I understand more of your problem.
I assume you want to use JPA. In such case you have a choice of:
creating your own EntityManager (in such case you cannot have it injected; instead you have yo use an EntityManagerFactory and build your own). This is an "application managed EntityManager". You don't really want to do this.
using an injected EntityManaged ("conatiner managed EntityManager"). This is the standard choice.
Now you need a transaction. Since you should be using a JTA EntityManager, you will need a transaction object that is responsible for coordinating the whole thing. Again, you have two choices:
in a JSF bean, inject a UserTransaction (using #Resource annotation). This is messy, error-prone and takes a lot of boilerplate, but you will find all the necessary methods. You can create your own (application managed) EntityManager, call its joinTransaction method and then call begin-commit on UserTransaction. This is would be an "application managed transaction"
move your EntityManager code to EJB. It only takes a couple of lines of code and a single annotation (#Statless). All the code inside an EJB is - magically - wrapped inside a transaction that the container manages for you. This is the "container managed transaction" - the default and common choice.
Each of the things above could (and should) be expanded with some additional information. But the short path for you is:
create an EJB (a simple class with #Stateless annotation),
move the method that uses EntityManager to the EJB,
inject the EJB into your managed bean (using #EJB annotation) and call the relevant method.
The JTA transaction will happen around each call to any EJB method. This should get you started :-)
I use JTATransactionManager to manage Transactions. One piece of code that I want to wrap with Spring's #Transactional annotation has 2 database calls - one using Hibernate SessionFactory and another a plain JDBC. Both use the same dataSource. Hence, I expect both to be bound by the same Transaction.
But it does not look like one Transaction is used. Instead each opens its own Transaction. What could be the reason for this. ? How do I make sure to use a single Transaction to bind both these operations. ?
I can provide configuration and code if needed.
Make sure in both of your database calls, you use propagation as Propagation.NESTED as
#Transactional(propagation=Propagation.NESTED)
and in the wrapper method, you mention Propagation.REQUIRED orPropagation.REQUIRED_NEW` as
#Transactional(propagation=Propagation.REQUIRED)
or
#Transactional(propagation=Propagation.REQUIRED_NEW)
By doing this, you mention that both DB calls will inherit the transaction boundary of the wrapper method.
I am using Spring declarative database transaction management using the #Transactional annotation on my java methods.
In one case, I would like to explicitly commit the current transaction (the one wrapping the currently executing method) prior to the method returning.
How can this be done?
I have tried auto wiring the current HibernateTransactionManager from the spring context and using that to commit, but it doesn't commit the transaction.
The code I have tried is:
transactionManager.commit(transactionManager
.getTransaction(new DefaultTransactionDefinition()));
i have not tried but you might be able to do this with some trick which i can think of
get TransactionStatus using TransactionAspectSupport.currentTransactionStatus()
inject transaction manager to your bean (assuming you are using hibernate)
try to invoke doCommit(DefaultTransactionStatus status) in transaction manager.
try this out not sure it will work or not because as per spring doc
transaction
You are strongly encouraged to use the declarative approach to
rollback if at all possible. Programmatic rollback is available should
you absolutely need it, but its usage flies in the face of achieving a
clean POJO-based architecture.
i have not tested but if you set setRollbackOnly to TransactionStatus that might also do the job.
The nested transaction, that being seeked above, can be achieved using REQUIRES_NEW propogation, BUT by taking care of self invocation, as explained here
If I have a service class which calls three other service classes in a row, and each of those sub-services has to deal with a DAO object at some point, how can I make so that the wrapper service wraps them all into a single transaction? Will it be as simple as annotating the wrapper with #Transactional? What if the DAO is already marked as #Transactional?
The default transaction propagation in Spring framework is REQUIRED, which means that the transaction is created if it does not already exist or the code joins existing one:
Support a current transaction, create a new one if none exists. Analogous to EJB transaction attribute of the same name.
This is the default setting of a transaction annotation.
This means that if you wrap calls to three transactional methods in a single transactional method, they will all run within a single transaction. Just like that.
See also:
What is the right way to use spring MVC with Hibernate in DAO, sevice layer architecture
If you annotate the outer service as #Transactional and your DAOs are also #Transactional and called by the service they will by default join the outer transaction as you're hoping.
this is actually a question about nested transaction (http://en.wikipedia.org/wiki/Nested_transaction). with spring, (assume you are using version 3 and annotation), REQUIRED is default for transaction mode. If you set this model for your service methods, all methods wrapped by your "wrapper" service will use the host transaction, which means they will run in same transaction.
Title says it all: What is the difference between a UserTransaction and an EntityTransaction?
My rudimentary understanding is that UserTransaction is used when JTA is required (e.g. to do queries on mulitple things), and that EntityTransaction is used when JPA only is required (e.g. when the query is atomic).
Is that the only difference between the two or is there more to it than that?
My rudimentary understanding is that
UserTransaction is used when JTA is
required (e.g. to do queries on
mulitple things), and that
EntityTransaction is used when JPA
only is required (e.g. when the query
is atomic).
That's basically right, but your description of "multiple things" and "atomic" is a bit strange. JTA allows the developper to use distributed transaction to perform changes on multiples resources (database, JMS broker, etc.) atomically (all-or-nothing). If only one resource is accessed (e.g. one single database), you don't need JTA, but the transaction is still atomic (all-or-nothing). That's for instance the case when you use a regular JDBC transaction on one database.
Considering UserTransaction vs. EntityTransaction:
If JPA is use stand-alone, you use EntityTransaction to demarcate the transaction yourself.
If JPA is used within a managed environment where it integrates with JTA, you use UserTransaction. The EntityManager hooks itself into the JTA distributed transaction manager. The only subtlety I'm aware of considers the flush of the changes. When EntityTransaction is used, JPA know it needs to flush the changes. If transaction are controlled using UserTransaction, it needs to register a callback using JTA registerSynchronization, so that the changes are flushed to the database before the transaction completes. If you use EJB with CMT (container managed transaction), you don't even need to use UserTransaction: the app server starts and stops the transactions for you.
Related questions:
What is difference between UserTransaction and EntityManager.getTransaction() (duplicate)
XA and non-XA datasource with Spring/Hibernate (related)