ORM many-to-one and many-to-many relationships using JDBC DAO - java

I am writing a small tool for training purposes.
The main scope is to understand how to work with persistent data without using ORM tools.
So, there is a small DB with tables:
users(id, login, password, group_id)
groups(id, name, description)
roles(id, name, description)
// for many-to-many relationship between groups and roles.
groupsroles(group_id, role_id)
So, I have implemented a DAO pattern, with 3 entities : User, Role, Group.
The question is : what is the best way to implement the work with relationships?
How to share the same connection between UserDAO, GroupDAO, RoleDAO to use DB transactions ?

One option is to let the service start a JTA transaction. This will automatically be available to all code running in the same thread. Then use a managed connection pool, so connections automatically join the running JTA transaction.
You can do your usual JDBC work on the connections, just don't call commit() on them, but do call close() on them.
If your goal is only to understand persistence and you don't necessarily want to think about transactions at this moment, you can use stateless session beans (EJB beans). These will automatically start and commit the transaction for you. The Service can be the EJB that your clients will call and this one will automatically start the transaction. Your DAOs can be stateless session beans as well and can be injected with a data source.
e.g.
#Stateless
public class MyService {
#EJB
private UserDAO userDAO;
#EJB
private GroupDAO groupDAO;
#EJB
private RoleDAO roleDAO;
public void myMethod() {
User user = userDAO.getById(...);
Group group = groupDAO.getByUserId(...);
// more DAO stuff
}
}
#Stateless
public class UserDAO {
#Resource(mappedName="java:/myDS")
private DataSource dataSource;
public void getById(Long id) {
connection = dataSource.getConnection();
// do JDBC work on connection
}
}

It's easy to let DAOs share a connection, because it should be created by a service layer, passed into each DAO object, and closed. Just pass the connection around.
Another alternative would be to not share the connection between three DAOs. Rather than mke three queries, you could make one JOIN query, bring all the data back at once, and map it into objects. The penalty is more bytes on the wire, because you bring the parent data back for every child object.

Use a thread local to hold a reference to your connection. The DAO will use connection from the service layer when a connection is passed. When the caller (service layer) does not pass a connection , DAO will use the connection from thread-local. Thus all DAO can share same connection in a given thread.
TX management is as follows.
All transactions are initiated and ended in service layer. The DAO will not have any commit/rollback logic. Since connection is shared across all the DAO, the caller (service layer) is in full control of the transaction.

Related

when entitymanager(session) created in spring?

i read https://www.baeldung.com/spring-open-session-in-view article
According to this article, it says that the session is created in the request phase.
Spring opens a new Hibernate Session at the beginning of the request. These Sessions are not necessarily connected to the database.
But as far as I know, in Spring, when a transaction starts, it gets an entity manager (session). The reason is that there is no need to create an entity manager for logic that does not use JDBC.
#Transactional
#Service
public class DoService {
// when use this service EntityManager is created;
}
I wonder if I'm getting it wrong.

Transaction management in EJB 3.0 and hibernate

I am trying to understand the transactions management and try to use its power in my already existing application developed in Struts 2, EJB 3 and hibernate 5.2.
Now I have ejb in my business layer like below
#Stateless
#TransactionManagement(TransactionManagementType.CONTAINER)
public class MyEJb implements ejbxyz {
#Override
public void method(){
Dao dao=new Dao() //Dao class is simple java class
dao.fooMethod(); //this method updates some record
dao.barMethod(); // this method updates some other record
}
}
public class Dao{
fooMethid(){
Session session=sessFactory.openSession();
session.beginTransaction();
session.update(x);
}
barMethod(){
try{
Session session=sessFactory.getCurrentSession();
session.getNamedQuery("xyz").executeUpdate();
}catch(HibernateException ex){
session.getTransaction.rollback();
}
}
}
I understand that Transaction management should be done at service layer(at ejb in my case). But how can I achieve this over there. ?
Now the dependency is if barMethod() fails to update the record then I need to rollback the changes made in fooMethod. So basically I need both the methods to be done in one transaction.
When I execute the application it throws the below exception
Exception while barMethod getNamedQuery is not valid without active transaction
Its because I am not beginning any transaction in barMethod. But then I really dont want to start a new transaction and want to continue with the older transaction started in fooMethod.
Container managed transactions are indeed suported out of the box for EJB beans. However, your Dao class is not a managed bean - it is a regular pojo that you instantiate manualy - therefore it does not participate in any transaction started by your other ejb.
So move your Dao to separate file, annotate it with #Stateless and then inject it into your service using #EJB private Dao dao;
There is more to transactions in Ejb container though. You can control the transaction support on method level via #TransactionAttribute annotation, that specifies how should the container invoke your method with regard to transaction. That way you can control, whether your method requires its own transaction, or if it shall participate in a transaction initiated by the caller(e.g. when invoked from ejb bean). For more info have a look at official Java EE tutorial

Will Spring estabilish connection to DB, when I use transacional bean in non-transacional?

Good day, guys!
If I have non-transactional bean(BannerSizeServiceUntransact), which uses transactional bean(bannerSizeService), will Spring estabilish connection to DB, when I use non-transacional bean?
(I have many refused connections to PostgreSQL in log. I belive my logic does;t create new connection on each request, but may be I wrong.)
#Repository
public class BannerSizeServiceUntransactImpl implements BannerSizeServiceUntransact {
#Resource
BannerSizeService bannerSizeService;
public List<BannerSizeVO> sizesByType(String type) throws BannerServiceException{
return bannerSizeService.sizesByType(type);
} }
#Repository
#Transactional
public class BannerSizeServiceImpl implements BannerSizeService {
....
}
Yes, Spring will establish a database connection even when you're using beans that aren't marked #Transactional, so that's not the cause of your refused connections.
What's going to happen in this scenario is that when you invoke the call to bannerSizeService.sizesByType(type), Spring will start a new transaction, and when control returns to BannerSizeServiceUntransact.sizesByType(), it will end. So if BannerSizeServiceUntransact.sizesByType() did other database calls before or after the call to bannerSizeService.sizesByType(type), those calls would happen in separate transactions, one per DB call. (Not annotating a Service as #Transactional doesn't mean that transactions aren't used, just that they only span a single database call.)
Also note that if the method that calls BannerSizeServiceUntransact.sizesByType() was marked #Transactional, then the transaction started there will carry over all of the code you've shown here, because that transaction will start when that higher-up method is called and will end when it ends, and all of the code here will have executed while it was in effect. Not annotating something as #Transactional doesn't forbid its participation in an existing transaction, it just doesn't require the initiation of a new one.
Also, keep in mind that #Transactional controls transactions. Spring might end up making a new connection for each transaction it opens, or using only one and reusing it for each transaction, or rotating through a pool of connections (resulting in more than one but fewer than N connections for N transactions). It's guaranteed that if Spring talks to the database, there will be a connection in use, but you can't guarantee how many will be used over N calls simply by your #Transactional annotations. (Though of course you can set settings in your Spring config that might impact the number used, e.g. specifying a connection pool with a max size of 1.)

How does Spring Data Neo4j begin transaction work?

I have a comprehension question. I cannot understand how the database actions from the Neo4jTemplate like "getOrCreateNode()" belong to the surrounding transction. How is it implemented? The Neo4jTemplate would be shared in a multi-threaded environment? I cannot see a distinct membership of the transaction. I would understand if the actions are directly in the transaction object (e.g. tx.getOrCreateNode()).
#Service
public class TestService {
#Autowired
private Neo4jTemplate template;
public void save(IndexedTriple triple) {
GraphDatabase gdb = template.getGraphDatabase();
Transaction tx = gdb.beginTx();
Node subject = gdb.getOrCreateNode()
...
tx.success();
tx.finish();
}
}
Thanks in advance.
The below extract from the reference documentation pretty much sums it up. Use the spring transaction manager instead of using the Neo4j transactions and let spring take care of demarcation. Also, the transaction management is completely thread-safe. For you, I suggest using #Transactional annotation. If there is an existing transaction already, then spring joins that existing transaction as well.
Transactions
The Neo4jTemplate provides implicit transactions for some of its
methods. For instance save uses them. For other modifying operations
please provide Spring Transaction management using #Transactional or
the TransactionTemplate.

Why do we have to manually flush() the EntityManager in a extended PersistenceContext?

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).

Categories