OpenJPA HSQLdb - how to handle IDs - java

I'm having trouble handling IDs of my databse tables using OpenJPA and HSQLdb. I created an Abstract class where I handle annotations and stuff to remap into the DB:
// Property accessors
#Id
#Column(name = "IDTESTOBJEKT", unique = true, nullable = false)
public Integer getIdtestobjekt() {
return this.idtestobjekt;
}
public void setIdtestobjekt(Integer idtestobjekt) {
this.idtestobjekt = idtestobjekt;
}
It's as a Facade used to create Testobjekts.
Testobjekt test_obj = new Testobjekt();
test_obj.setEigentuemerin("helge");
// test_obj.setIdtestobjekt(1);
EntityManagerHelper.beginTransaction();
TestobjektDAO test_dao = new TestobjektDAO();
test_dao.save(test_obj);
EntityManagerHelper.commit();
List<Testobjekt> foo;
foo = test_dao.findByEigentuemerin("helge");
Testobjekt from_db = foo.get(0);
System.out.println(from_db.getEigentuemerin());
Nevertheless what I set ... 1, nothing... I get errors.
Like:
Field "model_layer.AbstractTestobjekt.idtestobjekt" of "model_layer.Testobjekt#3209fa8f" can not be set to "null" value.
I want the ORM layer to handle that ID stuff without bothering me. My experience with Hibernate is that is handles that stuff quite well... but OpenJPA seems to be cumbersome here. I assume my annotations are wrong or something but I'm having trouble tracking this multi-layered issue down.
I configured OpenJPA in the persistence.xml:
<persistence-unit name="HSQLdb_mvn_openJPA_autoTablesPU"
transaction-type="RESOURCE_LOCAL">
<provider>
org.apache.openjpa.persistence.PersistenceProviderImpl
</provider>
<class>model_layer.Testobjekt</class>
<class>model_layer.AbstractTestobjekt</class>
<properties>
<property name="openjpa.ConnectionDriverName"
value="org.hsqldb.jdbc.JDBCDriver" />
<property name="openjpa.ConnectionURL"
value="jdbc:hsqldb:hsql://localhost:9001/mydb" />
<property name="openjpa.ConnectionUserName" value="SA" />
<property name="openjpa.jdbc.SynchronizeMappings"
value="buildSchema(ForeignKeys=true)" />
</properties>
</persistence-unit>
How do I handle an automated ID strategy with OpenJPA?
Thanks,
wishi

How do I handle an automated ID strategy with OpenJPA?
Use the #GeneratedValue annotation (and I suggest using the default GenerationType.AUTO strategy which indicates that the persistence provider should pick an appropriate strategy for the particular database):
#Id
#GeneratedValue
#Column(name = "IDTESTOBJEKT", unique = true, nullable = false)
public Integer getIdtestobjekt() {
return this.idtestobjekt;
}

Related

How to prevent Hibernate cache?

I'm working on an web application using Hibernate 4, Spring 3. I'm struggling with an issue for days.
In the application I have an entity class named 'User':
#Entity
public class User {
#Id
private int uid;
#Column(unique = true)
private String username;
private String password;
private boolean confirmed;
//... getters and setters
}
This entity class is mapped from a table of db called 'user'.
There is another entity class named 'Confirmation':
#Entity
#NamedQueries({
#NamedQuery(name = "getAllConfirmations", query = "select c from Confirmation c")
})
public class Confirmation {
#Id
private String username;
private boolean confirmed;
//... getters and setters
}
This entity class is mapped from a view of db called 'confirmation'.
create view confirmation
as
select username,confirmed from user
I have a method in my service class to get list of all Confirmation object:
public List<Confirmation> getListOfConfirmations() {
Query query = entityManager.createNamedQuery("getAllConfirmations");
return query.getResultList();
}
Also, there's a method to confirm User objects- set confirmed field 'true':
public int confirmUser(int uid) {
User user = getUser(uid);
if (user != null) {
user.setConfirmed(true);
try {
entityManager.getTransaction().begin();
entityManager.merge(user);
entityManager.getTransaction().commit();
return 1;
} catch (Exception e) {
e.printStackTrace();
}
}
return 0;
}
When I call confirmUser() it works fine and User object and it's row in database would be changed, But when I call getListOfConfirmations() after changes no change would be viewed in the result list.
It seems, by default, hibernate caches query result of views.
Is there any way to prevent hibernate to prevent caches this result.
In addition, I've tried #Cacheable(false) for Confirmation class or set #QueryHint(name = "org.hibernate.cacheable", value = "false") for getAllConfirmations named query, these don't work.
Persistence config:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="MyPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>bob.jpacache.Confirmation</class>
<class>bob.jpacache.User</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost/cachetest"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.password" value="root"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
Thanks, in advance, for your help.
#Cacheable refers to the second-level cache and your problem seems to me that it is in the first level cache. I believe that the problem is in the life cycle of your EntityManager (at what time you create a new, at what time you close it), do a simple test: after the change of the User's objects, try call entityManager.clear () and then query your Confirmation object. NOTE: entityManager.clear () must be called on the same EntityManager that will be used to make the query.
Another detail, do not know what his real purpose, but the query has no filter. Thus, whether the User has to confirm or not, will always bring all records of User table.

What causes "java.lang.IllegalArgumentException: Can not set java.lang.Integer field"

I cannot resolve these new exceptions
Can not set java.lang.Integer field GcmRegistraionIdentity.gcmId to GcmRegistraionIdentity
org.hibernate.PropertyAccessException: could not get a field value by reflection getter of GcmRegistraionIdentity.gcmId
My Dynamic Web Project (Jee7) targeted to
GlassFish Server Open Source Edition 4.1 (build 13)
Hibernate
Hibernate Core {4.3.7.Final}
My Persistence.xml
<persistence version="2.1"
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://www.oracle.com/webfolder/technetwork/jsc/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="testPU" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>jdbc/testDB</jta-data-source>
<properties>
<property name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
<property name="hibernate.show_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
Heres my EDITED entity class (partial: e.g Getters/Setters NOT SHOWN)
#Entity
#Table(name = "gcm_registration")
public class GcmRegistraionIdentity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "gcm_id", unique = true, nullable = false, insertable = false, updatable = false)
private Integer gcmId;
#Column(name = "registration_id")
private String registraionId = null;
#Column(name = "created")
#Temporal(TemporalType.TIMESTAMP)
private Date created;
public Integer getGcmId() {
return gcmId;
}
public void setGcmId(final Integer gcmId) {
this.gcmId = gcmId;
}
Mysql version is
Version 5.6.22 MySQL Community Server (GPL)
I am running on Mac OS X 10.10.1 (14B25) (Yosemite)
Heres my JAX-RS class
#Path("registrations")
#Stateless
public class RegistrationResource {
#PersistenceContext
private EntityManager mEntityManager;
#POST
#Path("gcm")
public void register(final RegistrationIdJson registrationId) {
final GcmRegistraionIdentity gcmRegistraionIdentity = new GcmRegistraionIdentity();
gcmRegistraionIdentity.setRegistraionId(registrationId.getRegistrationId());
mEntityManager.persist(gcmRegistraionIdentity);
}
}
Heres the DDL for my MySql table
CREATE TABLE `gcm_registration` (
`gcm_id` int(11) NOT NULL AUTO_INCREMENT,
`registration_id` varchar(1024) NOT NULL,
`created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`gcm_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
I'll recommend a change in the name of id field.
Alter the table and update the column to "id". I think that "_id" is doing funny stuff on hibernate.
The solution was to replace
Hibernate Core {4.3.7.Final}
with
Hibernate Core {4.3.5.Final}
No other code or configuration changes were required

Eclipselink with MongoDB - cast exception [duplicate]

This question already has answers here:
Eclipselink with MongoDB java.lang.ClassCastException
(3 answers)
Closed 7 years ago.
I'm getting stuck in configuring JPA for Mongodb.
Here is my stack exception :
[EL Config]: connection: 2014-03-31 10:48:24.171--ServerSession(1883377923)--Connection(1001688235)--Thread(Thread[main,5,smarttrade])--disconnect
[EL Severe]: ejb: 2014-03-31 10:48:24.181--ServerSession(1883377923)--Thread(Thread[main,5,smarttrade])--java.lang.ClassCastException: org.eclipse.persistence.nosql.adapters.mongo.MongoPlatform cannot be cast to org.eclipse.persistence.internal.databaseaccess.DatabasePlatform
at org.eclipse.persistence.sequencing.TableSequence.onConnect(TableSequence.java:168)
at org.eclipse.persistence.sequencing.Sequence.onConnect(Sequence.java:270)
at org.eclipse.persistence.internal.sequencing.SequencingManager.onConnectSequences(SequencingManager.java:927)
at org.eclipse.persistence.internal.sequencing.SequencingManager.onConnectInternal(SequencingManager.java:747)
at org.eclipse.persistence.internal.sequencing.SequencingManager.onConnect(SequencingManager.java:700)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeSequencing(DatabaseSessionImpl.java:282)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:636)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:632)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:568)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.postConnectDatasource(DatabaseSessionImpl.java:799)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.login(DatabaseSessionImpl.java:756)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:241)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:685)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.getAbstractSession(EntityManagerFactoryDelegate.java:204)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.createEntityManagerImpl(EntityManagerFactoryDelegate.java:304)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:336)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:302)
at com.smarttrade.tick.engine.TickEngine.start(TickEngine.java:287)
My persistence.xml is defined as follow :
<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"
version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="mongo" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.smarttrade.tick.jpa.Instrument</class>
<class>com.smarttrade.tick.jpa.Snapshot</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.target-database"
value="org.eclipse.persistence.nosql.adapters.mongo.MongoPlatform" />
<property name="eclipselink.nosql.connection-spec"
value="org.eclipse.persistence.nosql.adapters.mongo.MongoConnectionSpec" />
<property name="eclipselink.nosql.property.mongo.port" value="27017" />
<property name="eclipselink.nosql.property.mongo.host" value="localhost" />
<property name="eclipselink.nosql.property.mongo.db" value="mydb" />
<property name="eclipselink.logging.level" value="FINEST" />
</properties>
</persistence-unit>
</persistence>
I have two entity classes :
#Entity
#NoSql(dataFormat = DataFormatType.MAPPED)
public class Instrument {
#Id
String securityID = null;
#OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH })
Set<Snapshot> snapshots = new HashSet<Snapshot>();
// constructor, getters and setters
...
}
and
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
#NoSql(dataFormat = DataFormatType.MAPPED)
public class Snapshot {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
double id;
#Temporal(TemporalType.TIMESTAMP)
Date snapshotTs;
String bestOfferOwn;
.. // other fields
// constructor, getters and setters
...
}
And here it's how I call it :
EntityManagerFactory factory = Persistence.createEntityManagerFactory("mongo");
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
Instrument i = new Instrument("JAP_USDEUR");
Snapshot s = new Snapshot(new Date(), "LP_one", 20000, 3.1, new Date(), "LP_two", 10000, 3.0, new Date());
Snapshot s2 = new Snapshot(new Date(), "LP_rg", 500, 4.9, new Date(), "LP_zet", 6000, 5.1, new Date());
i.getSnapshots().add(s);
i.getSnapshots().add(s2);
em.persist(i);
em.getTransaction().commit();
em.close();
The factory is created, and then it seems that that EntityManager make the connection, but after I have this cast exception. I found a post about it (Eclipselink with MongoDB java.lang.ClassCastException)but I had already added the classes in my persistence.xml.
Like I'm really a newbie in jpa I might have set something wrong, but I can't find out what.
I finally find out where was my problem. I used a GenerationType.TABLE for my Snaphot's Id generation strategy, but this is not supported in nosql.
I just changed :
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
double id;
to
#Id
#GeneratedValue
double id;
and it worked

How to refresh updated entity data without restarting the server

I am using EclipseLink JPA as ORM and web logic 10.3 as an application server in my project. Everything working fine until i got a bug for data refresh. Here is the case one of my entity table row is updated to new value but my entity manager or JPA did not pick that value. For this we have lite rely re started the server. then it picked up the value.
Here is my persistence.xml file and here is the way i am using entity manager in my class.
<persistence-unit name="BasePersistenceUnit" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/CTH_DS</jta-data-source>
<class>org.test.partyrequest.model.dataobject.RqstTrc</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="eclipselink.target-server" value="WebLogic_10" />
<!-- Logging level is set to INFO, Need to change in Production -->
<property name="eclipselink.logging.level" value="FINE" />
<property name="eclipselink.persistence-context.flush-mode" value="COMMIT" />
<property name="eclipselink.persistence-context.close-on-commit" value="true" />
<property name="eclipselink.cache.shared.default" value="false" />
</properties>
</persistence-unit>
SPRING JPA XML FILE
<context:load-time-weaver aspectj-weaving="on" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="BasePersistenceUnit" />
</bean>
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter" />
<bean id="transactionManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager" />
<!-- ========================= BUSINESS OBJECT DEFINITIONS ========================= -->
<!-- Instruct Spring to perform declarative transaction management automatically on annotated classes. -->
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<!-- Post-processor to perform exception translation on #Repository classes
(from native exceptions such as JPA PersistenceExceptions to Spring's DataAccessException hierarchy).
-->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
My Entity calss
#Entity
#Table(name = "PRTY_RQST")
public class PrtyRqst implements Serializable {
private static final long serialVersionUID = -4679712398918736694L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PRTY_RQST_PRTYRQSTID_GENERATOR")
#SequenceGenerator(name = "PRTY_RQST_PRTYRQSTID_GENERATOR", allocationSize = 1, sequenceName = "PRTY_RQST_SEQ")
#Column(name = "PRTY_RQST_ID")
private Long prtyRqstId;
#Column(name = "CHLD_RQST_IND")
private String chldRqstInd;
#Column(name = "PARNT_PRTY_RQST_ID")
private BigDecimal parntPrtyRqstId;
#Column(name = "PROCES_REFR")
private String procesRefr;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "RQST_DT_TM")
private Date rqstDtTm;
#Column(name = "UPDT_BY")
private String updtBy;
// bi-directional many-to-one association to PrtyKey
#OneToMany(mappedBy = "prtyRqst", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<PrtyKey> prtyKeys;
// bi-directional many-to-one association to PrtyRqstHist
#OneToMany(mappedBy = "prtyRqst", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#OrderBy("rqstDtTm DESC")
private List<PrtyRqstHist> prtyRqstHists;
#OneToOne(mappedBy = "prtyRqst", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private RqstPayload rqstPayload;
// bi-directional many-to-one association to RqstTrc
#OneToMany(mappedBy = "prtyRqst", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<RqstTrc> rqstTrcs;
// bi-directional many-to-one association to AddtnRqstInfo
#OneToMany(mappedBy = "prtyRqst", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<AddtnRqstInfo> addtnRqstInfos;
// bi-directional many-to-one association to BusnApplc
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH)
#JoinColumn(name = "BUSN_APPLC_ID")
private BusnApplc busnApplc;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH)
#JoinColumn(name = "INTN_PROCES_TYP_ID")
private IntnProcesTyp intnProcesTyp;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH)
#JoinColumn(name = "INTN_STATS_ID")
private IntnStat intnStat;
#Column(name = "ORCHESTRATION_ID")
private String orchestrationId;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH)
#JoinColumn(name = "ALLW_CHNL_ID")
private AllwChnl allwChnl;
// bi-directional many-to-one association to RqstTyp
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH)
#JoinColumn(name = "RQST_TYP_ID")
private RqstTyp rqstTyp;
#Column(name = "TRACK_RQST_IND")
private String trackRqstInd;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "SUBMIT_DT_TM")
private Date submitDtTm;
#Temporal(TemporalType.DATE)
#Column(name = "EFFECTIVE_DT")
private Date effectiveDt;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "RQST_CREATE_DT_TM")
private Date rqstCreateDtTm;
In my DAO IMPL class I have this.persist(prtyRqstDO);
#Transactional(readOnly = true, propagation=Propagation.REQUIRED)
private PartyRequestBO createRequest(PartyRequestBO partyRequestBO, boolean isParent) throws RuntimeException {
if (log.isDebugEnabled()) {
log.debug("Enter: PartyRequestsDAOImpl:createRequest()");
}
partyRequestBO.setOrchestrationID(generateOrchestrationId());
PrtyRqst prtyRqstDO = PartyRequestEntityMapper.partyRequestMapper(partyRequestBO, isParent, true);
try {
this.persist(prtyRqstDO);
partyRequestBO.setRequestIdentifier(prtyRqstDO.getPrtyRqstId());
} catch (Exception e) {
if(log.isDebugEnabled()) {
log.debug("PartyRequestsDAOImpl:createRequest : " + PartyRequestConstants.UNABLE_TO_INSERT, e);
}
throw new PartyRequestDataException(PartyRequestConstants.UNABLE_TO_INSERT, e);
}
if (log.isDebugEnabled()) {
log.debug("Exit: PartyRequestsDAOImpl:createRequest()");
}
return partyRequestBO;
}
#Transactional(readOnly = true, propagation=Propagation.REQUIRED)
public void persist(T entity) {
if (log.isDebugEnabled()) {
log.debug("Enter: BaseDAO:persist() : " + entity);
}
this.getEntityManager().persist(entity);
if (log.isDebugEnabled()) {
log.debug("Exit: BaseDAO:persist()");
}
}
public EntityManager getEntityManager() {
if (log.isDebugEnabled()) {
log.debug("Enter: BaseDAO:getEntityManager() : " + this.entityManager);
}
return this.entityManager;
}
Here the problem is, if i update the row in one of the table through back end my application container is not picking the change.
Can any one Tell me? thank you in advance.
EDIT:
Thank you both of you. I have modified according to your comments added following lines of code.
this.entityManager.clear();
this.entityManager.close();
//this.getEntityManager().refresh(entityManager);
Here i could able to get the update value what i have done it through backend with out restarting server. But the problem is it hold all the changed values.
for example i have changed value to FulOrderWSA it was working. changed to FulorderWSB it was working again.Now i have tried for FulOrderWSZ it didn't work(DB values is FulorderWSB ).
Finally i tried here with old value that is FulorderWSA as per DB it should not work but it worked for me. what i noticed that it is holding all the DB changed values here.
How to get ride of this. I have used both clear and close for entityManager. can any one help me on this.
thank you.
Vijay.
You have turned off the EclipseLink shared cache (AKA second level cache), so the issue is likely that you are holding onto long lived EntityManagers. Once an entity becomes managed by the EM, JPA requires that EM to return that exact instance from every find/query operation as it was when first read and any changes your app might have made to it.
There are a number of options. The best is to look at your EntityManager lifecycle and only obtain an EntityManager when needed, and close it when done. Or, just call em.clear() at points to prevent them from filling up, which will detach all entities associated to the em. Make sure to flush changes though if you wish to keep the changes before calling clear.
If there is a specific entity you need to refresh, em.refresh(entity) will work. This will clear any changes the application might have made though, and can be dangerous with cascade refresh settings mixed with lazy access - so use carefully or you may unintentionally wipe out changes to a whole tree at a later time.
You have caching disabled, so you should see any database changes.
My guess is that you are hold onto a single EntityManager in your DAO. This is very bad, as an EntityManger should be created per transaction, or per request, not held for the duration of the application. It is also not thread safe, so holding onto a single one does not make sense, as it is a transactional object.
You seem to also be using Spring, so it might be proxying the EntityManager underneath and creating one per transaction, but perhaps you have not configured Spring or your transactions correctly.
Include the code the creating/configures the EntityManager.
Thanks,
for all your support. Basically we are not using Cache from EclipseLink. we had bean that handles all the metadata initialization as init method. what we have done is, used JDK Timer to reload the particular Bean to refresh the data. It was working fine.
I have checked the time taking to refresh the all the methods are less than 500 milliseconds. I can foresee only issue when this thread is executing and there is a request.since it is taking less than 500 millisecs its ok for us.
I hope this will be helpful if someone is not using cache you can try this approach.
Thank you.

Persistency unit fails to make the relation many to many

Ok this is a weird problem because I had it working before.
So I have 2 classes: game and developer. They have a many to many relationship.
The persistency unit makes automatically the table game_developer.
Thus there are 3 tables: game developer and game_developer.
When I enter Information inside the database. The table game and developer will get there values as normal but the table game_developer will remain empty. So the relationship isn't recognized.
Also when I run the webapp everything inside the tables should be dropped. The developer drops fine but the game remains to exist.
Any push in the right direction is appreciated.
Thank you in advance,
David
Initialization:
try {
gameOrganizer = (GameOrganizer) getServletContext().getAttribute("database");
Game game = new Game("Counter Strike: source");
Game game2 = new Game("Battlefield: bad company 3");
Game game3 = new Game("Killing floor");
Developer devel = new Developer("valve");
Developer devel2 = new Developer("EA Games");
Developer devel2b = new Developer("DICE");
Developer devel3 = new Developer("Ubisoft");
//The GameOrganizer is the controller between the model en the view.
//The view being the website.
//So gameOrganizer.addGame(game) will persist the object to the database.
gameOrganizer.addGame(game);
gameOrganizer.addGame(game2);
gameOrganizer.addGame(game3);
gameOrganizer.addDeveloper(devel);
gameOrganizer.addDeveloper(devel2);
gameOrganizer.addDeveloper(devel2b);
gameOrganizer.addDeveloper(devel3);
game.addDeveloper(devel);
devel.getGames().add(game);
game2.addDeveloper(devel2);
devel2.getGames().add(game2);
game2.addDeveloper(devel2b);
devel2b.getGames().add(game2);
game3.addDeveloper(devel3);
devel3.getGames().add(game3);
} catch (DatabaseException ex) {
Logger.getLogger(GameController.class.getName()).log(Level.SEVERE, null, ex);
} catch (DomainException ex) {
Logger.getLogger(GameController.class.getName()).log(Level.SEVERE, null, ex);
}
The game class:
#Entity
public class Game implements Serializable{
private String gameNaam;
private double prijs;
#ManyToMany(mappedBy = "games")
private Collection<Developer> developers = new ArrayList<Developer>();
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
public Game(){};
.
.
//methods
.
.
}
The Developer class
#Entity
public class Developer implements Serializable {
private String naam;
private String info;
#ManyToMany
private Collection<Game> games = new ArrayList<Game>();
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
public Developer() {
}
.
.
//methods
.
.
}
The persistency Unit:
<?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="GameDatabaseSitePU" transaction-type="RESOURCE_LOCAL">
<provider>oracle.toplink.essentials.PersistenceProvider</provider>
<class>domainmodel.Developer</class>
<class>domainmodel.Game</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="toplink.jdbc.user" value="app"/>
<property name="toplink.jdbc.password" value="app"/>
<property name="toplink.jdbc.url" value="jdbc:derby://localhost:1527/GameDatabase;create=true"/>
<property name="toplink.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
<property name="toplink.ddl-generation" value="drop-and-create-tables"/>
</properties>
</persistence-unit>
</persistence>
The relationship isn't recognized because you persist the objects before you establish the relationships. Do the calls gameOrganizer.add..() after you add the objects to each others collections. Also add persist on cascade to your many-to-many relationship of developers:
#ManyToMany(cascade = CascadeType.PERSIST, mappedBy = "games")
private Collection<Developer> developers = new ArrayList<Developer>();
Then you only need to persist the games.
I think in a bi-directional many-to-many relationship you need to set both sides ...
i.e. if you do
devel.getGames().add(game);
you also need to do
game.getDeveloper().add(devel);
otherwise JPA will not really see the other side, the insert into the mapping table will be something like (FK1, null), which will fail, which is why you won't see any entry ...
I don't know much about toplink, but i think something like
<property name="toplink.logging.level" value="FINE"/>
should give you sql statements in your logging which help a lot debugging these kind of problems :)

Categories

Resources