OpenJPA OneToMany and composite key in parent and child table - java

I have tables with composited primary key.
Server(key=ServerId)
ServerId|Name
1 |server1
2 |server2
ParentObj(key=ServerId+Code)
ServerId|Code |Title
1 |code1|value1
1 |code2|value2
2 |code1|Value2b
ChildObj(key=ServerId+Code+Name)
ServerId|Code |Name |Value
1 |code1|prop1|val1
1 |code1|prop2|val2
1 |code2|prop1|val1b
2 |code1|prop3|val3
This is Java beans I have.
#Entity #Table(name="ParentObj") #Access(AccessType.FIELD)
#IdClass(value=ParentObj.PK.class)
#XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
#XmlRootElement
public class ParentObj {
#Id private long serverId;
#Id private String code;
private String title;
public long getServerId() { return serverId; }
public String getCode() { return code; }
public String getTitle() { return title; }
public static class PK implements Serializable {
private static final long serialVersionUID = 1L;
private long serverId;
private String code;
public long getServerId() { return serverId; }
public void setServerId(long id) { serverId=id; }
public String getCode() { return code; }
public void setCode(String code) { this.code=code; }
}
}
#Entity #Table(name="ChildObj") #Access(AccessType.FIELD)
#IdClass(value=ChildObj.PK.class)
#XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
#XmlRootElement
public class ChildObj {
#Id private long serverId;
#Id private String code;
#Id private String name;
private String value;
// public getter+setters for each field
public static class PK implements Serializable {
private static final long serialVersionUID = 1L;
private long serverId;
private String code;
private String name;
public long getServerId() { return serverId; }
public void setServerId(long id) { serverId=id; }
public String getCode() { return code; }
public void setCode(String code) { this.code=code; }
public String getName() { return name; }
public void setName(String name) { this.name=name; }
}
}
I have been trying "everything" to create OneToMany mapping(ParentObj->ChildObj) but nothing seem to work. I don't need ManyToOne(ParentObj<-ChildObj) link but that's ok if one must be defined.
This is a legacy database so I cannot insert an auto_increment identity column or create extra join table between parent and childs.
This annotation is conceptually what I want but multiple join columns is not accepted by OpenJPA2.x library.
// from parent to zero or more childs
#OneToMany(fetch=FetchType.LAZY)
#JoinColumns({
#JoinColumn(name="server_id", referencedColumnName="server_id"),
#JoinColumn(name="code", referencedColumnName="code")
})
private List<ChildObj> properties;
Edit, answer
OneToMany, ManyToOne and EmbeddedId annotations works. I have only tried reading existing rows but its fine for now. Later I try update+insert+delete tasks.
public class ParentObj {
#EmbeddedId ParentObj.PK pk;
#OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="parent", orphanRemoval=true)
private List<ChildObj> childs;
public PK getPK() { return pk; }
public void setPK(PK pk) { this.pk=pk; }
public List<ChildObj> getChilds() { return childs; }
...
#Embeddable #Access(AccessType.FIELD)
public static class PK implements Serializable {
private static final long serialVersionUID = 1L;
#Column(nullable=false) private long serverId;
#Column(nullable=false) private String code;
..getters+setters+hashCode+equals functions
}
}
public class ChildObj {
#EmbeddedId ChildObj.PK pk;
#ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.PERSIST, optional=false)
#JoinColumns({
#JoinColumn(name="serverid", referencedColumnName="serverid", nullable=false),
#JoinColumn(name="code", referencedColumnName="code", nullable=false)
})
private ParentObj parent;
public PK getPK() { return pk; }
public void setPK(PK pk) { this.pk=pk; }
public long getServerId() { return pk.getServerId(); }
public String getCode() { return pk.getCode(); }
public String getName() { return pk.getName(); }
...
#Embeddable #Access(AccessType.FIELD)
public static class PK implements Serializable {
private static final long serialVersionUID = 1L;
#Column(nullable=false) private long serverId;
#Column(nullable=false) private String code;
#Column(nullable=false) private String name;
..getters+setters+hashCode+equals functions
}
}

The easiest way to do this is to create an association from ChildObj to ParentObj similar to the following:
#ManyToOne(fetch = FetchType.LAZY, optional = true)
#JoinColumns({
#JoinColumn(name = "serverId", referencedColumnName = "serverId"),
#JoinColumn(name = "code", referencedColumnName = "code")})
private ParentObj parentObj;
and then define the #OneToMany association in ParentObj like this:
#OneToMany(mappedBy = "parentObj", fetch=FetchType.LAZY)
private List<ChildObj> children;
I would also recommend that you define your composite keys as #Embeddable classes, used as #EmbeddedId references in the Entities. These embeddable PK classes should be separate classes (not inner classes), as you will use them separately to query the related Entities, and serialisation of inner classes can cause problems

Related

Add foreign key using hibernate and jpa

Those are my classes:
#Entity
#Table(name="assessment")
public class AssesmentProperties {
#Id
#Column(name="AssessmentId")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long AssessmentId;
#Column(unique=true,nullable=false)
private String AssessmentName;
private String AssessmentLevel;
private String Specialization;
private int time;
private String keywords;
private int NoOfSections;
//getters and setters
}
#Embeddable
public class SettingsPrimary implements Serializable {
private Long AssessmentId;
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long Section;
//getters and setters
}
#Entity
#Table(name="section")
public class SectionProperties {
#EmbeddedId
private SettingsPrimary PrimaryKey;
private String SectionType;
private int Weightage;
private int time;
private int NoOfQuestions;
//getters and setters
}
In the table section I need to create assessment_id as FK to assessment table and set cascade on delete. I have tried to do it with different ways but without success.
Maybe this could help you.
#Entity
#Table(name="section")
public class SectionProperties {
#Id
private Long PrimaryKey;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "assessment_id", referencedColumnName="AssessmentId")
private AssesmentProperties AssesmentProperties;
private String SectionType;
private int Weightage;
private int time;
private int NoOfQuestions;
//getters and setters
}
I changed the SectionProperties id to a Long and mapped the AssessmentProprties into a ManytoOne prop.
This way, always that a AssessmentProperties binded to a Section will be deleted, the associated SectionProperties will too.

Save an entity and all its related entities in a single save in spring boot

I'm using Spring Boot,REST and JPA to build my application. In app, there are 2 entities with one to many relationship.
Entity 1 :
#Entity
#Table( name = "report")
#JsonIgnoreProperties(ignoreUnknown = true)
public class CustomReport {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "REPORT_SEQ")
#SequenceGenerator(sequenceName = "REPORT_SEQ", allocationSize = 1, name = "REPORT_SEQ")
private Long id;
private String name;
private Long createdBy;
private Timestamp lastModifiedTimestamp;
#OneToMany(mappedBy = "customReport", cascade = CascadeType.ALL)
private Set<CustomReportActivity> customReportActivitySet;
public Set<CustomReportActivity> getCustomReportActivitySet() {
return customReportActivitySet;
}
public void setCustomReportActivitySet(Set<CustomReportActivity> customReportActivitySet) {
this.customReportActivitySet = customReportActivitySet;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Long createdBy) {
this.createdBy = createdBy;
}
public Timestamp getLastModifiedTimestamp() {
return lastModifiedTimestamp;
}
public void setLastModifiedTimestamp(Timestamp lastModifiedTimestamp) {
this.lastModifiedTimestamp = lastModifiedTimestamp;
}
}
Entity 2:
#Entity
#Table( name = "report_activity")
public class CustomReportActivity {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "REPORT_ACTIVITY_SEQ")
#SequenceGenerator(sequenceName = "REPORT_ACTIVITY_SEQ", allocationSize = 1, name = "REPORT_ACTIVITY_SEQ")
private Long id;
String activityName;
#ManyToOne
#JoinColumn( name="report_id" )
#JsonBackReference
private CustomReport customReport;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getActivityName() {
return activityName;
}
public void setActivityName(String activityName) {
this.activityName = activityName;
}
public CustomReport getCustomReport() {
return customReport;
}
public void setCustomReport(CustomReport customReport) {
this.customReport = customReport;
}
}
And my request JSON is as follows :
{
"name": "test report",
"createdBy" : 129,
"customReportActivitySet": [
{"activityName":"a"},
{"activityName":"b"},
{"activityName":"c"},
{"activityName":"d"},
{"activityName":"e"}
]
}
I want to save both entities in one shot. I've implemented the save functionality in following way:
#RequestMapping(value="/save", method = RequestMethod.POST)
public ResponseEntity<?> addReport(#RequestBody CustomReport customReport) {
return new ResponseEntity<>(customReportService.createCustomReport(customReport), HttpStatus.CREATED);
}
CustomReportService method:
public CustomReport createCustomReport(CustomReport customReport) {
return customReportRepository.save(customReport);
}
CustomRepository:
public interface CustomReportRepository extends CrudRepository<CustomReport, Long> {
}
But I'm getting the constraint violation exception with this:
java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot
insert NULL into ("REPORT_ACTIVITY"."REPORT_ID")
Is it possible to save both entities in one save operation?
Please help!
You would have to add a small piece of code which would populate each CustomReportActivity within the CustomReport instance. Only then the persistence provide can successfully perform the cascade save operation:
public CustomReport createCustomReport(CustomReport customReport) {
customReport.getCustomReportActivitySet.forEach((activity) -> {
activity.setCustomReport(customReport);
});
return customReportRepository.save(customReport);
}
The bottom line is that the dependencies have to be set on both sides of the relationship.
Try this sample, in my case it worked as expected, child entities are saved automatically in a single save operation with creating relations to the parent entity:
#Entity
public class Parent {
#Id
private Long id;
#JoinColumn(name = "parentId")
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Child> children;
}
#Entity
public class Child {
#Id
private Long id;
private Long parentId;
}

Java Persistence Composite ID

I'm trying to insert a record with composite primary key, but at the time of saving a new record I get this message:
e = (org.springframework.orm.jpa.JpaSystemException)
org.springframework.orm.jpa.JpaSystemException: Could not set field
value [POST_INSERT_INDICATOR] value by reflection...
#Getter
#Setter
#Entity
#EqualsAndHashCode
#Table(name = "produto")
#IdClass(ProdutoId.class)
public class Produto implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_produto")
private Long idProduto;
#Id
#Column(name = "oficina", insertable = false, updatable = false)
private Long idOficina;
#ManyToOne
#JoinColumn(name = "oficina")
private Oficina oficina;
}
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
#Data
public class ProdutoId implements Serializable {
public Long idProduto;
public Long idOficina;
}
#Repository
public interface ProdutoRepository extends JpaRepository<Produto, ProdutoId> {}
Has anyone ever seen a bug like this?
To create composite primary key you can refer this example,
#Entity
#Table(name="testuserrole")
public class UserRole{
#EmbeddedId
private UserRoleId id = new UserRoleId();
public UserRoleId getId() {
return id;
}
public void setId(UserRoleId id) {
this.id = id;
}
#Transient
public long getUserId() {
return id.userId;
}
public void setUserId(long userId) {
id.userId=userId;
}
#Transient
public long getRoleId() {
return id.roleId;
}
public void setRoleId(long roleId) {
id.roleId=roleId;
}
}
#Embeddable
class UserRoleId implements Serializable {
#Column(name = "user_id")
public long userId;
#Column(name = "role_id")
public long roleId;
}

java.lang.IllegalArgumentException: expecting IdClass mapping

I have configured composite primary key for my entity Employee as follows
Employee.java:
#Entity
#Table(name="employee")
#Proxy(lazy=false)
#IdClass(EmployeeId.class)
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private EmployeeId employeeId;
private Person person;
private Branch branch;
private boolean isActive;
public Employee() {
}
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name="person", column = #Column(name="person_id")),
#AttributeOverride(name="branch", column = #Column(name="branch_id"))})
public EmployeeId getEmployeeId() {
return employeeId;
}
public void setEmployeeId(EmployeeId employeeId) {
this.employeeId = employeeId;
}
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="person_id")
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="branch_id")
public Branch getBranch() {
return branch;
}
public void setBranch(Branch branch) {
this.branch = branch;
}
#Column(name="is_active")
public boolean getIsActive() {
return isActive;
}
public void setIsActive(boolean isActive) {
this.isActive = isActive;
}
}
EmployeeId.java:
#Embeddable
public class EmployeeId implements Serializable {
private static final long serialVersionUID = 1L;
private Person person;
private Branch branch;
public EmployeeId() {
}
public EmployeeId(Person argPerson, Branch argbranch) {
this.person = argPerson;
this.branch = argbranch;
}
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="person_id", insertable=false, updatable=false)
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="branch_id", insertable=false, updatable=false)
public Branch getBranch() {
return branch;
}
public void setBranch(Branch branch) {
this.branch = branch;
}
}
I created a SessionFactory bean using class org.springframework.orm.hibernate5.LocalSessionFactoryBean and mapped all hbm.xml as a MappingLocations.
My code throws the following error:
Caused by: java.lang.IllegalArgumentException: expecting IdClass mapping
at org.hibernate.metamodel.internal.AttributeFactory$3.resolveMember(AttributeFactory.java:971)
at org.hibernate.metamodel.internal.AttributeFactory$5.resolveMember(AttributeFactory.java:1029)
at org.hibernate.metamodel.internal.AttributeFactory.determineAttributeMetadata(AttributeFactory.java:451)
at org.hibernate.metamodel.internal.AttributeFactory.buildIdAttribute(AttributeFactory.java:128)
at org.hibernate.metamodel.internal.MetadataContext.buildIdClassAttributes(MetadataContext.java:337)
at org.hibernate.metamodel.internal.MetadataContext.applyIdMetadata(MetadataContext.java:269)
at org.hibernate.metamodel.internal.MetadataContext.wrapUp(MetadataContext.java:190)
at org.hibernate.metamodel.internal.MetamodelImpl.initialize(MetamodelImpl.java:219)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:296)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:476)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:707)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:723)
at org.springframework.orm.hibernate5.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:504)
at org.springframework.orm.hibernate5.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:488)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFac
How can I avoid this error? I am using spring-orm-4.3.1-RELEASE and hibernate-core-5.2.0.Final.
Update
I have created a sample project and I am getting the following error while running...
Caused by: org.hibernate.AnnotationException: Property of #IdClass not found in entity sample.domain.Employee: employee
Refer the code: https://www.dropbox.com/s/axr8l01iqh0qr29/idclass-using-hibernate5.tar.gz?dl=0
What I did wrong? Kindly provide your inputs here
Your situation corresponds to the chapter 2.4.1 Primary Keys Corresponding to Derived Identities of the JPA 2.1 Specification.
The identity of Employee is derived from identities of Person and Branch. You haven't shown the code of either of them, so I'll assume they have simple primary keys. In that relationship, Person and Branch are "parent entities" and Employee is a "dependant" entity.
The ID of Employee may be mapped using either IdClass or EmbeddedId, not both at the same time.
See chapter 2.4.1.1 Specification of Derived Identities.
If you want to use IdClass, then:
The names of the attributes of the id class and the Id attributes of the dependent entity class must correspond as follows:
The Id attribute in the entity class and the corresponding attribute in the id class must have the same name.
...
If an Id attribute in the entity is a many-to-one or one-to-one relationship to a parent entity, the corresponding attribute in the id class must be of (...) the type of the Id attribute of the parent entity.
So your classes would look like this (getters, setters, superfluous annotations etc. omitted)
#Entity
#IdClass(EmployeeId.class)
public class Employee {
#Id
#ManyToOne
private Person person;
#Id
#ManyToOne
private Branch branch;
}
public class EmployeeId {
private Long person; // Corresponds to the type of Person ID, name matches the name of Employee.person
private Long branch; // Corresponds to the type of Branch ID, name matches the name of Employee.branch
}
If you use EmbeddedId, then:
If the dependent entity uses an embedded id to represent its primary key, the attribute in the embedded id corresponding to the relationship attribute must be of the same type as the primary key of the parent entity and must be designated by the MapsId annotation applied to the relationship attribute. The value element of the MapsId annotation must be used to specify the name of the attribute within the embedded id to which the relationship attribute corresponds.
And the code would look like this:
#Entity
public class Employee {
#EmbeddedId
private EmployeeId id;
#ManyToOne
#MapsId("personId") // Corresponds to the name of EmployeeId.personId
private Person person;
#ManyToOne
#MapsId("branchId") // Corresponds to the name of EmployeeId.branchId
private Branch branch;
}
#Embeddable
public class EmployeeId {
private Long personId; // Corresponds to the type of Person ID
private Long branchId; // Corresponds to the type of Branch ID
}
A composite key mapping can be either done with an IdClass or an Embeddable. If you want to use an IdClass you have to annotate your fields in Employee with #Id.
#IdClass(EmployeeId.class)
class Person{
#Id
private Person person;
#Id
private Branch branch;
}
If you want to use an Embedded as a composite key please remove the #IdClass(EmployeeId.class) annotation from Person. You also don't need the person and branch field in your Person class because those are defined in your Embedded class.
Change to:
#Entity
#Table(name = "employee")
#Proxy(lazy = false)
#IdClass(EmployeeId.class)
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private EmployeeId id;
private Person person;
private Branch branch;
private boolean isActive;
public Employee() {
}
#EmbeddedId
#AttributeOverrides({#AttributeOverride(name = "person", column = #Column(name = "person_id") ),
#AttributeOverride(name = "branch", column = #Column(name = "branch_id") )})
public EmployeeId getId() {
return id;
}
public void setId(EmployeeId id) {
this.id = id;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "person_id")
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "branch_id")
public Branch getBranch() {
return branch;
}
public void setBranch(Branch branch) {
this.branch = branch;
}
#Column(name = "is_active")
public boolean getIsActive() {
return isActive;
}
public void setIsActive(boolean isActive) {
this.isActive = isActive;
}
}
The IdClass shouldnt be defined as Embeddable -
#Entity
#Table(name="employee")
#IdClass(EmployeeId.class)
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#ManyToOne
private Person person;
#Id
#ManyToOne
private Branch branch;
private boolean isActive;
public Employee() { }
//....
}
And -
public class EmployeeId implements Serializable {
private static final long serialVersionUID = 1L;
private Person person;
private Branch branch;
public EmployeeId() {}
public EmployeeId(Person argPerson, Branch argbranch) {
this.person = argPerson;
this.branch = argbranch;
}
}
Read your comment - Can I make a suggestion that you map Employee to person_id and branch_id, and not the JPA objects Person and Branch? This will let us test if your hbm config is correct. Id also suggest posting your hbm config as I think there is information missing from this problem
So the table will be similar to -
#Entity
#Table(name="employee")
#IdClass(EmployeeId.class)
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private Long personId;
#Id
private Long branchId;
private boolean isActive;
public Employee() { }
//....
}
And -
And -
public class EmployeeId implements Serializable {
private static final long serialVersionUID = 1L;
private Long personId;
private Long branchId;
public EmployeeId() {}
public EmployeeId(Person argPerson, Branch argbranch) {
this.person = argPerson;
this.branch = argbranch;
}
}
This link could help you
JPA - EmbeddedId with #ManytoOne
Relationship mappings defined within an embedded id class are not supported.Then you need to change the embeddedId class like this
#Embeddable
public class EmployeeId implements Serializable {
private static final long serialVersionUID = 1L;
private Long personId;
private Long branchId;
public EmployeeId() {
}
public EmployeeId(Long argPerson, Long argbranch) {
this.personId = argPerson;
this.branchId = argbranch;
}
#Column(name = "person_id")
public Long getPersonId() {
return personId;
}
public void setPersonId(Long personId) {
this.personId = personId;
}
#Column(name = "branch_id")
public Long getBranchId() {
return branchId;
}
public void setBranchId(Long branchId) {
this.branchId = branchId;
}
}
JPA Composite Primary Key
Specifies a composite primary key class that is mapped to multiple fields or properties of the entity.
The names of the fields or properties in the primary key class and the
primary key fields or properties of the entity must correspond and
their types must be the same.
The answer is in here. read description for you. enter link description here
(Sample code)
#Entity
#Table(name = "EMP_PROJECT")
#IdClass(ProjectAssignmentId.class)
public class ProjectAssignment {
#Id
#Column(name = "EMP_ID", insertable = false, updatable = false)
private int empId;
#Id
#Column(name = "PROJECT_ID", insertable = false, updatable = false)
private int projectId;
#ManyToOne
#JoinColumn(name = "EMP_ID")
Professor employee;
#ManyToOne
#JoinColumn(name = "PROJECT_ID")
Project project;
....
}
public class ProjectAssignmentId implements Serializable {
private int empId;
private int projectId;
...
}
Mention #IdClass annotation with the class which holds the ID.
Check the answer at this post

JPA, Eclipselink - Relations are deleted on new transaction

I'm building a small eclipse rcp with a little bit of JPA. Now something strange happens:
I create some TopCategories with some SubCategories, this works as intended. The inserts are printed in the log. I close my application and now the problem raises up:
The Categories have a relation to books
Book.java
#Entity
public class Book implements Serializable, PropertyChangeListener {
private static final long serialVersionUID = 4646743297687986216L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private boolean active = true;
#Temporal(TemporalType.TIMESTAMP)
private Date updated;
#Lob
private Set<Group> allowedGroups;
#Column(columnDefinition = "TEXT")
private String text;
private BookType type;
#ManyToOne
private TopCategory topCategory;
#ManyToOne
private SubCategory subCategory;
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private BookAttachment attachment;
#Transient
private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
// ordinary getter/setter
#PrePersist
#PreUpdate
private void updateUpdated() {
this.updated = new Date();
}
}
After restart and querying Book with this select b from Book all SubCategories which aren't used getting deleted. If a SubCategory has a relation to Book it stays in my DB. Why this occures?
Category.java
#MappedSuperclass
public class Category implements Serializable {
private static final long serialVersionUID = 6091963773161164543L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
#Temporal(TemporalType.TIMESTAMP)
private Date updated;
#Enumerated(EnumType.STRING)
private CategoryType type;
#Transient
private List<Snippet> snippets = new LinkedList<Snippet>();
// ordinary getter/setter
#PrePersist
#PreUpdate
public void updateUpdated() {
this.updated = new Date();
}
}
TopCategory.java
#Entity
public class TopCategory extends Category {
#OneToMany(cascade = CascadeType.ALL)
private List<SubCategory> subCategories;
public TopCategory() {
setName("");
setSubCategories(new ArrayList<SubCategory>());
}
public List<SubCategory> getSubCategories() {
return subCategories;
}
public void setSubCategories(List<SubCategory> subCategories) {
this.subCategories = subCategories;
}
#Override
public void setType(CategoryType type) {
super.setType(CategoryType.topCategory);
}
SubCategory.java
#Entity
public class SubCategory extends Category {
#ManyToOne(cascade = CascadeType.ALL)
private TopCategory topCategory;
public TopCategory getTopCategory() {
return topCategory;
}
public void setTopCategory(TopCategory topCategory) {
this.topCategory = topCategory;
}
#Override
public void setType(CategoryType type) {
super.setType(CategoryType.subCategory);
}
}
I'm using Eclipselink 2.1.1.
Regards
Alright - I've found the problem: One of the result lists from my model is modified from a contentprovider - this is were not used SubCategories are removed, in case that the entity objects weren't detached, it caused the entitymanger to update.

Categories