Update: It seems it's failing after one insert, #412, fails a not null constraint at the database level. The transaction is probably rolling itself back. Given this setup, is it possible to get a new transaction established?
I'm trying to insert a lot of rows into my oracle database, and JPA works just fine until about the 400th insert. I expect to have several thousand rows to insert.
Here's my psuedo-code (shortened for clarity) & persistence.xml:
#Stateless
public class LocalContentService
{
#Inject EntityManager em;
public void mySavingMethod(){
for(Foo foo : fooDao.fetchAllFoos()){
Bar bar = new Bar(foo);
em.persist(bar);
em.flush();
em.clear();
log.debug("Saved content for: " + bar.getId());
}
}
<persistence-unit name="databaseTest" >
<jta-data-source>java:/jdbc/testDS</jta-data-source>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<class>org.myorg.Bar</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" />
<property name="hibernate.use_sql_comments" value="true" />
</properties>
</persistence-unit>
After roughly 400 rows, I get this error message and all subsequent inserts fail:
ERROR [stderr] (http--127.0.0.1-8080-1)
javax.persistence.TransactionRequiredException: JBAS011469:
Transaction is required to perform this operation (either use a
transaction or extended persistence context)
So my question is two fold
1) What on earth happened to my transaction midway through the process? Can it be avoided?
2) Is there a better approach to doing a bulk insert like this one (keeping in mind that i'm loading a bunch of Foo's and they need to be transformed into Bar's before persisting.
I'm running inside a jBoss 7.1.1.Final AS and hibernate-jpa-2.0-api
Related
In my application I'm using Eclipselink as ORM for OracleDB and I encountered performance problem.
I'm executing code like this:
entityManager
.createNamedQuery(RoleToPermissionEntity.FIND_BY_APPLICATION_ROLE, RoleToPermissionEntity.class)
.setParameter(RoleToPermissionEntity.APPLICATION_ROLES_QUERY_PARAM, applicationRoles)
.getResultList();
with named query:
SELECT mapping
FROM RoleToPermissionEntity mapping
WHERE mapping.applicationRole IN :applicationRoles
ORDER BY mapping.id
Entity manager is set by #PersistenceContext.
For 3 given application roles application gets 123 rows (from 393), 9 column each (2 Timestamps with time zone, 3 numbers, 4 short varchars).
I checked time of execution as difference between System.nanoTime() before and after execution of given code. It's about 550 ms, no matter if it's executed 1st time or 10th in a row. And my assumption is that it should be much faster.
My first guess was problem with query, so I checked Eclipselink logs. Executed query is:
SELECT *all_columns*
FROM *table_name*
WHERE (APPLICATION_ROLE IN (?,?,?)) ORDER BY ID
bind => [3_application_roles]
Looks ok for me. I tried to execute it as native query, but result is the same. I tried also other queries like SELECT * FROM table_name, but time still is about 500-600 ms.
I wanted to have some comparison for this time so I created database connection manually and executed query like:
Class.forName("oracle.jdbc.driver.OracleDriver");
connection = DriverManager.getConnection(database_args);
Statement statement = connection.createStatement();
statement.executeQuery(query);
I executed it for several times, first (when connection was established) took quite a long time, but next took like 50-60 ms.
My second guess was problem with connection pool. I tried to find something in Eclipselink docs and I noticed only that parameters:
<property name="eclipselink.connection-pool.default.initial" value="1"/>
<property name="eclipselink.connection-pool.default.min" value="16"/>
<property name="eclipselink.connection-pool.default.max" value="16"/>
should be set. They are, but the problem still exists.
Content of my persistence.xml:
<persistence>
<persistence-unit name=unit transaction-type="JTA">
<jta-data-source>datasource</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<!-- cache needs to be deactivated for multiple pods -->
<!-- https://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching -->
<shared-cache-mode>NONE</shared-cache-mode>
<properties>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.logging.level.sql" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
<!--<property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>-->
<property name="eclipselink.weaving" value="false"/>
<property name="eclipselink.target-database"
value="org.eclipse.persistence.platform.database.oracle.Oracle12Platform"/>
<property name="eclipselink.connection-pool.default.initial" value="1"/>
<property name="eclipselink.connection-pool.default.min" value="16"/>
<property name="eclipselink.connection-pool.default.max" value="16"/>
</properties>
</persistence-unit>
</persistence>
What can I do to fix this behavior?
After few next hours I found the problem. Default fetch size of OJDBC is 10, so with increasing number of rows to fetch time increases very fast.
What is strange: this was my first idea, so I tried to set <property name="eclipselink.jdbc.fetch-size" value="100"/> in persistence.xml. It didn't work, so I jumped to other solutions. Today I set it on single query by query.setHint("eclipselink.jdbc.fetch-size", 100) and it works.
I have an issue here and I must assume someone else must have run into this before. It has been 3 weeks now and I have ran out of options nou.
Environment:
Jboss eap 7
Java 8
Java EE 7
Postgres
Hibernate 5x
Linux
The idea is to be able to write to two data sources in a single transaction using the xa-resource for my transaction management. I have two databases both with different tables represented by different entities as such.
My service bean is called by a managed bean from the war layer through an injected service interface at post construct.
My service implementation has an injected entity manager(em) annotated with the persistence context specifying the target database as a “unitName”. The service bean calls the entity interface implementation passing the chosen em as a param, eventually the em is received by the base entity that in turn does the db operations.
My application is divided into 3 modules/layers web=war, services=jar, and domain=jar with an EAR as the main archive. My problem is actually in the back-end.
I had first added in my persistence xml the following:
Created 2 persistence units (PU1 has 15 entities, PU2 has 17 listed in class element)
transaction-type = JTA
exclude-unlisted-classes = false and
hibernate.hbm2ddl.auto is = update
I have a base entity, entities and also have a repository package that holds my interfaces and their implementations to interact with my databases.
Now when i run my setup like this, both my databases have exactly 32 tables each and my tables have some of the columns merged, i.e. I have table1 with fields a, b, and c in db1 then I also have table1 (same name) in db2 with fields d, e, and f and both the tables in their database end up with columns a, b, c, d, e, and f.
If I manipulate my persistence.xml as below:
<persistence-unit name="PU1" transaction-type="JTA">
<jta-data-source>java:jboss/datasources/db1</jta-data-source>
<properties>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
</properties>
<class>domain.org.PemsBusinessArea</class>
...
</persistence-unit>
<persistence-unit name="PU2" transaction-type="JTA">
<jta-data-source>java:jboss/datasources/db2</jta-data-source>
<properties>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
</properties>
<class>domain.org .KeyFields</class>
...
</persistence-unit>
and I deploy and run my application I end up with the exception:
Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:79)
at org.hibernate.loader.Loader.getResultSet(Loader.java:2117)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1900)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1876)
at org.hibernate.loader.Loader.doQuery(Loader.java:919)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:336)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:501)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:371)
at Caused by: org.postgresql.util.PSQLException: ERROR: column plexusbusi0_.name does not exist
and the column “name” exists in the target database table.
Is there anyone who can help me with the above situation? Thanks in advance.
So it turns out I had missed specifying the target PU in one of my service bean methods. After that change, all is now working fine.
I'm facing a problem and have no idea what's going wrong. The cenary:
Hibernate 5
Apache Tomcat 9
JSF 2
No Spring. It's important to say because I saw this problem happening realted with Spring use, but this is not my case.
The datasource was correctly configured on Tomcat, and the Hibernate also creates the tables and update schemma correctly for each new Entity.
The problem is when I try to persist a new Entity, nothing happens. Then I tried to include "flush()" call... but then I've got an error saying I have no transaction active:
javax.persistence.TransactionRequiredException: no transaction is in progress
It seems to be a problem related with a transaction requirement, but I have also tried:
include "#Transactional" annotation on method;
include "#Transactional" annotation on class;
Force begin transaction with "beginTransaction()" call but then I've got a NullPointer;
So... I don't know what do to.
Follow you'll see my relevant code. Can you help me to solve this problem?
persistence.xml file:
<persistence-unit name="hospitalPU" transaction-type="RESOURCE_LOCAL">
<description>
Persistence unit for Hibernate
</description>
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<non-jta-data-source>java:comp/env/jdbc/hospitalDatasource</non-jta-data-source>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.default_catalog" value="hospital" />
<property name="hibernate.connection.datasource" value="java:comp/env/jdbc/hospitalDatasource"/>
<property name="hibernate.id.new_generator_mappings" value="false" />
</properties>
</persistence-unit>
My Entity:
#Entity(name="Dominio")
#Table(name="Dominio")
public class Dominio implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Integer id;
here goes another fileds and getters/setters...
On my managed bean, I have:
#PersistenceUnit
private EntityManagerFactory emf;
And:
protected synchronized EntityManager getEntityManager() {
if (emf == null) {
emf = Persistence.createEntityManagerFactory("hospitalPU");
}
return emf.createEntityManager();
}
It seems to work fine, but the problem happens here:
With this, nothing happen and no Exception occours. Just NOTHING happens:
getEntityManager().persist(getDominio());
With this, I have "javax.persistence.TransactionRequiredException: no transaction is in progress":
getEntityManager().persist(getDominio());
getEntityManager().flush(); //exception occours here!
What am I doing wrong? Thanks in advance for you all!
you need to more configure the persistence.xml or hibernate.cfg.xml. you can refer bellow link to configure these xml files.
https://gist.github.com/imanoleizaguirre/3819393
http://www.journaldev.com/7122/jsf-spring-hibernate-integration-example-tutorial
http://www.javaknowledge.info/simple-crud-using-jsf2hibernate-integration-and-mysql/
This one here clearly explains what is the problem:
"javax.persistence.TransactionRequiredException: no transaction is in progress"
First, you have clearly mentioned that you are using a Non-JTA datasource. meaning that the container will no longer manage for you transaction boundaries. You must begin and commit/rollback transactions on your own. You therefore need to follow the following:
EntityManager em = ....
EntityTransaction et = em.getTransaction();
try {
et.begin();
em.persist(entity);
et.commit();
} catch (Exception ex) {
et.rollback();
throw new RuntimeException(ex);
}
I'm developing a Java Web Project using JPA (EclipseLink) to connect with our databases. I have a persistence unit where I configured the database where my data is going to persisted. The question is that I also have to access another database that is already created and populated with info, and I just want to access one table of this database to retrieve some information. How can I access it using JPA just to retrieve info (neither save nor update anything).
After setting up your entity managers you can just run a native query :
entityManager.createNativeQuery("SELECT ...");
So, you can create another persistent-unit poiting to your other database
<persistence-unit name="read-and-write-database">
...
<properties>
<!-- conection -->
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/database-write" />
<.../>
</properties>
</persistence-unit>
<persistence-unit name="read-database">
...
<properties>
<!-- conection -->
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/database-read" />
<.../>
</properties>
</persistence-unit>
And, in a SE environment, you would something like that to create the EntityManager:
EntityManagerFactory readWriteEntityManagerFactory = Persistence.createEntityManagerFactory("read-and-write-database");
EntityManager readWriteEntityManager = readWriteEntityManagerFactory.createEntityManager();
EntityManagerFactory readEntityManagerFactory = Persistence.createEntityManagerFactory("read-database");
EntityManager readEntityManager = readEntityManagerFactory.createEntityManager();
if you are in a container, the PersistenceContext anotation have the unitName field that you can use to define the persistente-unit
Keep in mind that by doing that, you will have two different persistence context. So, changes made in one of then, not gonna be "visiable" to the other one until the persistence of the data.
obs: sorry any typo.
I hope this helps you.
Cheers
I want to use Hibernate with H2 and I want the schema to be created automatically. There are many examples online and my configurations seem fine, but it is not created. Previously I used it with MySQL and did not have any problem. Are there additional parameters to be included in anywhere for H2?
My persistence unit is defined in persistence.xml as follows:
<persistence-unit name="some.jpa.name"
transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!-- tried with and without class property
<class>some.package.KeywordTask</class>
-->
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:h2:./test" />
<property name="javax.persistence.jdbc.user" value="" />
<property name="javax.persistence.jdbc.password" value="" />
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<property name="hibernate.hbm2ddl.auto" value="create" />
<property name="show_sql" value="true" />
</properties>
</persistence-unit>
Since show_sql is set to true, I expect to see create statements but nothing happens, i.e. the schema is not created.
I keep my EntityManagerFactory as a final static variable:
public static EntityManagerFactory emf = Persistence.createEntityManagerFactory("some.jpa.name");
In some place in my code, I am trying to persist an entity:
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
KeywordTask task = new KeywordTask();
task.setKeyword(keywordTask.getKey());
task.setLimit(keywordTask.getValue());
em.persist(task);
em.getTransaction().commit();
em.close();
This throws exception with cause:
org.h2.jdbc.JdbcSQLException: Table "KEYWORDTASK" not found;
which is expected since the schema is not created.
How can I get the schema created?
The reason of this problem was quite unrelated! I am writing it here in case some other guys might face it too, and spend half a day for such a stupid thing.
First, I changed from H2 to Derby to check, and it worked. In this way, I was sure that there was no problem with persistence.xml configuration.
After searching around the logs, I realized that hibernate was not able to create the table since one of the properties of the KeywordTask entity was limit, and it is a reserved word! (Remember the place that I persist an instance and observe the name of the setter: setLimit.) After changing the name of the property, it worked.