When should I close connection with database ?
I create connection one time when application starting, and then I use entity manager in this way:
public void createItem(TYPE item){
em.getTransaction().begin();
em.persist(item);
em.getTransaction().commit();
}
public class Connection { //creating connection (one time)
private static final String PERSISTENCE_UNIT_NAME = "ejb";
private static EntityManagerFactory factory;
private static EntityManager em;
static{
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
em = factory.createEntityManager();
}
public static EntityManager getEntityManager() {
return em;
}
}
I think it does not make sense to close connection evey each operation (like create) and create new connecion when I want to save item again.
You should not make entitymanager static, it should be an object that is removed after you do your transactions. This also mean that you should close it after your operation is finished. EntitymanagerFactory can stay static, you only need 1 for each program run. The reason as to why you should close it is that you are wasting resources on your device.
Longer/ better explanation on EMF https://stackoverflow.com/a/4544053/6270761
As far as i know the EntityManager is just abstraction to handle work-unit in ongoing transaction, if you created it using EntityManagerFactory which it is in current implementation you have to close it no matter what framework or template you are using.
If you obtained it using dependency injection (eg using EJB and #PersistenceContext annotation) you should not close it by hand i.e. it will close by embed dependency which you injected, the idea is to always close java.sql.Connection to prevent resource leak.
More over the application has finished using the entity manager factory, and/or at application shutdown, the application should close the entity manager factory. Once an EntityManagerFactory has been closed, all its entity managers are considered to be in the closed state as well.
Related
I'm working on a legacy codebase and saw something unsettling in our custom repositories. EntityManager is autowired into the repos directly. For example:
#Repository
public class OperationRepository {
// Yikes
private final EntityManager entityManager;
private QOperation operation = QOperation.operation;
#Autowired
public OperationRepositoryImpl(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Override
public Optional<Operation> findOneByIdAndType(Long operationId, OperationType type) {
JPAQuery<Operation> query = new JPAQuery<>(entityManager);
QOperation qOperation = QOperation.operation;
query.select(operation).from(operation)
.where(
operation.type.eq(type),
...
}
}
My understanding is that this is dangerous since EntityManager is not threadsafe and is being managed here as a field. I don't see an explicit definition in any of our configuration files to provide an EntityManager bean so am not sure what Spring does in this case.
I am going to start on the fix for using #PersistenceContext here instead but wanted to understand what the impact is on this being in production for so long and what consequences might have come from it.
Would we be limiting our connection pool size to the number of single entitymanagers in our repository beans? Are there any other dangers it could have caused? Or am I making too much of it?
It really depends on the configuration of your application context, which might get configured by Spring Boot if you are using that, but in general and with a typicals setup this is not a problem.
In such a setup the application context doesn't contain a single (or a limited set of) EntityManager instance but an EntityManagerFactory which can create EntityManager instances on demand.
And you don't get injected a normal EntityManager either, but a proxy which will point to different instances upon different calls, typically so that each thread has its own EntityManager and after a web request is completed the next request handled by the same thread gets a fresh instance.
If you are still concerned, I recommend to use a debugger to inspect the EntityManager and confirm that it is indeed a proxy and that it delegates to different actual instances for different threads.
You might also want to take a look at this question about Spring Scopes which is the underlying abstraction for this: Spring Bean Scopes
My problem is actually simple but I really do not find a good solution to it.
I've currently to manage several DB in my application:
one UNIQUE admin DB (with a static name);
one client DB, with a name depending on the client.
I'm using JPA and I would like to create dynamically EntityManagers for client DB. But when I create this programmatically, I get this error:
javax.persistence.TransactionRequiredException: joinTransaction has been called on a resource-local EntityManager which is unable to register for a JTA transaction.
Here is the code:
#Stateful
public class ServiceImpl implements Service{
private EntityManagerFactory emf;
private EntityManager em;
#PostConstruct // automatically called when EJB constructed and session starts
public void init() {
emf = Persistence.createEntityManagerFactory("punit");
em = emf.createEntityManager();
}
...
And
#Stateful(mappedName = "CustomerService")
public class CustomerServiceImpl extends ServiceImpl implements CustomerService {
#Override
public void create(Customer cust) {
getEm().joinTransaction();
getEm().persist(cust);
}
More generally, I'v got problems with JPA. I just would like to connect to two databases, do some CRUD operations on them. But I really don't know how to manage transactions (my first approach was to let the container manage it...).
If someone could help me, could be great!
NB: I'm using a Glassfish Java EE server and PGSql DBs.
In jpa, you can declare several prsistenceunits in the persistence.xml file.
At the point of injection, you can do something like this:
#PersistenceContext(unitName = "unitName0", properties={#PersistenceProperty(...)}
EntityManager emClient;
#PersistenceContext(unitName = "unitName1", properties={#PersistenceProperty(...)}
EntityManager emAdmin;
This way, you dont have to create the entity managers manually, hence you get the container transaction management.
NOT TESTED:
If you have dynamic database names, you would inject EntityManagerFactory
#PersistenceContext(unitName ="name")
EntityManagerFactory emf;
//at the point you want the EntityManager
Map<String, String> props; //put the connection property for the EM here
EntityManager em = emf.createEntityManager(props);
Based on the fact that in a J2EE environment we use the concept of DataSources, and ConnectionPooling, it would be nearly impossible to implement this kind of dynamic datasources, without resorting to manual creation of entitymanagerfactory.
This is my reasoning:
The server manages the connection pooling, and the jpa provider (such as eclipselink) uses jndi to determine the connection to the database. This implies that if you were to change the database name, then it must also have a connection pooling resources, and an associated jdbc resource. This will ofcourse negate what you want to do.
Basic solution: Create EntityManagerFactory manually and manually manage transactions.
Specify in the persistence xml that the unit is non-jta for this to work.
Then you can programmatically supply connection data based on user-session:
Something of this sort:
//this must be session specific.
class PersistenceSession{
static Map<String, String> clientSessionProps;
//When new session starts and a new client has logged in.
static void setClientConnectionProperties(Client client){
.....
}
static Map<String, String> getClientSessionProps(){
return clientSessionProps;
}
}
At the ejb level.
#Stateless
public class TestEntityFacade extends AbstractFacade<TestEntity> {
private EntityManagerFactory emf;
#PostConstruct
void init(){
emf = Persistence.createEntityManagerFactory("name");
}
#Override
protected EntityManager getEntityManager() {
return emf.createEntityManager(PersistenceSession.getClientSessionProps());
}
public TestEntityFacade() {
super(TestEntity.class);
}
void add(Entity e){
EntityManager em = getEntityManager();
em.getTransaction().begin();
.....
em.getTransaction().commit();
}
}
Actually very neat way how to do this is with CDI Producers, you can define a bean which will produce for your any number of custom Entity Managers, see the example.
#SessionScoped
public class EntityManagerProducer {
#Produces
#AdminDB
#PersistenceContext(unitName = "adminDB")
public EntityManaged adminDB;
#Produces
#UserDB
#PersistenceContext(unitName = "userDB")
public EntityManaged userDB;
}
This means that these two EntityManagers get created within every user session and than you can inject them to any bean with
#Inject
#UserDB
private EntityManager em; //if you want to use UserDB now
#UserDB and #AdminDB are your own defined Qualifiers. This leads to much more easier and readable code.
In few project I have been successfully using
#PersistenceUnit(unitName = "MiddlewareJPA")
EntityManagerFactory emf;
...
EntityManager entityManager = emf.createEntityManager();
to obtain EntityManager for Database connection, but some days ago I was trying to move my project to Jboss EAP 6.2 and it couldn't create EntityManager. I was googling it and I found that I should try change #PersistenceUnit to
#PersistenceContext(unitName = "MiddlewareJPA")
private EntityManager entityManager;
to obtain EntityManager. It worked but I don't know why. What is the difference bettween PersistenceUnit and PersistenceContext? What are pros and cons of each one? Where should we be using one of them?
PersistenceUnit injects an EntityManagerFactory, and PersistenceContext injects an EntityManager. It's generally better to use PersistenceContext unless you really need to manage the EntityManager lifecycle manually.
I don't know how it works exactly in the Java EE, but in Spring, when you specify #PersistenceContext annotation, it injects EntityManager. Where does it get EntityManager? It is wrong to create one EntityManager for the whole application lifetime by calling EntityManagerFactory.createEntityManager(). So instead a special implementation of EntityManager interface is used and instantiated directly. It has an internal mutable thread-local reference to a real EntityManager. Implementations of methods just redirect calls to this real EntityManager. And there is a servlet listener, that before each request obtain EM by calling EMF.createEntityManager() and assign it to that inner reference of special EM. Also this listener manages transactions by calling getTransaction().begin(), .commit() and .rollback() on the real EM. It is very simplified description of performed work. And I believe, that JEE container does the same thing, as Spring does.
In general case it is better to inject EntityManager, because with EntityManagerFactory and #PersistenceUnit you should create/destroy EntityManager every time by hands and manage transactions too.
EntityManager obtained via #PersistenceContext is called Container Managed EntityManager as container will be responsible for managing "EntityManager". EntityManager obtained via #PersistenceUnit / entityManagerFactory.createEntityManager() is managed in the application by the developer. (for e.g. managing lifecycle of EntityManager, releasing the resources acquired by EntityManager, etc.).
In our J2EE application, we use a EJB-3 stateful bean to allow the front code to create, modify and save persistent entities (managed through JPA-2).
It looks something like this:
#LocalBean
#Stateful
#TransactionAttribute(TransactionAttributeType.NEVER)
public class MyEntityController implements Serializable
{
#PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager em;
private MyEntity current;
public void create()
{
this.current = new MyEntity();
em.persist(this.current);
}
public void load(Long id)
{
this.current = em.find(MyEntity.class, id);
}
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void save()
{
em.flush();
}
}
Very important, to avoid too early commits, only the save() method is within a transaction, so if we call create(), we insert nothing in the database.
Curiously, in the save() method, we have to call em.flush() in order to really hit the database. In fact, I tried and found that we can also call em.isOpen() or em.getFlushMode(), well anything that is "em-related".
I don't understand this point. As save() is in a transaction, I thought that at the end of the method, the transaction will be committed, and so the persistent entity manager automatically flushed. Why do I have to manually flush it?
Thanks,
Xavier
To be direct and to the metal, there will be no javax.transaction.Synchronization objects registered for the EntityManager in question until you actually use it in a transaction.
We in app-server-land will create one of these objects to do the flush() and register it with the javax.transaction.TransactionSynchronizationRegistry or javax.transaction.Transaction. This can't be done unless there is an active transaction.
That's the long and short of it.
Yes, an app server could very well keep a list of resources it gave the stateful bean and auto-enroll them in every transaction that stateful bean might start or participate in. The downside of that is you completely lose the ability to decide which things go in which transactions. Maybe you have a 2 or 3 different transactions to run on different persistence units and are aggregating the work up in your Extended persistence context for a very specific transaction. It's really a design issue and the app server should leave such decisions to the app itself.
You use it in a transaction and we'll enroll it in the transaction. That's the basic contract.
Side note, depending on how the underlying EntityManager is handled, any persistent call to the EntityManager may be enough to cause a complete flush at the end of the transaction. Certainly, flush() is the most direct and clear but a persist() or even a find() might do it.
If you use extended persistence context all operations on managed entities done inside non-transactional methods are queued to be written to the database. Once you call flush() on entity manager within a transaction context all queued changes are written to the database. So in other words, the fact that you have a transactional method doesn't commit the changes itself when method exits (as in CMT), but flushing entity manager actually does. You can find full explanation of this process here
Because there is no way to know "when" the client is done with the session (extended scope).
Considering there is no #PersistenceContext available to inject the EntityManager, plus you need to manually manage Transactions, what is the best way to design such an application?
For the EntityManagerFactory/EntityManager, as far as I can see, you must have each DAO accepting an EntityManager in the costructor e.g.
public class DAOImpl implements DAO
{
private EntityManager em;
DAOImpl(EntityManager em){
this.em = em;
}
//all CRUD operations follow
}
The first question that rises is when do you call EntityManager#close()?
Point A: The way I see it, you are better off doing this in a Filter at the end of the request cycle, which implies that you associate the EntityManager with the current thread (using ThreadLocal?)
Second question is, how and when do you inject the EntityManager?
Considering there is a ServletContextListener where we create and close the EntityManagerFactory, we could have a static method as follows
public static EntityManager createEntityManager(){
return entityManagerFactory.createEntityManager(PERSISTENT_NAME);
}
but since we want to encapsulate creating the DAO, we could use a factory e.g.
public class DAOFactory
{
public static DAO dao(){
//return a new DAO
}
}
As per Point A we should use a ThreadLocal to create the DAO using the EntityManager for the current Thread.
For managing Transactions.
The best way I can think of (which mimics the JPA spec) is to create your own Transaction annotation and use reflection to inject the begin/commit/rollback operations.
You should then return a Proxy from the DAOFactory which handles the transactions
I wouldn't do all that. Why try to recreate the whole JPA spec yourself? You just need to be able to use JPA without a container.
Spring can help you with this. Try it.