How to handle distributed transaction using jpa - mysql

I have a requirement where I need to insert the reduced in two different databases MYSQL and mongodb. In the case of fail over scenario entire transaction should be rolled back.
Please help as early as possible. Need to implement this requirement.

First of all you have to define two database connections and thus also two different persistence units defined in your
persistence.xml
file.
After that, just create 2 separate EntityManagers in each DAO method.
Try the following:
persistFoo(Foo f) {
// Create these EntityManagers with a proper connection/persistence unit name
EntityManager emMySQL = //your MySQL db
EntityManager emMongo = //your Mongo db
EntityTransaction txMySQL = emMySQL.getTransaction();
EntityTransaction txMongo = emMongo.getTransaction();
try {
txMySQL.begin();
emMySQL.persist(f);
txMySQL.commit();
txMongo.begin();
emMongo.persist(f);
txMongo.commit();
} catch(Exception e) {
if(txMySQL.isActive()) {
txMySQL.rollback();
}
if(txMongo.isActive()) {
txMongo.rollback();
}
} finally {
emMySQL.close();
emMongo.close();
}
}

Related

Implementing with both Adapter Design Pattern and Facade Design pattern

I'm new to design patterns.
I'm implementing a tool which can connect to different databases as user need.
this is my code structure.
in controllers I have my API calls. Below I paste post APi call for get all databases in server
#PostMapping("/allDatabases")
public List<String> getDatabases(#RequestBody DatabaseModel db)
throws IOException, SQLException {
return migrationInterface.getAllDatabases(db);
}
for now I'm getting response by calling a method in interface inside service package.
But when database server is change(ex: postgres,mysql) I have to use different queries.
Ex:
public class PostgresPreparedStatements {
public PreparedStatement getAllDbs(Connection con) throws SQLException {
return con.prepareStatement(
"SELECT datname FROM pg_database
WHERE datistemplate = false;");
}
}
This query is not working in MySQL database. So I'll keep deferent prepared statements for deferent databases. My idea is calling to a BaseAdapter from controller and check server type like below.
public class BaseAdapter {
public void checkServerType(String server) {
switch(server) {
case "postgres" :
// postgres functions
break;
case "mysql" :
// mysql functions
break;
default:
break;
}
}
}
I want to call PostgresConnector.java if server is postgres. from Connector I want to call Facade to call functions and related queries.
Any idea how to do this?
please note: For now I'm implementing this for postgres and MySQL,but in future this should work with any database.
Adapter pattern is not used when you want to add new behaviour such as new databases in your case. The goal of adapter class is to allow other class to access the existing functionality. Adapter converts the interface of one class into something that may be used by another class.
It looks like BaseAdapter has a responsibility to choose SQL statement for different databases. We can paraphraze this responsibility like we want to have generated SQL query based on database. So it looks like
we can replace this switch statement with HashTable(Java) or Dictionary(C#). And this HashTable(Java) or Dictionary(C#) can be a simple factory that creates SQL queries. And our generated SQL queries can be strategies for concrete database.
So let's dive in code.
It looks like this is a place where Strategy pattern can be used:
Strategy pattern is a behavioral software design pattern that enables
selecting an algorithm at runtime. Instead of implementing a single
algorithm directly, code receives run-time instructions as to which in
a family of algorithms to use.
Let me show an example via C#. I am sorry I am not Java guy, however I provided comments about how code could look in Java.
We need to have some common behaviour that will be shared across all strategies. In our case, it would be just one GetAllDbs() method from different data providers:
public interface IDatabaseStatement
{
IEnumerable<string> GetAllDbs();
}
And its concrete implementations. These are exchangeable strategies:
public class PostgresDatabaseStatement : IDatabaseStatement // implements in Java
{
public IEnumerable<string> GetAllDbs()
{
return new [] { "PostgresDatabaseStatement" };
}
}
public class MySQLDatabaseStatement : IDatabaseStatement // implements in Java
{
public IEnumerable<string> GetAllDbs()
{
return new[] { "MySQLDatabaseStatement" };
}
}
public class SqlServerDatabaseStatement : IDatabaseStatement // implements in Java
{
public IEnumerable<string> GetAllDbs()
{
return new[] { "SqlServerDatabaseStatement" };
}
}
We need a place where all strategies can be stored. And we should be able to get necessary strategy from this store. So this is a place where simple factory can be used. Simple factory is not Factory method pattern and not Abstract factory.
public enum DatabaseName
{
SqlServer, Postgres, MySql
}
public class DatabaseStatementFactory
{
private Dictionary<DatabaseName, IDatabaseStatement> _statementByDatabaseName
= new Dictionary<DatabaseName, IDatabaseStatement>()
{
{ DatabaseName.SqlServer, new SqlServerDatabaseStatement() },
{ DatabaseName.Postgres, new PostgresDatabaseStatement() },
{ DatabaseName.MySql, new MySQLDatabaseStatement() },
};
public IDatabaseStatement GetInstanceByType(DatabaseName databaseName) =>
_statementByDatabaseName[databaseName];
}
and then you can get instance of desired storage easier:
DatabaseStatementFactory databaseStatementFactory = new();
IDatabaseStatement databaseStatement = databaseStatementFactory
.GetInstanceByType(DatabaseName.MySql);
IEnumerable<string> allDatabases = databaseStatement.GetAllDbs(); // OUTPUT:
// MySQLDatabaseStatement
This design is compliant with the open/closed principle.

MSDTC on server 'servername' is unavailable with linq to sql

I am using Transactionscope with linqtosql. I have the following code:
public bool Save(int Id, List<Student> students, List<Subject> subjects)
{
var isDataSaved = false;
using (TransactionScope scope = new TransactionScope())
{
try
{
// Save the students
SaveStudents(students);
// Save the subjects
SaveSubjects(subjects);
scope.Complete();
isDataSaved = true;
}
catch (Exception ex)
{
throw ex;
}
return isDataSaved;
}
}
In both the methods I am using the two tables : Students, Subjects present in the same database. The datacontext object dependency is setup using the constructor as mentioned in the below class:
public class StudentsRepository:IStudentsRepository
{
public StudentsRepository()
{
_dataContext = new SchoollDetailsDataContext(connectionString);
}
}
The same datacontext object is used in both the methods SaveStudents and SaveSubjects.
I am getting an exception : MSDTC on server 'servername' is unavailable.
As per my initial analysis this kind of error will occur where a database operation will be in my local database and another will be in a remote database.
Can anyone help me to know is there anything I am missing here?
You need to turn the MSDTC service on.
Start-->Control Panel --> Administrative Tools --> services.
Find the service Distributed Transaction Coordinator and start it.
By default its startup property is set to Manual so its switched off.

How to recover from database errors in Grails within a transaction

In short, what I am trying solve is how to recover from certain database errors in a Grails application using Hibernate and continue on with the transaction skipping over the failed row updates that are part of a batch of changes.
The application uses Grails 2.3.11 but I have also tried with version 1.3.8 with similar failed results.
Basically there is a Grails service class that iterates over a list of imported records and attempts to update associated master records appropriately. In certain situations exceptions might occur during the domain.save(flush:true) call e.g. org.hibernate.exception.DataException thrown due to issues like (Data truncation: Data too long for column ...).
At this point I have tried:
Disabling transactions
Using domainObj.withTransaction() for each individual record
Trying various #Transactional annotations
Calling domain.clearErrors() and domain.discard() after catching the exception
Tried using a nested service with Transactional annotation with noRollbackFor as shown below
A number of other approaches but nothing I've tried has worked
Example code:
#Transactional
class UpdateService {
public updateBatch(Integer batchId) {
...
list.each { record ->
record.value = 123
try {
nestedService.saveDomain()
} catch (e) {
record.clearErrors()
record.discard()
}
}
batch.status = "POSTED"
batch.save()
}
}
#Transactional
class NestedService {
#Transactional(propagation = Propagation.REQUIRED, noRollbackFor = RuntimeException.class)
public void saveDomain(domainObj) throws RuntimeException {
if (domainObj.validate() && domainObj.save(flush:true) {
log.info "domain $domain was saved"
}
}
}
Once an error occurs I can't seem to clear out the hibernate session. On each subsequent record being updated I receive the error:
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction
where it indicates the original failed domain id.
Revision:
Vahid, Thanks for the suggestions. I have tried that. I realized one issue is that I am passing objects across transactional boundaries. So I experimented with the NestedService class do something along the lines of:
#Transactional(propagation = Propagation.REQUIRE_NEW)
public void saveDomain(domainObj) {
def newObj = new Domain.get(domainObj.id)
newObj.properties = domainObj.properties
if (newObj.validate() && newObj.save(force:true) ) { ... }
I expected that to work but the original domainObj still fails even though I'm not calling the save on it. Very strange...
A simple approach would be to loop and then use validate(). If it does fail, then just store the id of the failed entity and proceed.
if(!domainObject.validate()){
// store Id for trying it again later ?
}else{
// Save
}

Lock statement vs AutoResetEvent for LocalDb Thread Synchronization

I am writing an application that utilizes Windows Phone's LocalDB feature. I realized that I need to ensure that only one thread is performing operations on a given database, so I have created an AutoResetEvent object to coordinate the various threads vying for access to the database. My code goes pretty much like this:
class SomeClass
{
AutoResetEvent DatabaseLock = new AutoResetEvent(true);
public async void AddData(Person person)
{
await Task.Run(() =>
{
MyDataContext db = null;
try
{
this.DatabaseLock.WaitOne();
db = MyDataContext.GetInstance();
db.People.InsertOnSubmit(person);
db.SubmitChanges();
}
finally
{
if (db == null)
db.Dispose();
this.DatabaseLock.Set();
}
}
}
}
Obviously that's not the real code, but it's the same general pattern. Anyway, I decided to use the AutoResetEvent object here, as I have seen suggested online in multiple locations. However, I would be inclined to use a lock {...} statement instead.
Is there any reason to use AutoResetEvent? I feel like it's slow compared to locking an object.
You should use an AutoResetEvent when you need to signal to another thread.
In this case, you're just locking a resource, so the lock statement would be a better choice.

What is the proper way to ensure EntityManager connections are closed?

There are 19 methods in our DAO layer, each is some variation of this:
public TicketProp saveTicketProp(TicketProp prop) {
EntityManager em = this.emf.createEntityManager();
try {
em.getTransaction().begin();
prop = (TicketProp) em.merge(prop);
em.getTransaction().commit();
return prop;
} finally {
em.close();
}
}
Meaning: In each method we handle our own transaction and close it in a finally block. We're testing a Jersey app, so our JUnit tests extend JerseyTest. Each test method instantiates a Grizzly container, runs the test, then shuts down the container. EntityManagerFactory is injected by spring. We're using JPA over Hibernate.
I'm monitoring the connections to our MySQL test DB and they're always high. One test alone runs the MySQL "Max_used_connections" variable to 38. For fun, I went and commented out all the em.close() calls, and the test still uses 38 connections.
I'm using Hibernate's built-in connection pooling (not for prod use, I know). I still expected some sort of intelligent pooling.
Am I handling the EntityManager wrong? How else can I close connections?
You should close the EntityManagerFactory at the end of your test. From the javadoc of EntityManagerFactory#close():
void javax.persistence.EntityManagerFactory.close()
Close the factory, releasing any resources that it holds. After a factory instance has been closed, all methods invoked on it will throw the IllegalStateException, except for isOpen, which will return false. Once an EntityManagerFactory has been closed, all its entity managers are considered to be in the closed state.
As a side note, you should actually rollback the transaction before closing the EM in the finally clause:
public TicketProp saveTicketProp(TicketProp prop) {
EntityManager em = this.emf.createEntityManager();
try {
em.getTransaction().begin();
prop = (TicketProp) em.merge(prop);
em.getTransaction().commit();
return prop;
} finally {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
if (em.isOpen()) {
em.close();
}
}
}
Why do you think that EntityManager.close() always physically closes underlying connection? It's up to connection pool (you probably need to configure it and set the maximum number of simultaneously open connections).