Even after reading the documentation, I seem to have a fundamental misunderstanding about Google App Engine’s entity groups. My goal is a trivial example of ORM: I’ve got some Employees assigned to Departments. An employee can only be assigned to one department, but a department can have many employees. It’s your standard one-to-many relationship.
Given the employee’s key (email) and a department name, I want to look up both the employee and department objects, and if they don’t exist, to create them.
What follows is pseudocode, not meant to compile. If producing code that will compile would help you help me, I’d be happy to do so, but I think my problem is conceptual.
Data Objects:
@Entity
public class Department {
private Key key;
private String name;
// getters and setters
}
@Entity
@NamedQuery(name="getEmployeesInDept", query="SELECT a from Employee a WHERE a.dept=:dept")
public class Employee {
private Key key;
private String firstName;
@ManyToOne
private Department dept;
// getters and setters
}
Look Up or Create
Key employeeKey = KeyFactory.createKey("Employee", email);
Employee employee = entityManager.find(Employee.class, employeeKey);
if(employee == null)
{
Key deptKey = KeyFactory.createKey("Department", deptName);
Department dept = entityManager.find(Department.class, deptKey);
if(dept == null)
{
dept = new Department();
dept.setKey(deptKey);
dept.setName(deptName);
entityManager.persist(dept);
}
employee = new Employee();
employee.setKey(employeeKey);
employee.setFirstName(firstName);
employee.setDept(dept);
entityManager.persist(employee);
}
entityManager.close();
print("Found employee " + employee.getFirstName() + " from " + dept.getName() + " department!");
That’s the logic that worked perfectly when I was using ye olde generic ORM before I tried migrating to Google App Engine.
However, on GAE, I get an exception like:
javax.persistence.PersistenceException: Detected attempt to establish
Employee(“bob@mycompany.com”) as the parent of Department(14) but the
entity identified by Department(14) has already been persisted without
a parent. A parent cannot be established or changed once an object has
been persisted.
While I understand that in order to get Employee and Department into the same entity group (which I would prefer), I have to make one of them the parent of the other, their relationship isn’t really one that fits into the parent-child paradigm in my mind.
I have tried wrapping various parts between entityManager.getTransaction().begin() and entityManager.getTransaction().end(), but to no avail.
I can get around this by including Department’s key as part of Employee’s key (thus making Department the parent of Employee), but then I have no idea how to look up an Employee based on their email and figure out what department they’re in, or, conversely, how to look up all the employees in a given department.
Does this make sense? How should I structure this relationship in GAE? Surely this is a very common pattern that has a simple solution that is just eluding me.
I’m convinced that there’s some fundamental piece of this puzzle that I’m missing, because it seems rather ridiculous that a simple many-to-one foreign key cannot be easily represented in GAE’s ORM.
Cheers!
So if it doesn’t fit owned relationships then make it unowned, which is supported in v2.x of the GAE JPA plugin.