Can I create multiple Database Connections from one EntityManagerFactory? - java

I use JPA with Hibernate in my Servlet, which is hosted by Tomcat.
The database I use is MySQL.
I do not use JNDI or a Connection Pool.
This is my persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<persistence version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="pixxio-jpa" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>de.java2enterprise.onlineshop.model.AccessToken</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://192.168.88.88:3306/felix1_0"/>
<property name="javax.persistence.jdbc.user" value="felix1_0"/>
<property name="javax.persistence.jdbc.password" value="mypassword"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
</properties>
</persistence-unit>
</persistence>
This is the important code in my Servlet:
void doubleDatabaseConnection(PrintWriter out) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("pixxio-jpa", null);
EntityManager em = emf.createEntityManager();
EntityManager em2 = emf.createEntityManager();
getDatabaseSessionId(out, em);
getDatabaseSessionId(out, em2);
em.close();
em2.close();
emf.close();
}
void getDatabaseSessionId(PrintWriter out, EntityManager entityManager) {
Query q = entityManager.createNativeQuery("SELECT CONNECTION_ID();");
BigInteger result = (BigInteger) q.getSingleResult();
out.println("<br>Database Session Id: " + result);
}
This is printed by the servlet:
Database Session Id: 51317
Database Session Id: 51317
I assumed that the actual database connection is established, when the EntityManager is created. Therefore I assumed that the two MySQL-Connection-IDs from the two EntityManager instances differ.
Is it possible to create multiple distinct database connections from one EntityManagerFactory instance?
I want to note that changing the JPA provider is an option for me.

Hibernate use the same connection if you do not need a transaction.
If you start a transation, you get a new connection
EntityManagerFactory emf = Persistence.createEntityManagerFactory("pixxio-jpa", null);
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
EntityManager em2 = emf.createEntityManager();
em2.getTransaction().begin();
getDatabaseSessionId(System.out, em);
getDatabaseSessionId(System.out, em2);
em.close();
em2.close();
emf.close();
Updated
FYI: Hibernate use it's own connection pool if you do not set an connection pool (min=1; max=20).

Related

A JTA EntityManager cannot use getTransaction() in stored procedure call

I want to do an asynchronous transactional action in a ejb method by calling a stored procedure. When I call the methot I give below error:
java.lang.IllegalStateException: A JTA EntityManager cannot use getTransaction()
Bean
#Stateless
public class FileSearchDAO {
private static Logger logger = LoggerFactory.getLogger(FileSearchDAO.class);
#PersistenceContext(unitName = "FileSearchPU")
private EntityManager entityManager;
#Asynchronous
public Future<String> saveFile(String fileNo, List<String> runningFiles) {
try {
entityManager.getTransaction().begin();
entityManager.createNativeQuery(
" BEGIN prc_save_file (:fileNo); END;")
.setParameter("fileNo", fileNo).executeUpdate();
entityManager.getTransaction().commit();
runningFiles.remove(fileNo);
return new AsyncResult<>(fileNo);
} catch (Exception ex) {
ex.printStackTrace();
return new AsyncResult<>(ex.getMessage());
}
}
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="FileSearchPU" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>jdbc/FileSearchDS</jta-data-source>
<properties>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.transaction.jta.platform"
value="${hibernate.transaction.jta.platform}"/>
</properties>
</persistence-unit>
</persistence>
I haven't any Entity class. I just want to call the stored procedure which updates some table.
In a JTA managed datasource container handles transactions in a distributed way so also handling concurrency outside your application for example.
EntityManagers transaction can not be used because it is local transaction so something that is then not handled outside your application. Read also this post for more information.
If you need transaction you should use UserTransaction
#Resource
UserTransaction utx;
To use it your annotate your bean
#TransactionManagement(TransactionManagementType.BEAN)
and use transaction like
utx.begin();
...
utx.commit(); // utx.rollback();

Specifying database name with Eclipselink to SQLServer db?

I'm new to ElcipseLink and JPA. I've successfully set up my persistence.xml and EclipseLink library. However, when trying to retrieve data from the server, I get invalid object name: dbo.Material.
My values are stored in the leermiddelen database. The scheme is dbo and the table is Material. When I try to specify the cataloge name (leermiddelen), then I get an error that specifying the database name is not supported in Azure.
A little help? (btw, when manually connection with a connection string and the driver from Microsoft, it does work)
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<class>models.Material</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<property name="javax.persistence.jdbc.url"
value="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"/>
<property name="javax.persistence.jdbc.user" value="xxxxxxxxxxxx"/>
<property name="javax.persistence.jdbc.password" value="xxxxxxxxxx"/>
</properties>
</persistence-unit>
and the java code:
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("test");
EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction userTransaction = entityManager.getTransaction();
try {
userTransaction.begin();
#SuppressWarnings("unchecked")
List<Material> materials = entityManager.createQuery("SELECT e from Material e").getResultList();
System.out.println("Getting materials list...");
for (Iterator<Material> iterator = materials.iterator(); iterator.hasNext(); ) {
Material m = (Material) iterator.next();
System.out.println(m.toString());
}
entityManager.getTransaction().commit();
} catch (Exception e) {
entityManager.getTransaction().rollback();
}
entityManager.close();
entityManagerFactory.close();
}
Finally the error:
[EL Warning]: 2016-04-05 11:16:13.426--UnitOfWork(1690796457)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.2.v20151217-774c696): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid object name 'dbo.Material'.
Error Code: 208
Call: SELECT Number, Amount, CanReserve, Description, Firm, IsAvailable, Name, PhotoUrl, Price FROM dbo.Material
Conclusion for the question. It seems that the issue was caused by the incorrect jdbc url. The jdbc url for Azure SQL Database is as below.
jdbc:sqlserver://<hostname>.database.windows.net:1433;database=<database-name>;user=<username>#<hostname>;password={your_password_here};encrypt=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;
For getting the connection string on Azure portal, please see https://azure.microsoft.com/en-us/documentation/articles/sql-database-develop-java-simple-windows/#step-4-get-connection-string.

JPA on MFP Java adapter

I've created a Java adapter in MFP 7.0. The adapter is running on the local development server (Liberty). Since I couldn't find any references in the documentation, is there a possibility to use JPA within the Java adapter to access DB data?
Where do I need to put the persistence.xml?
Is there any configuration I have to do on the Liberty profile server.xml?
Where do I need to put the DB driver's library jar (EclipseLink)?
Attached you'll find the code from the Java adapter:
#GET
public String performJPAQuery(){
String result = null;
Person marco = new Person();
marco.setId(1);
marco.setName("Marco");
// connection details should be loaded from persistence.xml
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa-test");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(marco);
tx.commit();
// Querying the contents of the database using JPQL query
Query q = em.createQuery("SELECT p FROM Person p");
#SuppressWarnings("unchecked")
List<Person> results = q.getResultList();
logger.info("List of persons\n----------------");
for (Person p : results) {
logger.info(p.getName() + " (id=" + p.getId() + ")");
}
// Closing connection
em.close();
emf.close();
return result;
}
This is how my persistence.xml looks like:
<?xml version="1.0"
encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="jpa-test" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.sample.Person</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.sqlite.JDBC" />
<property name="javax.persistence.jdbc.url" value="jdbc:sqlite:sample.db" />
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.ddl-generation.output-mode" value="database" />
</properties>
</persistence-unit>
</persistence>
That is definitely possible. The location of the persistence.xml file should be as described here. Besides that, you will have to either:
use the connection using JNDI (in which case you do not need the javax.persistence.jdbc.url parameter).
along to the javax.persistence.jdbc.url parameter put the user credentials to your DB in persistence.xml (if you go for this option google for it, as it depends on the JPA/EclipseLink vesion, but probably this is a good start).
Instantiate manually EVERYTHING, in which case you do not need the persistence.xml file. This option is much more complicated, but also more flexible. I did it with Hibernate once, thus cannot help you with EclipseLink.

Is there a non-commercial Hibernate query checker?

We are using Hibernate at my workplace on some project and I had to modify some queryes recently. I found it really cumbersome to modify a query, run an ant smart or ant refresh and see whether my query works. When I asked one of my colleagues he told me that it is the way we use it.
Do you have any idea how can I speed up this process? I'm looking for a tool which can connect to a database (we are using PGSQL) and run my Hibernate query there and show the results without touching ant.
For example I would be able to try this:
#Query(query = "SELECT DISTINCT l FROM Line l, IN(l.workplaces) w WHERE w.workshop.sid=:wsid", params = "wsid")
JBoss Tools for eclipse has a HQL editor that you can open from the hibernate perspective, you can test hql queries there.
We have a junit-Test for hibernate which uses the derby database as a in-memory databse. This will create the database in derby with all tables and you should be able to execute the query, to see if it is valid.
We have all queries in the orm.xml, so those queries are already checked when creating the EntityManager.
setup
private static EntityManagerFactory emf;
private static EntityManager em;
#BeforeClass
public static void before()
{
emf = Persistence.createEntityManagerFactory("persistenztest");
em = emf.createEntityManager();
}
test
#Test public void test()
{
Query q = em.createQuery(YOUR_QUERY_HERE);
List<?> list = q.getResultList();
}
Persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="persistenztest" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<mapping-file>orm.xml</mapping-file>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.EmbeddedDriver" />
<property name="hibernate.connection.url" value="jdbc:derby:memory:sa;create=true;territory=de_DE;collation=TERRITORY_BASED:SECONDARY;"/>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/>
<property name="hibernate.cache.use_query_cache" value="false"/>
<property name="hibernate.cglib.use_reflection_optimizer" value="false" />
</properties>
</persistence-unit>
</persistence>

Problem on jboss lookup entitymanager

I have my ear-project deployed in jboss 5.1GA.
From webapp i don't have problem, the lookup of my ejb3 work fine!
es:
ShoppingCart sc= (ShoppingCart)
(new InitialContext()).lookup("idelivery-ear-1.0/ShoppingCartBean/remote");
also the iniection of my EntityManager work fine!
#PersistenceContext
private EntityManager manager;
From test enviroment (I use Eclipse) the lookup of the same ejb3 work fine!
but the lookup of entitymanager or PersistenceContext don't work!!!
my good test case:
public void testClient() {
Properties properties = new Properties();
properties.put("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");
properties.put("java.naming.factory.url.pkgs","org.jboss.naming:org.jnp.interfaces");
properties.put("java.naming.provider.url","localhost");
Context context;
try{
context = new InitialContext(properties);
ShoppingCart cart = (ShoppingCart) context.lookup("idelivery-ear-1.0/ShoppingCartBean/remote"); // WORK FINE
} catch (Exception e) {
e.printStackTrace();
}
}
my bad test :
EntityManagerFactory emf = Persistence.createEntityManagerFactory("idelivery");
EntityManager em = emf.createEntityManager(); //test1
EntityManager em6 = (EntityManager) new InitialContext().lookup("java:comp/env/persistence/idelivery"); //test2
PersistenceContext em3 = (PersistenceContext)(new InitialContext()).lookup("idelivery/remote"); //test3
my persistence.xml
<persistence-unit name="idelivery" transaction-type="JTA">
<jta-data-source>java:ideliveryDS</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop" /><!--validate | update | create | create-drop-->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
</properties>
</persistence-unit>
my datasource:
<datasources>
<local-tx-datasource>
<jndi-name>ideliveryDS</jndi-name>
...
</local-tx-datasource>
</datasources>
I need EntityManager and PersistenceContext to test my query before build ejb...
Where is my mistake?
Server-side EntityManager cannot be serialized so that you can use it as a client side EntityManager. That would mean that EntityManager referenced on the client-side still can talk to the database, use connection pool, etc. It is impossible (think of firewall, which protects database server, for instance).
If you need to test JPA, use local EntityManager without JTA transactions. If you want to test EJBs you need to simulate whole EJB container. You can use Spring Pitchfork or Glassfish 3 embedded container (the latter option is easier).
I need to test JPA, use local EntityManager without JTA transactions!
I followed your suggestion:I created new persistence.xml with a new persistence-unit
<persistence-unit name="ideliveryTest" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>it.idelivery.model.Category</class>
<class>it.idelivery.model.User</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/application"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.password" value=""/>
</properties>
</persistence-unit>
and in my test case:
try {
logger.info("Building JPA EntityManager for unit tests");
emFactory = Persistence.createEntityManagerFactory("ideliveryTest");
em = emFactory.createEntityManager();
} catch (Exception ex) {
ex.printStackTrace();
fail("Exception during JPA EntityManager instanciation.");
}
work fine!
In my maven project i put persistence.xml with persistence-unit type="RESOURCE_LOCAL" in src/test/resources
and i put persistence.xml with persistence-unit type="JTA" in src/main/resources
by this way I have two separates enviroment. One for test and one for production.
it's a best practice?

Categories

Resources