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 2.0 genericdao and ejb3 and I would like to create (produce) dynamically EntityManagers for client DB.
The first entytymanger (properties saved in persistence.xml) to find the the client DB properties ( name, login, password, dialect ... ) stored in the admin DB.
I want to use
#PersistenceContext(name = "nscloud_PU",type= PersistenceContextType.EXTENDED )
and ejb3 to resolve the LazyInitializationException
Related
I have read many questions and answers about dynamic implementation of EntityManager with different schemas. I found also a solution using alter database session to set current schema (see below).
ALTER SESSION SET CURRENT_SCHEMA= "SCHEMA_NAME"
As the number of users using the application increases, this isn't a suitable way of routing anymore. Also, it would change to EntityManager on every time a new user login. The situation is as follows
1 database server
many schemas on that server, every user has their own schema.
I only need to change the schema name during runtime the schema name is retainable by logged in user
I'm using Spring with Hibernate 4.0 and Spring data JPA
I can't find a way to change the schema completely dynamically. Does someone know how to do it in spring?
I am creating a Springboot application with OpenJPA.
My requirement is that I need to connect to multiple datasources dynamically and the datasource credentials are obtained at runtime by calling some rest-endpoints.
Here is the controller class:
#RestController
public class StationController {
#Autowired
BasicDataSource dataSource;
I have a service which returns me the jdbc_url depending on the customer name:
public String getDSInfo(String customername){
// code to get the datasource info (JDBC URL)
}
My questions are:
Is there a way in which I can create datasources at runtime by getting datasource credentials by calling some other service (which takes the customer id and returns the customer specific datasource) ?
Since my application is a web based application, many customers will be accessing it at the same time, so how to create and handle so many different datasources?
NOTE:
The code will get information about the customer specific data source only by firing some service at the runtime, so I cannot hardcode the datasource credentials in the XML configuration file.
I found some implementations with Hibernate but i am using Springboot with OpenJPA. So need OpenJPA specific help.
It sounds like you want a multi-tenancy solution.
Datasources are easy to create programmatically, just use a DataSourceBuilder with your connection details pulled in from a central source (e.g. a central config database or Spring Config Server).
Then you'll need to look at a multi-tenancy framework to tie the datasources back to clients.
See here:
https://www.youtube.com/watch?v=nBSHiUTHjWA
and here
https://dzone.com/articles/multi-tenancy-using-jpa-spring-and-hibernate-part
The video is a long watch but a good one. Basically you have a map of customer data sources (from memory) that allow an entityManager to pick up a datasource from the map by using a thread scoped custom spring scope of "customer" which is set when a user for a particular customer somehow logs into your app.
Multi-tenancy on the database level: One way to separate data for multiple clients is to have individual databases per tenant.
Suppose you are working on webservice or web application.
A client will send tenant id as header parameter.
Write one filter and get the tenant details from the Cache by tenant id.
Set the schema name in the filter
for example:
MDC.put(Constants.MONGO_TENANT_DB, "uat");
MongoMultiTenancyInterceptor will get called before any DB operation/orm call.
String tenantDBName = MDC.get(Constants.MONGO_TENANT_DB);
LOG.info("Switching to database: "+tenantDBName);
if(StringUtils.isNotBlank(tenantDBName)){
MultitenantDatastoreFactory.setDatabaseNameForCurrentThread(tenantDBName);
}
Setting the Database name for current Thread.
MultitenantDatastoreFactory : Create datastore instance per tenant schema and store into HashMap.
MultitenantDatastoreFactory.getDS(): Returns the datastore from the Hashmap by schema name
UserRepository: It will get Datastore object from the factory method and perform any DB operation.
I have uploaded my project in GITHUB, you can download the code from GITHUB
https://github.com/vikashnitk50/spring-morphia-db-poc
i want to configure multiple datasources in Play framework 2.1 with jpa.
one is H2, and the other is Oracle.
so i added the code like this in application.conf:
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:file:E:/myproject/setup/db/monitor"
db.default.user=sa
db.default.password=sa
db.default.jndiName=DefaultDS
jpa.default=defaultPersistenceUnit
db.oracle.driver=oracle.jdbc.driver.OracleDriver
db.oracle.url="jdbc:oracle:thin:#10.1.20.10:1521:prjct"
db.oracle.user=LOG_ANALYSE
db.oracle.password=LOG_ANALYSE
db.oracle.jndiName=OracleDS
jpa.oracle=ojdbcPersistenceUnit
i don't know how to assign for jpa.oracle and give it a meaningless name. but it does not show any errors. should i change it and how?
the main problem is: how can i tell Play which entities are managed by default datasource what others by the other, oracle?
for example, class A, B's tables are in H2 and class C, D's tables are in oracle. what should i codding for these entities to assign the datasources?
Finally, i found the way to connect to different db sources.
in play, the api of jpa has no method named getJPAConfig("").
thers is another construction of em(), em("").
so i access the dbs as:
EntityManager em0 = JPA.em("default");
EntityManager em1 = JPA.em("oracle");
that's it!
I did not used this feature (yet) but you have to useone of the annotations on your Models:
#PersistenceUnit(name="default")
#PersistenceUnit(name="oracle")
Or when you query yourself you can alsow specify it as:
EntityManager em = JPA.getJPAConfig("oracle").em();
Is it possible to use EJB 3 with JDBC. I read somewhere, that it's allowed.
However, I hear that EJB 3 implementation uses JTA, by default. What does that mean for JDBC? Is it only for the transaction support? That means JTA is used for transaction when using JDBC code? Meaning that even local transactions are implemented as global transactions?
Does it mean it's not a good idea to use JDBC with EJB 3? Many people point me to JPA, but it's an ORM. I want to use SQL.
any suggestions?
1º
That means JTA is used for transaction when using JDBC code ?
And
Meaning that even local transactions are implemented as global transactions ?
The EJB container CAN MAKE USE of resource manager local transactions AS AN OPTIMIZATION TECHNIQUE for enterprise beans for which distributed transactions ARE NOT NEEDED.
It is a good idea do the following when using a declarative or programmatic transaction demarcation:
declare resources using the Resource annotation in the enterprise bean class or using the resource-ref element in the enterprise bean’s deployment descriptor
Something like (setter method or member field)
// mappedName points to a global mapping name
#Resource(mappedName="java:/DefaultDS")
private javax.sql.DataSource ds;
And inside a business logic method
If you are using a declarative transaction
Connection conn = ds.getConnection();
If you are using a programmatic transaction
Declare a setter or member field UserTransaction
#Resource
private UserTransaction ut;
And
ut.beginTransaction();
Connection conn = ds.getConnection();
ut.commit();
Take care of the following
If you are using a Stateful session bean, do the following in the PrePassivate callback method
Close all JDBC connections in the PrePassivate method and assign the instance’s fields storing the connections to null
regards,
You can look at this page, it does appear that you can combine EJB3 with JDBC.
http://www.java2s.com/Tutorial/Java/0415__EJB3/UseJDBCInEJB.htm
If you are using JPA2, you can use entityManager.unwrap(Connection.class) to get actual connection and use with your JDBC code.
For example:
Connection connection = entityManager.unwrap( Connection.class );
try (Statement stmt = connection.createStatement()) {
stmt.executeUpdate( "INSERT INTO MyTable( name ) VALUES ( 'my name' ) " );
}
Does it mean it's not a good idea to use JDBC with EJB 3? Many people
point me to JPA, but it's an ORM. I want to use SQL.
Sometime it's necessary, for performance or compatibility issues. I usually use this technique to execute PL/PSQL with array parameters, complex Posgis SQL, etc.