Composite key with JPA entity, implementing tree of objects in one table? - jpa

I have one table named PLACES with one composite primary key (parent_id, version_id). It is a tree of objects, which are linked through the keys. One child has just one parent, and one parent may have many children.
How can I describe it with JPA entity?

Use a ManyToOne relation from the child to the parent.
This is for OpenJpa. Might even work.
public class Place{
#EmbeddedId
PlaceId id;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumns({
#JoinColumn(name="PARENT_ID" referencedColumnName="ID"), // ID = matching primary key
#JoinColumn(name="PARENT_VER" referencedColumnName="VER") //etc
})
public Place parent;
#OneToMany(fetch=FetchType.LAZY, mappedBy="parent")
public List<Place> childPlaces;
}
The OneToMany relation might be omitted if it's not needed. If I remember correctly, it needs to be managed, ie childs need to be inserted there too when creating child-places, by you, using java.
Btw.
I would advise against using a version column in a composite key in order to manually keep old versions of your data (for auditing or similar purposes) as that slows down and complicates all joins, and generally will make you miserable at some point in your life - As opposed to using a version column that is not part of a composite key, used for optimistic locking.
You might want to look into some kind of build in support for auditing/logging. OpenJpa has auditing support (OpenJPA Audit) and most database provide some support, either out-of-the-box or by using triggers. All alternatives are faster and better than using composite keys.

Related

How to get foreign key value from not fetched relationship?

Having two entities defining relationship by #ManyToOne and #OneToMany, how can I get foreign key without asking from related object and just by looking at defining tables? How do I get OWNER_ID from Owned by something like owned.getOwnerId() instead of owned.getOwner().getId() and still be able to owned.getOwner()?
Map the field in your entity as a basic mapping allows you to use the foreign key directly. You can keep the object reference mapping as well, but one of the two mappings must then be marked as insertable=false, updatable=false so that JPA knows which mapping controls the field in the event they show different values.

Entity Framework associations with nullable columns and without foreign keys

I am attempting to use Entity Framework with a database that does not make use of foreign keys. To make matters worse, tables that have a relationship make use of relating fields that can be null. For example the Order table has a column for ClientID that is nullable. Keeping in mind I did not create this database nor can I change it I would like to still be able to use Entity Framework (v6.1) to perform CRUD operations on the database.
The problem, as you might expect, has to do with the association between entities. I can create the associations myself manually but I cannot set the referential integrity because the properties in the entities map to columns in the database that can be NULL.
Is there a way to get around this? Perhaps a way to use the associations without having to define referential integrity? Granting that it would be up to me to make sure that any child records be deleted if a given parent is deleted..
I think this will work:
public class Order
{
//other properties
public int? ClientId {get; set;}
}
And set
modelBuilder.Entity<Order>()
.HasOptional(x=>x.Client)
.WithMany(x=>x.Orders)
.WithForeignKey(x=>x.CliendId);

How to optionally persist secondary table in Eclipselink

I am working with Eclipselink and having issue with using secondary table.
I have two tables as below.
Student with columns student_id(Primary Key), student_name etc.
Registration with columns student_id(FK relationship with Student table), course_name (with not null constraint) etc.
The requirement is student may or may not have registration. If student has registration, the data should be persisted to Registration table as well. Otherwise only Student table should be persisted.
My code snippet is as below.
Student.java
------------
#Entity
#Table(name = "STUDENT")
#SecondaryTable(name = "REGISTRATION")
#Id
#Column(name = "STUDENT_ID")
private long studentId;
#Basic(optional=true)
#Column(name = "COURSE_NAME", table = "REGISTRATION")
private String courseName;
I tried the following scenarios.
1. Student with registration - Working fine. Data is added to both Student and Registration tables
2. Student without registration - Getting error such as 'COURSE_NAME' cannot be null.
Is there a way to prevent persisting into secondary table?
Any help is much appreciated.
Thanks!!!
As #Eelke states, the best solution is to define two classes and a OneToOne relationship.
Potentially you could also use inheritance, having a Student and a RegisteredStudent that adds the additional table. But the relationship is a much better design.
It‘s possible using a DescriptorEventListener. The aboutToInsert and aboutToUpdate callbacks have access to the DatabaseCalls and may even remove the statements hitting the secondary table.
Register the DescriptorEventListener with the ClassDescriptor of the entity. For registration use a DescriptorCustomizer specified in a Customizer annotation at the entity.
However, you will not succeed fetching the entities back again later on. EclipseLink uses inner joins when selecting from the secondary table, so that the row of the primary table will be gone in the results.

Auditing #ElementCollection/#Embeddable with hibernate-envers

I'm trying to audit a collection of #Embeddable objects using hibernate-envers.
According to https://hibernate.atlassian.net/browse/HHH-6613 support for auditing #ElementCollection was added. This feature doesn't seem to work well: when trying to save several #Embeddable objects with the same revision number NonUniqueObjectException is thrown.
Does anyone have a working example of #ElementCollection+#Embeddable audited with Envers?
As of Hibernate 5.2.8, we managed to make it work by these steps:
Define the java type as Set for the collection of embeddable elements
Implement hashCode() and equals() methods in the class of the embeddable elements
Be sure to create an int column named SETORDINAL in the table that holds
the audit log of said elements (or let hibernate create the tables for you
by setting the appropriate configuration key).

JPA and selective ManyToOne relationship

Sure this is a simple answer, but I cannot find the right source to give the details.
I have a ManyToOne relationship. Because of a synchronization system, when a child is removed a field named 'removed' is set to 'true', and will automatically be deleted only a month later.
However, in the meanwhile, I would like it not to appear in the List in the parent. Is there an easy way to specify a select statement in the definition of the field or so?
#OneToMany(mappedBy = "parent")
#OrderBy("level")
public List<MenuItem> children;
As you are using hibernate you can use the #where annotation. I never used it myself but it seems quite straight forward. Have a look here: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-hibspec-collection