Using the wrong class to access a database

#1

Hello,

just starting to test ObjectDB and ran into a problem.

I've created a small program to test the Point database described in the Getting Started section:

package com.objectdb.tutorial;

// imports

public class Main {

public static void main(String[] args) {
  run();
}

static void run() {
  System.out.println("Test 1");
  System.out.println("Point.class: " + Point.class);
 
  EntityManagerFactory emf =
    Persistence.createEntityManagerFactory("$objectdb/db/points.odb");

  EntityManager em = emf.createEntityManager();

  create(em);
  retrieve(em);
 
  deleteAndUpdate(em);

  // close connection to db
  em.close();

  // close db
  emf.close();
}

static void create(EntityManager em) {
  em.getTransaction().begin();
  for (int i = 0; i < 1000; i++) {
   Point p = new Point(i, i);
   em.persist(p);
  }
  em.getTransaction().commit();
}

static void retrieve(EntityManager em) {
  // 1
  Query q1 = em.createQuery("SELECT COUNT(p) FROM Point p");
  System.out.println("Total Points: " + q1.getSingleResult());
 
  // 2
  Query q2 = em.createQuery("SELECT AVG(p.x) FROM Point p");
  System.out.println("Average X: " + q2.getSingleResult());
 
  // 3 get all points
  TypedQuery<Point> query =
    em.createQuery("SELECT p FROM Point p", Point.class);
  List<Point> results = query.getResultList();
  System.out.println("number of entries: " + results.size());
}

static void deleteAndUpdate(EntityManager em) {
  TypedQuery<Point> query =
    em.createQuery("SELECT p FROM Point p", Point.class);
  List<Point> results = query.getResultList();

  em.getTransaction().begin();
  for (Point p : results) {
   if (p.getX() >= 100) {
    em.remove(p); // delete entity
   }
   else {
    p.setX(p.getX() + 100); // update entity
   }
  }
  em.getTransaction().commit();
}
}

the Point class:

package com.objectdb.tutorial;

import javax.persistence.Entity;

@Entity
public class Point {
// Persistent Fields:
private int x;
private int y;

// Constructor:
Point (int x, int y) {
  this.x = x;
  this.y = y;
}

// Accessor Methods:
public int getX() { return this.x; }
public int getY() { return this.y; }
public void setX(int v) { this.x = v; }
public void setY(int v) { this.y = v; }

// String Representation:
@Override
public String toString() {
  return String.format("(%d, %d)", this.x, this.y);
}
}

Everything goes as planned.

Then, I created another program, just to test if I can access the database from here. This program is almost the same as the first; it only calls the retrieve method, no data is added. The package name is 'com.objectdb.test2'.

The Point class is exactly the same, with the exception that I use the package 'com.objectdb.test2'

This second app makes some queries and should not change the content of the db - but it does:

The first 2 queries are working fine, but the third ruins the database:

- The number of entries is zero.
- running the app a second time, the count is zero and the average is null.
- the first app cannot add points anymore; it now reports zero entries

-> db is corrupted

If it is an error to use the wrong class to access the db (which is perfectly ok), then
- why is no exception thrown in the queries?
- why the db is getting messed up with the third query - even if the class is wrong, it is only a read operation

best regards,
Gisela

#2

> The Point class is exactly the same, with the exception that I use the package 'com.objectdb.test2'

The new class is considered by ObjectDB as a new different class. Always use for every entity class only one class with one fully qualified name (i.e. the same package). You can change the class if necessary, but you should never use two different classes at the same time for the same entity.

> The first 2 queries are working fine, but the third ruins the database.

Tried and got:

Exception in thread "main" java.lang.ClassCastException

The database is fine but the application tries to cast the retrieve object of the old class to the new class. Since these are different classes, the casting fails.

> the first app cannot add points anymore;

You should get the following error message:

javax.persistence.PersistenceException
Ambiguous entity name - Point (used by ...

To use the database you must fix the ambiguity. You can do it by providing a new name to the new class using the name attribute of the Entity annotation.

ObjectDB Support

Reply