[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Newsgroup Home]
[news.eclipse.tools.emf] Re: [Teneo] Possible inconsistency using IdBags

Hi Bjorn,
Thanks for checking this, I will add this to the troubleshooting area of the docs.

gr. Martin

Bjoern Sundin wrote:
Hi Martin,

You are right: I cannot reproduce this error with mysql.

I've tested with derby, mysql, hsqldb and oracle. Attached you will find the
logs from each test starting from the point where list.clear() was called.
It seems that this erroneous behaviour only occurs when using Derby
database. This is very unfortunate for me as I am using the Derby database
(version 10.4.2)!

AFAICS is the key to the problem on row 46 and 47 in the derby.log:

<quote>
[main] DEBUG org.hibernate.SQL  - select max(ID) from "operation_operands"
[main] DEBUG org.hibernate.id.IncrementGenerator  - first free id: 1
<unquote>

I put a breakpoint in the modified the IncrementGenerator getNext-method and
changed the value of next id from 1 to 5 (like in the other logs). After
this manipulation also the Derby database was consistent! See
derby-manipulated.log.

This doesn't really make sense to me, as it would mean that with the Derby
database the delete of rows got persisted to the database before the query
for max(ID) whereas for the other databases it's done afterwards. I guess
this is rather a Derby driver problem, but other user of the framework might
as well be affected and should beware of the consequences using the IDBAG
setting in combination with Derby!

Greetings
Bjoern

"Martin Taal" <mtaal@xxxxxxxxx> schrieb im Newsbeitrag
news:gi6dh2$nfp$1@xxxxxxxxxxxxxxxxxxxx
Hi Bjoern,
I used your project but I am afraid that with me it worked fine. See the
before and after jpg's. Two
things I changed:
- I changed the Activator to work from a main method, which was easier to
run (see the attached file)
- I use mysql

I am using Hibernate 3.2.6 which you also tried I think.

I am a bit at a loss why it fails with you and not with me...

Can you check the hibernate log4j output specifically at the point that
the collection is cleared
and then saved?

gr. Martin

Bjoern Sundin wrote:
Hi Martin,

I extracted the concerned (simplified) objects from my project and packed
them into another simpler plugin application. See attached zip.

When you run the Activator the first time it will create the DB and the
initial model. The second time it will remove the "operands" and add them
again together with a new "operand reference".

I attach two screenshots showing the database table after the first run
and
after the second run. As you can see after the first run there are 4
"operands" in the table. After the second run I would expect the same
"operands" there plus the additional one but there is only the additional
one! I can reproduce this behaviour also omitting adding the additional
"operand". Then after the second run the table will be empty.

Greetings
Bjoern


"Martin Taal" <mtaal@xxxxxxxxx> schrieb im Newsbeitrag news:gi1g0c$o45$1@xxxxxxxxxxxxxxxxxxxx
Hi Bjoern,
I tried to replicate this in a test but I was not able to (with me it
works fine). Also in my case I
change the list which is last in the database. I have attached the test
I
used, it uses the Teneo
test framework but I am sure you can read through it. In addition I
attached the ecore model I used
to test. Can you check if you see any differences?

Otherwise if you have a test case for me then I can try it out.

gr. Martin

Bjoern Sundin wrote:
Hello Martin,

I have encountered a problem concerning lists in my application. After
extensive debugging I have found out that this problem is connected
with
the
use of IdBags.

I use Eclipse 3.4, Teneo 1.0.1 and Hibernate 3.3.1 (also tested with
3.2.6)

The problem is the following:
When adding objects to a list, one part of the logic first makes
list.clear() and then adds all the newly submitted objects. The newly
submitted objects could possibly partly contain the once removed in
list.clear().
This is no problem unless the list being modified is the one having the
last
rows in the database table! In this case only the new objects get added
to
the list. The ones removed and then readded do not get persisted to the
database again. They are visible to the GUI (model), however, but only
until
the application restarts.

The situation as an example:
Object Library has a unique ordered non-containment list referencing
object
Book (Books are contained in object Publisher).

In the database there is a table Library _ Books with three columns:
Library id | Book id | ID

To start the following ids are in the table:
 1|11|1
 1|12|2
 1|13|3
 2|11|4
 2|13|5

- I edit the list for the Library with id 2 in the GUI. I want to add a
Book
reference with id 12.

- The logic makes list.clear() and thus removes all the Book references
(11
and 13) for the Library with id 2.

- Then it adds the Book references 11, 12 and 13

- The transaction gets committed.

- The Model (EObjects) shows the following two lists:
 1{11, 12, 13}
 2{11, 12, 13}

- In the database I have the following:
 1|11|1
 1|12|2
 1|13|3
 2|12|4

- The expected result in the database would be
 1|11|1
 1|12|2
 1|13|3
 2|11|4
 2|12|5
 2|13|6

I'm able to resolve this behaviour by setting the
PersistenceOptions.MAP_ALL_LISTS_AS_IDBAG to false and recreate the
database. But I think it might be important to know about the impact of
this
problem when using IdBags as it (for me) unexpectedly removed entries
from
the database.

Greetings
Bjoern


--

With Regards, Martin Taal

Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Cell: +31 (0)6 288 48 943
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@xxxxxxxxxxxxxx - mtaal@xxxxxxxxx
Web: www.springsite.com - www.elver.org


--------------------------------------------------------------------------------


/**
* <copyright>
*
* Copyright (c) 2005, 2006, 2007, 2008 Springsite BV (The Netherlands)
and
others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*   Martin Taal
* </copyright>
*
* $Id: LibraryListAsBagAction.java,v 1.3 2008/02/28 07:08:15 mtaal Exp $
*/

package org.eclipse.emf.teneo.test.emf.sample;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.eclipse.emf.teneo.PersistenceOptions;
import org.eclipse.emf.teneo.samples.issues.bz237790.Bz237790Factory;
import org.eclipse.emf.teneo.samples.issues.bz237790.Bz237790Package;
import org.eclipse.emf.teneo.samples.issues.bz237790.Many;
import org.eclipse.emf.teneo.samples.issues.bz237790.One;
import org.eclipse.emf.teneo.test.AbstractTestAction;
import org.eclipse.emf.teneo.test.stores.TestStore;

/**
* @author <a href="mailto:mtaal@xxxxxxxxx";>Martin Taal</a>
* @version $Revision: 1.3 $
*/
public class ListAsIdBagAction extends AbstractTestAction {

private final Bz237790Factory factory = Bz237790Factory.eINSTANCE;

public ListAsIdBagAction() {
super(Bz237790Package.eINSTANCE);
}

@Override
public Properties getExtraConfigurationProperties() {
final Properties props = new Properties();
props.setProperty(PersistenceOptions.MAP_ALL_LISTS_AS_IDBAG, "true");
return props;
}

@Override
public void doAction(TestStore store) {
store.disableDrop();
{
store.beginTransaction();
addDataSet(store, 1);
addDataSet(store, 2);
store.commitTransaction();
}

// read the writers and add the second book to the second writer
{
store.beginTransaction();
final List<One> os = store.getObjects(One.class);
One o1 = null;
One o2 = null;
for (One o : os) {
if (o.getManies().size() == 2) {
o1 = o;
} else {
o2 = o;
}
}
final List<Many> reserve = new ArrayList<Many>(o1.getManies());
o1.getManies().clear();
reserve.add(1, o2.getManies().get(1));
o1.getManies().addAll(reserve);
store.commitTransaction();
}

{
store.beginTransaction();
final List<One> os = store.getObjects(One.class);
for (One o : os) {
assertEquals(3, o.getManies().size());
}
store.commitTransaction();
}
}

private void addDataSet(TestStore store, int index) {
{
final One one = factory.createOne();
store.store(one);
int num = 3;
if (index == 2) {
num = 2;
}
for (int i = 0; i < num; i++) {
final Many many = factory.createMany();
many.setName("" + index);
one.getManies().add(many);
store.store(many);
}
}

}
}


--------------------------------------------------------------------------------


<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0"
   xmlns:xmi="http://www.omg.org/XMI";
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
   xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"; name="bz237790"
   nsURI="http://www.eclipse.org/emf/teneo/samples/issues/bz225296";
nsPrefix="bz237790">
 <eClassifiers xsi:type="ecore:EClass" name="One">
   <eStructuralFeatures xsi:type="ecore:EReference" name="manies"
upperBound="-1"
       eType="#//Many" resolveProxies="false"/>
 </eClassifiers>
 <eClassifiers xsi:type="ecore:EClass" name="Many">
   <eStructuralFeatures xsi:type="ecore:EAttribute" name="name"
eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString";>
     <eAnnotations source="teneo.jpa">
       <details key="value" value="@Column(name=&quot;myname&quot;)"/>
     </eAnnotations>
   </eStructuralFeatures>
 </eClassifiers>
</ecore:EPackage>



--

With Regards, Martin Taal

Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Cell: +31 (0)6 288 48 943
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@xxxxxxxxxxxxxx - mtaal@xxxxxxxxx
Web: www.springsite.com - www.elver.org



--------------------------------------------------------------------------------


package model;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.teneo.PersistenceOptions;
import org.eclipse.emf.teneo.hibernate.HbDataStore;
import org.eclipse.emf.teneo.hibernate.HbHelper;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Environment;

public class ActivatorMain {

private static String dataStoreName = "ModelDS";
private static HbDataStore dataStore;

public static void main(String[] args) {
activateDataStore();
handleModel();

deactivateDataStore();
}

private static void activateDataStore() {

dataStore = HbHelper.INSTANCE.createRegisterDataStore(dataStoreName);

// Configure the EPackages used by this DataStore.
dataStore.setEPackages(new EPackage[] { ModelPackage.eINSTANCE });

dataStore.setProperties(getProperties());

// Initialize the DataStore. This sets up the Hibernate mapping and
// creates the corresponding tables in the database.
dataStore.initialize();

}

private static void deactivateDataStore() {
if (dataStore != null) {
dataStore.close();
}
}

private static Properties getProperties() {

Properties properties = new Properties();

properties.setProperty(PersistenceOptions.ID_COLUMN_NAME, "id");

properties.setProperty(PersistenceOptions.VERSION_COLUMN_NAME,
"version");

properties.setProperty(PersistenceOptions.ALWAYS_VERSION, "false");

properties
.setProperty(PersistenceOptions.MAXIMUM_SQL_NAME_LENGTH, "63");

properties.setProperty(PersistenceOptions.MAP_ALL_LISTS_AS_IDBAG,
"true");

properties.setProperty(
PersistenceOptions.JOIN_TABLE_FOR_NON_CONTAINED_ASSOCIATIONS,
"true");

properties.setProperty(PersistenceOptions.SET_FOREIGN_KEY_NAME, "true");

properties.setProperty(PersistenceOptions.ADD_INDEX_FOR_FOREIGN_KEY,
"true");

properties.setProperty(
PersistenceOptions.CASCADE_POLICY_ON_CONTAINMENT,
"MERGE,PERSIST,REFRESH,REMOVE");

properties.setProperty("teneo.runtime.update_schema", "true");

properties.setProperty("hibernate.hbm2ddl.auto", "update");

// cache implementation
properties.setProperty("hibernate.cache.provider_class",
"org.hibernate.cache.EhCacheProvider");

// enable the query cache
properties.setProperty("hibernate.cache.use_query_cache", "false");
properties.setProperty(Environment.DRIVER, "com.mysql.jdbc.Driver");
properties.setProperty(Environment.USER, "root");
properties.setProperty(Environment.URL,
"jdbc:mysql://127.0.0.1:3306/test2");
properties.setProperty(Environment.PASS, "root");
properties.setProperty(Environment.DIALECT,
org.hibernate.dialect.MySQLInnoDBDialect.class.getName());

return properties;

}

private static void handleModel() {

SessionFactory sessionFactory = dataStore.getSessionFactory();

// Open a new Session and start Transaction.
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Query query = session.createQuery("FROM Node");
List<?> entities = query.list();
if (entities.isEmpty()) {
Node node = ModelFactory.eINSTANCE.createNode();
node.setName("Node 1");
Operation operation = ModelFactory.eINSTANCE.createOperation();
operation.setName("Operation");
node.getOperations().add(operation);
for (int i = 0; i < 10; i++) {
Datapoint datapoint = ModelFactory.eINSTANCE.createDatapoint();
datapoint.setName("Datapoint " + i);
node.getDatapoints().add(datapoint);
if (i < 4) {
operation.getOperands().add(datapoint);
}
}
session.save(node);
} else {
Node node = (Node) entities.get(0);
List<Datapoint> operands = new ArrayList<Datapoint>(0);
Operation operation = node.getOperations().get(0);
for (Datapoint operand : operation.getOperands()) {
operands.add(operand);
}
Datapoint anotherOperand = node.getDatapoints().get(5);
operands.add(anotherOperand);

operation.getOperands().clear();
operation.getOperands().addAll(operands);

}
transaction.commit();
session.close();

}

}







--

With Regards, Martin Taal

Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Cell: +31 (0)6 288 48 943
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@xxxxxxxxxxxxxx - mtaal@xxxxxxxxx
Web: www.springsite.com - www.elver.org