Just wondering if beginning a new transaction in Hibernate actually allocates a connection to the DB?
I'm concerned b/c our server begins a new transaction for each request received, even if that request doesn't interact with the DB. We're seeing DB connections as a major bottleneck, so I'm wondering if I should take the time narrow the scope of my transactions.
Searched everywhere and haven't been able to find a good answer. The very simple code is here:
SessionFactory sessionFactory = (SessionFactory) Context.getContext().getBean("sessionFactory");
sessionFactory.getCurrentSession().beginTransaction();
sessionFactory.getCurrentSession().setFlushMode(FlushMode.AUTO);
thanks very much!
a
According to the section 11.1. Session and transaction scopes of the Hibernate documentation:
A SessionFactory is an
expensive-to-create, threadsafe
object, intended to be shared by all
application threads. It is created
once, usually on application startup,
from a Configuration instance.
A Session is an inexpensive,
non-threadsafe object that should be
used once and then discarded for: a
single request, a conversation or a
single unit of work. A Session will
not obtain a JDBC Connection, or a
Datasource, unless it is needed. It
will not consume any resources until
used.
In order to reduce lock contention in
the database, a database transaction
has to be as short as possible. Long
database transactions will prevent
your application from scaling to a
highly concurrent load. It is not
recommended that you hold a database
transaction open during user think
time until the unit of work is
complete.
Now, to answer your question:
getting a Session does not immediately acquire a connection (the connection is lazy loaded)
but calling beginTransaction() will cause the load of the connection for the given Session
subsequent calls will reuse the same connection
Look at org.hibernate.impl.SessionImpl#beginTransaction() and go through the code for more details.
(Updated per Pascal Thivent's comment)
Each Session creates a database connection if there is a need for that - e.g. if a transaction is started. The connection is not opened with the mere creation of the session.
To overcome this, you can use a connecetion pool so that connections are reused. Or you can make sure (as it appears you did) that no transaction is started automatically.
(This discusses read-only transactions. Take a look.)
Related
Is an attached jOOQ Record (UpdatableRecord) thread-safe, i.e. can I attach (fetch) a Record in one thread, and store it later in another thread without negative effects? Should I detach it in the original thread and attach it back in the new thread?
I know about the jOOQ manual page about thread-safety of the DSLContext. I'm using the Spring Boot Autoconfiguration of jOOQ, so that should all be thread-safe (with Spring's DataSourceTransactionManager and Hikari pooling).
But the following questions remain:
How does an attached Record behave when a transaction in the original thread is opened, and store() is called in another thread either before or after the original transaction has been committed? Does jOOQ open a new connection every time for each operation?
Would the attached Record be keeping a connection open across threads, which might then lead to resource leaks?
A jOOQ record is not thread safe. It is a simple mutable container backed by an ordinary Object[]. As such, all the usual issues may arise when sharing mutable state across threads.
But your question isn't really about the thread safety of the record.
How does an attached Record behave when a transaction in the original thread is opened, and store() is called in another thread either before or after the original transaction has been committed? Does jOOQ open a new connection every time for each operation?
This has nothing to do with Record, but how you configure jOOQ's ConnectionProvider. jOOQ doesn't hold a connection or even open one. You do that, explicitly, or implicitly, by passing jOOQ a connection via a ConnectionProvider (probably via some Spring configured DataSource). jOOQ will, for each database interaction, acquire() a connection, and release() it again after the interaction. The Record doesn't know how this connection is obtained. It just runs jOOQ queries that acquire and release connections.
In fact, jOOQ doesn't even really care about your transactions (unless you're using jOOQ's transaction API, but you aren't).
Would the attached Record be keeping a connection open across threads, which might then lead to resource leaks?
No, a Record is "attached" to a Configuration, not a connection. That Configuration contains a ConnectionProvider, which does whatever you configured it to do.
Context
I have a RESTful API for a versus fighting game, using JAX-RS, tomcat8 and Neo4j embedded.
Today I figured that a lot of queries will be done in a limited time, I'm using embedded for faster queries but I still want to go as fast as possible.
Problem
In fact, the problem is a bit different but not that much.
Actually, I'm using a Singleton with a getDabatase() method returning the current GraphDatabaseServiceinstance to begin a transaction, once it's done, the transaction is closed... and that's all.
I don't know if the best solution for optimal perfs is a Singleton pattern or a pool one (like creating XX instances of database connection, and reuse them when the database operation is finished).
I can't test it myself actually, because I don't have enough connections to even know which one is the fastest (and the best overall).
Also, I wonder if I create a pool of GraphDatabaseService instances, will they all be able to access the same datas without getting blocked by the lock?
Crate only one on GraphDatabaseService instance and use it everywhere. There are no need to create instance pool for them. GraphDatabaseService is completely thread-safe, so you can not worry about concurrency (note: transaction are thread-bound, so you can't run multiple transactions in same thread).
All operations in Neo4j should be executed in Transaction. On commit transaction is written in transaction log, and then persisted into database. General rules are:
Always close transaction as early as possible (use try-with-resource)
Close all resources as early as possible (ResourceIterator returned by findNodes() and execute())
Here you can find information about locking strategy.
To be sure that you have best performance, you should:
Check database settings (memory mapping)
Check OS settings (file system)
Check JVM settings (GC, heap size)
Data model
Here you can find some articles about Neo4j configuration & optimizations. All of them have useful information.
Use a pool - definitely.
Creating a database connection is generally very expensive. Using a pool will ensure that connections are kept for a reasonable mount of time and re-used whenever possible.
Is a connection only returned to the Connection pool in a JPA application if i call
entityManager.close();
?
Can the connection backing the entitymanger change during its lifecycle?
thanks in advance
mojoo
The JPA spec doesn't define such things and its up to the implementation to manage connections. When a transaction is active you'd be safe to assume the connection is the same until commit, for obvious reasons. Once the txn ends it may be handed back, or it may be held depending on implementation (and you don't mention yours)
This depends on the JPA implementation and configuration.
In EclipseLink by default a connection is only held for the duration of an active (dirty) transaction. i.e. from the first modification or lock, until the commit or rollback. For non-transactional queries a connection is acquired on demand and returned after the query execution. This allows for maximal usage of connection pooling. So, normally em.close() does nothing.
You can configure this using the "eclipselink.jdbc.exclusive-connection.mode" persistence unit property. "Always" will hold a connection for the life of the EntityManager.
You can also use different connection pools for transactions, versus non-transactional reads. This is useful with JTA, as you can use a non-JTA DataSource for reads.
Is it possible to model the following using Hibernate + Spring.
Open session
Begin transaction
Do some work
Commit
Begin transaction
More work
Commit
Close session
I use the Spring TransactionTemplate which does both session + transaction lifetime scoping.
The reason is that sometimes I have a few stages in a business process and I would like to commit after each stage completes. However I would like to continue using the same persistent objects. If I have a separate session per transaction then I get transient/detached exceptions because the original session was closed.
Is this possible?
Yes, Hibernate's Sessions can begin and commit several transactions. What you need to do is to store open session somewhere, then reuse it. Note, that Session is not a thread-safe object, but if you're sure it won't have problems with concurrency, what you need is just to use TransactionSynchronizationUtils to bind a session to the thread resources and then unbind it when desired, you can find an example here or you can take a look at OSIV and its standard implementations.
This is a very complicated thing, it's much easier and thus desirable that you close your session right away and don't reuse it, because it may bring troubles:
The objects inside of cache are not automatically evicted, thus your Session will grow in size until OutOfMemory.
The objects inside of session are not flushed unless they are dirty, thus the chance that object was changed by another user is larger and larger. Ensure that only a single user is going to change writable objects.
If some exception happens during one of steps, you have to ensure you close the session. After exception occurred inside of Session, this object is not reusable.
If transaction was rolled back, the session is cleared by Spring, thus all your objects become detached. Make sure your discard everything if at least one of transactions was rolled back.
You could achieve this using the OpenSessionInView pattern. Spring provides a javax.servlet.Filter implementation which you could use if you're working in a servlet environment (question doesn't say so). This will ensure that your Hibernate session is kept open for the duration of the request rather than just for an individual transaction.
The Javadoc on this class is pretty comprehensive and might be a good starting point.
I know that Java EE's session object can store complex objects, like a connection to a database.
I'm pondering how to implement a certain application for a programming practice, made with Java EE. My first option to use a connection pool, which is very easy with Java EE.
I'm wondering, out of curiosity, and also to properly justify the decision, what are the pros and cons of creating a connection to the database any time a client starts a session and storing it there, against the use of a connection pool.
Thanks a lot.
A resource pool will optimise the handling of the resource (your database connection) in a way your system can cope with it. Even though you can end up out of resources if you have a lot of opened connections.
That is more likely to happen if you store your database connection in the session context. Web applications don't need to be connected all the time to a database, that connection can be stablished at the beginning of a new operation and closed at the end. Using a resource pool you return your connection back to the pool when you no longer need it, so a new user (session in the web paradigm) can use that resource you have already released instead of creating a new one.
The pool will also handle the scenario in which some resources have been idle for a long time (no one has used them in a specific amount of time) and then it will release those resources.
When storing a database connection in the session you are never releasing the resource but keeping a permanent reference to it that will last as long as the user session does. You may not face any issues in a short time with that, specially if there are really few users connected at the same time. But in real world applications you will definitively find them.
Thus, storing a database connection in the session context is considered as a bad practice.
EDIT: I forgot to mention that should only store Serializable objects in the session so, if the application server decides to passivate a session, it can be persisted and restored when the application server decides to reactivate it. A database connection is not a Serializable resource.
Using a connection pool allows you maximize the usability of your connections. This means less connections = less memory = less sockets etc. The reason a pool is better than saving in a session is what happens if someone drops out unexpectedly? If you have a connection in your session, you risk keeping that connection alive for a long time, possibly indefinitely.