dmp
2010-01-04 02:12:36 UTC
Hi, I'm a newbie here trying some stuff on JE BDB. And now I'm having
troubles with Indexes and Inheritance...
Brief Explanation:
______________
I have the following classes:
- AbstractEntity: it is an abstract class that implements Serializable
and has a property "id" (public getter & setter) which is a
@PrimaryKey and it is using a Sequence in order to automatic increment
this "id" value (@PrimaryKey(sequence = "ID_SEQ") private Long id;).
This class is annotated as @Persistent since its mission is just be
extended from all my business classes which will be stored into my
database. I have just two business classes: Employee and Department.
- Employee: It is a business class (it's a bean) that extends the
AbstractEntity and it is annotated as @Entity since I need to persist
its status. This class has attributes as follows: Long docID, Long
managerId, long departmentId, and others like first and last names,
address, etc.
- Department: it is a business class too and also extends
AbstractEntity and it is annotated as @Entity. This class has String
departmentName and String location attributes.
Employee and Department classes has access to the "id" property of
AbstractEntity through the getter and setter methods.
But I'm having an exception when my App is trying to save the first
Employee who is a manager. The console shows this message:
TryingJEBDBApp DatabaseExcaption:
com.sleepycat.je.ForeignConstraintException: (JE 4.0.71) Secondary
persist#EntityStoreName#com.dmp.gamblit.persistence.BDB.store.eployee.Employee#managerId
foreign key not allowed: it is not present in the foreign database
persist#EntityStoreName#com.dmp.gamblit.persistence.BDB.store.eployee.Employee
Please, I appreciate any help from you guys.
Hugs,
dmp
PS: For more information, please keep reading:
App Details:
__________
I have published both business classes into my Repository class
(responsible for handling all Database concerns) as follows:
// registering Proxies classes or subclasses with a
secondary key defined
model = new AnnotationModel();
// For Sub classes having secondary keys, use:
model.registerClass(Department.class);
model.registerClass(Employee.class);
/
******************************************************************************************************************
* Here I try to registered my Persistent class too,
like this: model.registerClass(AbstractEntity.class); *
* but Nothing happened. This means that the same error
was lunched. *
/
*******************************************************************************************************************
A brief look into my App classes:
@Persistent
public abstract class AbstractEntity implements Serializable
-----------------------------------------------------------------------------------
/** Holder for the id of the entities that extend from this */
@PrimaryKey(sequence = "ID_SEQ")
private Long id;
/**
* Gets the identification for this entity
*
* @return the id of this entity
*/
public Long getId() {
return id;
}
/**
* Sets the identification for this entity
*
* @param id
* the new id for this entity
*/
public void setId(Long id) {
this.id = id;
}
-------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------
@Entity
public class Department extends AbstractEntity
---------------------------------------------------------------
@SecondaryKey(relate = MANY_TO_ONE)
private String departmentName;
private String location;
public Department() {
super(); // Needed for deserialization
}
-----------------------------------------------------------------
-----------------------------------------------------------------
@Entity
public class Employee extends AbstractEntity
-------------------------------------------------------------
@SecondaryKey(relate = ONE_TO_ONE)
/* Many Employees may have the same first name. */
@SecondaryKey(relate = MANY_TO_ONE)
private String firstName;
/* Many Employees may have the same last name. */
@SecondaryKey(relate = MANY_TO_ONE)
private String lastName;
/* Many Employees may have the same position. */
@SecondaryKey(relate = MANY_TO_ONE)
private String position;
/* Many Employees may have the same salary. */
@SecondaryKey(relate = MANY_TO_ONE)
private float salary;
@SecondaryKey(relate = MANY_TO_ONE, relatedEntity = Department.class,
onRelatedEntityDelete = NULLIFY)
private Long departmentId;
@SecondaryKey(relate = MANY_TO_ONE, relatedEntity = Employee.class,
onRelatedEntityDelete = NULLIFY)
private Long managerId;
private String address;
.....
/**
* Empty constructor needed for deserialization.
*/
public Employee() {
super();// The empty constructor needed for deserialization.
}
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
My Repository class has a setup() method to initialize all necessary
DB tasks:
...
public void setup() throws DatabaseException {
// Set up the environment.
envmntConfig = new EnvironmentConfig();
envmntConfig.setAllowCreate(true);
// Set up the entity store
storeConfig = new StoreConfig();
storeConfig.setAllowCreate(true);
// Allows to work with transactions.
envmntConfig.setTransactional(true);
storeConfig.setTransactional(true);
// Environment handles are free-threaded by default in JE,
// so we do not have to do anything to cause the
// environment handle to be free-threaded.
// registering Proxies classes or subclasses with a secondary key
defined
model = new AnnotationModel();
// For Proxies Classes use: model.registerClass(MyProxy.class);
// For Sub classes having secondary keys, use:
model.registerClass(Department.class);
model.registerClass(Employee.class);
storeConfig.setModel(model);
// Open the environment
envmnt = new Environment(ENVMNT_HOME, envmntConfig);
// Open the entity store
store = new EntityStore(envmnt, STORE_NAME, storeConfig);
// Get a transaction
txn = envmnt.beginTransaction(null, null);
}
Also I have two more classes: EmployeeDao and DepartmentDao
responsibles for giving DB access so this has the method openAllIndex
() in which the indexes are opened: (DepartmentDao is similar)
public class EmployeeDao {
private AbstractDataAccessor<Long, Employee> dao = new
DataAccessor<Long, Employee>();
private DepartmentDao departmentDao;
/* Employee IndexAccessors */
private PrimaryIndex<Long, Employee> employeeById;
private SecondaryIndex<String, Long, Employee> employeeByFirstName;
private SecondaryIndex<String, Long, Employee> employeeByLastName;
private SecondaryIndex<Float, Long, Employee> employeeBySalary;
private SecondaryIndex<Long, Long, Employee> employeeByManagerId;
private SecondaryIndex<Long, Long, Employee> employeeByDepartmentId;
public EmployeeDao() {
openAllIndex();
}
/** Opens all primary and secondary indexes. */
@SuppressWarnings("unchecked")
public void openAllIndex() throws DatabaseException {
/* Primary index of the Employee Parent database. */
dao.openEntityIndex(Long.class, Employee.class);
/* Primary index of the Employee database. */
employeeById = getEmployeeById();
/* Secondary index of the Employee database. */
employeeByFirstName = (SecondaryIndex<String, Long, Employee>) dao
.getSecondaryIndex(employeeById, String.class, "firstName");
employeeByLastName = (SecondaryIndex<String, Long, Employee>) dao
.getSecondaryIndex(employeeById, String.class, "lastName");
employeeBySalary = (SecondaryIndex<Float, Long, Employee>) dao
.getSecondaryIndex(employeeById, Float.class, "salary");
employeeByManagerId = (SecondaryIndex<Long, Long, Employee>) dao
.getSecondaryIndex(employeeById, Long.class, "managerId");
employeeByDepartmentId = (SecondaryIndex<Long, Long, Employee>) dao
.getSecondaryIndex(employeeById, Long.class, "departmentId");
// Opening Department Indexes.
departmentDao = new DepartmentDao();
}
As you can see, I'm using a DataAccessor:
private AbstractDataAccessor<Long, Employee> dao = new
DataAccessor<Long, Employee>();
This "dao" object is encapsulating some DB specific tasks but the idea
is that my Entry point (EmployeeDao and DepartmentDao) keep as simple
as possible.
For instance, this class has a Repository object as an attribute and
my EmployeeDao does not know about this Repository class. EmployeeDao
just use the "dao" object and that all.
Thnx,
dmp
troubles with Indexes and Inheritance...
Brief Explanation:
______________
I have the following classes:
- AbstractEntity: it is an abstract class that implements Serializable
and has a property "id" (public getter & setter) which is a
@PrimaryKey and it is using a Sequence in order to automatic increment
this "id" value (@PrimaryKey(sequence = "ID_SEQ") private Long id;).
This class is annotated as @Persistent since its mission is just be
extended from all my business classes which will be stored into my
database. I have just two business classes: Employee and Department.
- Employee: It is a business class (it's a bean) that extends the
AbstractEntity and it is annotated as @Entity since I need to persist
its status. This class has attributes as follows: Long docID, Long
managerId, long departmentId, and others like first and last names,
address, etc.
- Department: it is a business class too and also extends
AbstractEntity and it is annotated as @Entity. This class has String
departmentName and String location attributes.
Employee and Department classes has access to the "id" property of
AbstractEntity through the getter and setter methods.
But I'm having an exception when my App is trying to save the first
Employee who is a manager. The console shows this message:
TryingJEBDBApp DatabaseExcaption:
com.sleepycat.je.ForeignConstraintException: (JE 4.0.71) Secondary
persist#EntityStoreName#com.dmp.gamblit.persistence.BDB.store.eployee.Employee#managerId
foreign key not allowed: it is not present in the foreign database
persist#EntityStoreName#com.dmp.gamblit.persistence.BDB.store.eployee.Employee
Please, I appreciate any help from you guys.
Hugs,
dmp
PS: For more information, please keep reading:
App Details:
__________
I have published both business classes into my Repository class
(responsible for handling all Database concerns) as follows:
// registering Proxies classes or subclasses with a
secondary key defined
model = new AnnotationModel();
// For Sub classes having secondary keys, use:
model.registerClass(Department.class);
model.registerClass(Employee.class);
/
******************************************************************************************************************
* Here I try to registered my Persistent class too,
like this: model.registerClass(AbstractEntity.class); *
* but Nothing happened. This means that the same error
was lunched. *
/
*******************************************************************************************************************
A brief look into my App classes:
@Persistent
public abstract class AbstractEntity implements Serializable
-----------------------------------------------------------------------------------
/** Holder for the id of the entities that extend from this */
@PrimaryKey(sequence = "ID_SEQ")
private Long id;
/**
* Gets the identification for this entity
*
* @return the id of this entity
*/
public Long getId() {
return id;
}
/**
* Sets the identification for this entity
*
* @param id
* the new id for this entity
*/
public void setId(Long id) {
this.id = id;
}
-------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------
@Entity
public class Department extends AbstractEntity
---------------------------------------------------------------
@SecondaryKey(relate = MANY_TO_ONE)
private String departmentName;
private String location;
public Department() {
super(); // Needed for deserialization
}
-----------------------------------------------------------------
-----------------------------------------------------------------
@Entity
public class Employee extends AbstractEntity
-------------------------------------------------------------
@SecondaryKey(relate = ONE_TO_ONE)
/* Many Employees may have the same first name. */
@SecondaryKey(relate = MANY_TO_ONE)
private String firstName;
/* Many Employees may have the same last name. */
@SecondaryKey(relate = MANY_TO_ONE)
private String lastName;
/* Many Employees may have the same position. */
@SecondaryKey(relate = MANY_TO_ONE)
private String position;
/* Many Employees may have the same salary. */
@SecondaryKey(relate = MANY_TO_ONE)
private float salary;
@SecondaryKey(relate = MANY_TO_ONE, relatedEntity = Department.class,
onRelatedEntityDelete = NULLIFY)
private Long departmentId;
@SecondaryKey(relate = MANY_TO_ONE, relatedEntity = Employee.class,
onRelatedEntityDelete = NULLIFY)
private Long managerId;
private String address;
.....
/**
* Empty constructor needed for deserialization.
*/
public Employee() {
super();// The empty constructor needed for deserialization.
}
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
My Repository class has a setup() method to initialize all necessary
DB tasks:
...
public void setup() throws DatabaseException {
// Set up the environment.
envmntConfig = new EnvironmentConfig();
envmntConfig.setAllowCreate(true);
// Set up the entity store
storeConfig = new StoreConfig();
storeConfig.setAllowCreate(true);
// Allows to work with transactions.
envmntConfig.setTransactional(true);
storeConfig.setTransactional(true);
// Environment handles are free-threaded by default in JE,
// so we do not have to do anything to cause the
// environment handle to be free-threaded.
// registering Proxies classes or subclasses with a secondary key
defined
model = new AnnotationModel();
// For Proxies Classes use: model.registerClass(MyProxy.class);
// For Sub classes having secondary keys, use:
model.registerClass(Department.class);
model.registerClass(Employee.class);
storeConfig.setModel(model);
// Open the environment
envmnt = new Environment(ENVMNT_HOME, envmntConfig);
// Open the entity store
store = new EntityStore(envmnt, STORE_NAME, storeConfig);
// Get a transaction
txn = envmnt.beginTransaction(null, null);
}
Also I have two more classes: EmployeeDao and DepartmentDao
responsibles for giving DB access so this has the method openAllIndex
() in which the indexes are opened: (DepartmentDao is similar)
public class EmployeeDao {
private AbstractDataAccessor<Long, Employee> dao = new
DataAccessor<Long, Employee>();
private DepartmentDao departmentDao;
/* Employee IndexAccessors */
private PrimaryIndex<Long, Employee> employeeById;
private SecondaryIndex<String, Long, Employee> employeeByFirstName;
private SecondaryIndex<String, Long, Employee> employeeByLastName;
private SecondaryIndex<Float, Long, Employee> employeeBySalary;
private SecondaryIndex<Long, Long, Employee> employeeByManagerId;
private SecondaryIndex<Long, Long, Employee> employeeByDepartmentId;
public EmployeeDao() {
openAllIndex();
}
/** Opens all primary and secondary indexes. */
@SuppressWarnings("unchecked")
public void openAllIndex() throws DatabaseException {
/* Primary index of the Employee Parent database. */
dao.openEntityIndex(Long.class, Employee.class);
/* Primary index of the Employee database. */
employeeById = getEmployeeById();
/* Secondary index of the Employee database. */
employeeByFirstName = (SecondaryIndex<String, Long, Employee>) dao
.getSecondaryIndex(employeeById, String.class, "firstName");
employeeByLastName = (SecondaryIndex<String, Long, Employee>) dao
.getSecondaryIndex(employeeById, String.class, "lastName");
employeeBySalary = (SecondaryIndex<Float, Long, Employee>) dao
.getSecondaryIndex(employeeById, Float.class, "salary");
employeeByManagerId = (SecondaryIndex<Long, Long, Employee>) dao
.getSecondaryIndex(employeeById, Long.class, "managerId");
employeeByDepartmentId = (SecondaryIndex<Long, Long, Employee>) dao
.getSecondaryIndex(employeeById, Long.class, "departmentId");
// Opening Department Indexes.
departmentDao = new DepartmentDao();
}
As you can see, I'm using a DataAccessor:
private AbstractDataAccessor<Long, Employee> dao = new
DataAccessor<Long, Employee>();
This "dao" object is encapsulating some DB specific tasks but the idea
is that my Entry point (EmployeeDao and DepartmentDao) keep as simple
as possible.
For instance, this class has a Repository object as an attribute and
my EmployeeDao does not know about this Repository class. EmployeeDao
just use the "dao" object and that all.
Thnx,
dmp