Which method in BMP is used to avoid unnecessary round trips to the database? - ejb-3.0

If I'm using BMP bean, is there any method which avoids unnecessary roundtrips to database and increase the efficiency...
Does any of these method serve the purpose? (Question in a certification test)
ejbSave(), ejbStore() or ejbPersist()
In a multi-tiered architecture, with database, application server, and Web layers—you optimize performance by reducing the network traffic “round trip.” Best approach is said to be to start and stop transactions at the application server level, in the EJB container. So would like to know the methods help reduce unnecessary round-trips for that in Bean Managed persistence type beans....Am new to ejb.., so am trying to learn the concepts
ejbSave() and ejbpersist() do not exist...

You wouldn't have to deal with any of these methods: 'ejbSave(), ejbStore() or ejbPersist()'
If I'm using BMP bean, is there any method which avoids unnecessary roundtrips to database
Short Answer:
Yes, methods of EntityManager
Long Answer:
To avoid network round trips to the database, you'd just have to set the transaction boundaries correctly. When you use the methods provided by EntityManager (I'm talking about JPA), the methods act on the persistence context. The persistence context being a cache, real db hits are avoided until the commit happens.
Following is a section from the TomEE docs
JPA 101
If there's one thing you have to understand to successfully use JPA (Java
Persistence API) it's the concept of a Cache. Almost everything boils
down to the Cache at one point or another. Unfortunately the Cache is an
internal thing and not exposed via the JPA API classes, so it not easy to
touch or feel from a coding perspective.
Here's a quick cheat sheet of the JPA world:
A Cache is a copy of data, copy meaning pulled from but living
outside the database.
Flushing a Cache is the act of putting modified data back into the
database.
A PersistenceContext is essentially a Cache. It also tends to have
it's own non-shared database connection.
An EntityManager represents a PersistenceContext (and therefore a
Cache)
An EntityManagerFactory creates an EntityManager (and therefore a
PersistenceContext/Cache)
With you are
responsible for EntityManager (PersistenceContext/Cache) creating and
tracking...
-- You must use the EntityManagerFactory to get an EntityManager
-- The resulting EntityManager instance is a
PersistenceContext/Cache
-- An EntityManagerFactory can be injected via the #PersistenceUnit
annotation only (not #PersistenceContext)
-- You are not allowed to use #PersistenceContext to refer to a unit
of type RESOURCE_LOCAL
-- You must use the EntityTransaction API to begin/commit around
every call to your EntityManger
-- Calling entityManagerFactory.createEntityManager() twice results in
two separate EntityManager instances and therefor two separate
PersistenceContexts/Caches.
-- It is almost never a good idea to have more than one instance of
an EntityManager in use (don't create a second one unless you've destroyed
the first)
With the container
will do EntityManager (PersistenceContext/Cache) creating and tracking...
-- You cannot use the EntityManagerFactory to get an EntityManager
-- You can only get an EntityManager supplied by the container
-- An EntityManager can be injected via the #PersistenceContext
annotation only (not #PersistenceUnit)
-- You are not allowed to use #PersistenceUnit to refer to a unit of
type TRANSACTION
-- The EntityManager given by the container is a reference to the
PersistenceContext/Cache associated with a JTA Transaction.
-- If no JTA transaction is in progress, the EntityManager cannot be
used because there is no PersistenceContext/Cache.
-- Everyone with an EntityManager reference to the same unit in the
same transaction will automatically have a reference to the same
PersistenceContext/Cache
-- The PersistenceContext/Cache is flushed and cleared at JTA
commit time
Cache == PersistenceContext
The concept of a database cache is an extremely important concept to be
aware of. Without a copy of the data in memory (i.e. a cache) when you
call account.getBalance() the persistence provider would have to go read
the value from the database. Calling account.getBalance() several times
would cause several trips to the database. This would obviously be a big
waste of resources. The other side of having a cache is that when you call
account.setBalance(5000) it also doesn't hit the database (usually). When
the cache is "flushed" the data in it is sent to the database via as many
SQL updates, inserts and deletes as are required. That is the basics of
java persistence of any kind all wrapped in a nutshell. If you can
understand that, you're good to go in nearly any persistence technology
java has to offer.
Complications can arise when there is more than one
PersistenceContext/Cache relating the same data in the same transaction.
In any given transaction you want exactly one PersistenceContext/Cache for
a given set of data. Using a TRANSACTION unit with an EntityManager
created by the container will always guarantee that this is the case. With
a RESOURCE_LOCAL unit and an EntityManagerFactory you should create and use
exactly one EntityManager instance in your transaction to ensure there is
only one active PersistenceContext/Cache for the given set of data active
against the current transaction.

Related

Spring JPA: keeping the persistence context small

How can I keep the persistence context small in a Spring JPA environment?
Why: I know that by keeping the persistence context small, there will be a significant performance boost!
The main problem area is:
#Transactional
void MethodA() {
WHILE retrieving next object of 51M (via a stateless session connection) DO
get some further (readonly) data
IF condition holds THEN
assessment = retrieve assession object (= record from database)
change assessment data
save the assessment to the database
}
Via experiments in this problem domain I know that when cleaning the persistence context every 250 iterations, then the performance will be a lot better.
When I add these lines to the code, so every 250 iterations:
#PersistenceContext
private EntityManager em;
WHILE ...
...
IF counter++ % 250 == 0 THEN
em.flush()
em.clear()
}
Then I get errors like "cannot reliably perform the flush operation".
I tried to make the main Transactional read-only and the asssessment-save part 'Transaction-requires-new', then I get errors like 'operating on a detached entity'. Very strange, because I never revisit an open entity.
So, how can I keep the persistence context small?
Have tried 10s of ways. Help is really appreciated.
I would suggest you move all the condition logic into your query so that you don't even have to load that many rows/objects. Or even better, write an update query that does all of that in a single transaction so you don't need to transfer any data at all between your application and database.
I don't think that flushing is necessary with a stateless session as it doesn't keep state i.e. it flushes and clears the persistence context after every operation, but apart from that, I also think this this might not be what you really want as that could lead to re-fetching of data.
If you don't want the persistence context to fill up, then use DTOs for fetching the data and execute update statements to flush the changes.

Spring jpa: Do I need to add #Transactional annotation on retrieval queries

I am using EntityManger for the retrieval queries in my spring boot application. An example snippet is given below.
#Repository
public class EntityManagerUtil {
#PersistenceContext
private EntityManager entityManager;
public List<Employee> getAll(){
// Use entityManager here
}
}
I need some clarity on the below questions.
a. Is EntityManger will be created for every call (or) will it be a singleton? (I tried printing entityManager, it is returning the same object for all the calls)
b. Is this approach leads to any connection leaks?
c. Do I need to put #Transactional annotation on reading operations?
I am using spring boot version 2.0.3-release
a) See M Deinum's comments about the injected EntityManager being a proxy. The normal situation for JPA is to have an EntityManager tied to each thread, Spring sets this up for you and provides a proxy to delegate to the actual EntityManager. So this arrangement is safe.
b) Connection leaks happen when you don't return a database connection to the pool. Spring takes care of providing a connection and cleaning up resources so in the normal course of things you shouldn't get connection leaks. If you ignore the facilities Spring gives you like JdbcTemplate and insist on writing your own JDBC code, then you can cause resources to leak. If your code tries to use an EntityManager intended for another thread you will get an exception, it will not fail silently, and it will not (in itself) cause a connection leak.
c) You are using an RDBMS so you will have a transaction.
Apparently some people think transactions are optional, but they really aren't. If you don't specify them then Spring will wrap each operation in its own transaction. Not only are you just better off in general being explicit about this, but you can mark the transaction as readonly, which lets Spring perform some optimizations, see Oliver Drotbohm's answer for details. So maybe you can get by without it for some cases (such as, each http request results in only one database operation), but it is in your interest to use it.

#Transaction annotation between layers in Spring

What is the difference in using this #Transactional annotation in Domain/Service layer and Dao layer. Will it provide any advantage using in Domain layer.
It is good practice to use #Transactional in the service layer because it governs the logic needed to identify the scope of a database and/or business transaction. The persistence layer by design doesn't know the scope of a transaction.
DAOs can be made #Transactional like any other bean, but it's a common practice to use it in service layer. We tend to do this because we want separation of concerns. The persistence layer just retrieve / stores data back and forth from the database.
For example, if we want to transfer some amount from one account to another, we need two operations, one account needs to be debited other needs to be credited. So, the scope of these operation is only known by service layer and not persistence layer.
The persistence layer cannot know what transaction it's in, take for example a method person.updateUsername(). Should it run in it's own separate transaction always? there is no way to know, it depends on the business logic calling it.
Here a few thread you should read
Where does the #Transactional annotation belong?
Where should "#Transactional" be place Service Layer or DAO
The place you use #Transactional annotation specifies the scope of your transaction.
When using it in DAO layer you are specifying that each DAO operation will be committed in a transaction.
When using it in service you are specifying that each service operation (business unit) is committed in a transaction, this is recommended since usually service method represents a business unit which should be included in the same transaction since any failure should roll back the whole business unit.
#Transactional: There are two separate concepts to consider, each with it's own scope and life cycle:persistence context , database transaction
It look like u r more into database traction :
#Transactional annotation itself defines the scope of a single database transaction. The database transaction happens inside the scope of a persistence context.
The persistence context is in JPA the EntityManager, implemented internally using an Hibernate Session

Inject Session object to DAO bean instead of Session Factory?

In our application we are using Spring and Hibernate.
In all the DAO classes we have SessionFactory auto wired and each of the DAO methods are calling getCurrentSession() method.
Question I have is why not we inject Session object instead of SessionFactory object in prototype scope? This will save us the call to getCurrentSession.
I think the first method is correct but looking for concrete scenarios where second method will throw errors or may be have bad performance?
When you define a bean as prototype scope a new instance is created for each place it needs to be injected into. So each DAO will get a different instance of Session, but all invocations of methods on the DAO will end up using the same session. Since session is not thread safe it should not be shared across multiple threads this will be an issue.
For most situations the session should be transaction scope, i.e., a new session is opened when the transaction starts and then is closed automatically once the transaction finishes. In a few cases it might have to be extended to request scope.
If you want to avoid using SessionFactory.currentSession - then you will need to define your own scope implementation to achieve that.
This is something that is already implemented for JPA using proxies. In case of JPA EntityManager is injected instead of EntityManagerFactory. Instead of #Autowired there is a new #PersistenceContext annotation. A proxy is created and injected during initialization. When any method is invoked the proxy will get hold of the actual EntityManager implementation (using something similar to SessionFactory.getCurrentSession) and delegate to it.
Similar thing can be implemented for Hibernate as well, but the additional complexity is not worth it. It is much simpler to define a getSession method in a BaseDAO which internally call SessionFactory.getCurrentSession(). With this the code using the session is identical to injecting session.
Injecting prototype sessions means that each one of your DAO objects will, by definition, get it's own Session... On the other hand SessionFactory gives you power to open and share sessions at will.
In fact getCurrentSession will not open a new Session on every call... Instead, it will reuse sessions binded to the current session context (e.g., Thread, JTA Transacion or Externally Managed context).
So let's think about it; assume that in your business layer there is a operation that needs to read and update several database tables (which means interacting, directly or indirectly, with several DAOs)... Pretty common scenario right? Customarily when this kind of operation fails you will want to rollback everything that happened in the current operation right? So, for this "particular" case, what kind of strategy seems appropriate?
Spanning several sessions, each one managing their own kind of objects and bound to different transactions.
Have a single session managing the objects related to this operation... Demarcate the transactions according to your business needs.
In brief, sharing sessions and demarcating transactions effectively will not only improve your application performance, it is part of the functionality of your application.
I would deeply recommend you to read Chapter 2 and Chapter 13 of the Hibernate Core Reference Manual to better understand the roles that SessionFactory, Session and Transaction plays within the framework. It will also teach will about Units of work as well as popular session patterns and anti-patterns.

JPA2 Entities Caching

As it stands I am using a JSF request scoped bean to do all my CRUD operations. As I'm sure you most likely know Tomcat doesn't provide container managed persistence so in my CRUD request bean I am using EnityManagerFactory to get fold of enity manager. Now about the validity of my choice to use request scoped bean for this task, it's probably open for a discussion (again) but I've been trying to put it in the context of what I've read in the articles you gave me links to, specifically the first and second one. From what I gather EclipseLink uses Level 2 cache by default which stored cached entity. On ExlipseLink Examples - JPA Caching website it says that:
The shared cache exists for the duration of the persistence unit ( EntityManagerFactory, or server)
Now doesn't that make my cached entities live for a fraction of time during the call that is being made to the CRUD request bean because the moment the bean is destroyed and with it EntityManagerFactory then so is the cache. Also the last part of the above sentence "EntityManagerFactory, or server" gets me confused .. what precisely is meant by or server in this context and how does one control it. If I use the #Cache annotation and set appropriate amount of expire attribute, will that do the job and keep the entities stored on the servers L2 cache than, regardless of whether my EntityManagerFactory has been destroyed ?
I understand there is a lot of consideration to do and each application has specific requirements . From my point of view configuring L2 cache is probably the most desirable (if not only, on Tomcat) option to get things optimized. Quoting from your first link:
The advantages of L2 caching are:
avoids database access for already loaded entities
faster for reading frequently accessed unmodified entities
The disadvantages of L2 caching are:
memory consumption for large amount of objects
stale data for updated objects
concurrency for write (optimistic lock exception, or pessimistic lock)
bad scalability for frequent or concurrently updated entities
You should configure L2 caching for entities that are:
read often
modified infrequently
not critical if stale
Almost all of the above points apply to my app. At the heart of it, amongst other things, is constant and relentless reading of entities and displaying them on the website (the app will serve as a portal for listing properties). There's also a small shopping cart being build in the application but the products sold are not tangible items that come as stock but services. In this case stale entities are no problem and also, so I think, isn't concurrency as the products (here services) will never be written to. So the entities will be read often, and they will be modified infrequently (and those modified are not part of the cart anyway, an even those are modified rarely) and therefore not critical if stale. Finally the first two points seem to be exactly what I need, namely avoidance of database access to already loaded entities and fast reading of frequently accessed unmodified enteties. But there is one point in disadvantages which still concerns me a bit: memory consumption for large amount of objects. Isn't it similar to my original problem?
My current understanding is that there are two options, only one of which applies to my situation:
To be able to delegate the job of longer term caching to the persistence layer than I need to have access to PersistenceContext and create a session scoped bean and set PersistenceContextType.EXTENDED. (this options doesn't apply to me, no access to PersistenceContext).
Configure the L2 #Cache annotation on entities, or like in option 1 above create a session scoped bean that will handle long term caching. But aren't these just going back to my original problem?
I'd really like to hear you opinion and see what do you think could be a reasonable way to approach this, or perhaps how you have been approaching it in your previous projects. Oh, and one more thing, just to confirm.. when annotating an entity with #Cache all linked entities will be cached along so I don't have to annotate all of them?
Again all the comments and pointers much appreciated.
Thanks for you r answer .. when you say
"In Tomcat you would be best to have some static manager that holds onto the EntityManagerFactory for the duration of the server."
Does it mean I could for example declare and initialize static EntityManagerFactory field in an application scoped been to be later used by all the beans throughout the life of the application ?
EclipseLink uses a shared cache by default. This is shared for all EntityManagers accessed from an EntityManagerFactory. You do not need to do anything to enable caching.
In general, you do not want to be creating a new EntityManagerFactory per request, only a new EntityManager. Creating a new EntityManagerFactory is quite expensive, so not a good idea, even ignoring caching (it has its own connection pool, must initialize the meta-data, etc.).
In Tomcat you would be best to have some static manager that holds onto the EntityManagerFactory for the duration of the server. Either never close it, or close it when a Servlet is destroyed.

Resources