JPA oredered lists #OrderedBy and #OrederColumn - jpa

I have a question about the #OrderBy and #OrderColumn of the JPA spec.
The problem is that I will have an entity that maintains a list of elemets. Each element will appear in several lists. As I understand the #OrderBy and #OrderColumn annotations, you cannot have the same element appear in different positions in many ordered lists. I just can't believe this.
Can someone explain these annotations a bit? The difference between these two annotations? Specifically how I could do soemthing like this:
#Entity
public class Class{
#ManyToMany
private List<Students> studentsInRankedOrder;
// this list should be ordered by class rank.
// but a student who is ranked 1 in one class will most likely not be ranked 1
// in another course.
}
#Entity
public class Student{
#ManyToMany
private List<Class> enrolledIn;
}
Thanks a lot.

http://openjpa.apache.org/builds/2.1.1/apache-openjpa/docs/manual.html#ref_guide_mapping_jpa_coll_order
I understand now. "Order columns are always in the container table." This makes much more sense to me.

Related

Inheritance vs composition in JPA

A legacy application persistence is based on JPA. There is an entity, People, mapped to the database table People.
Now a subset of all the rows in People needs some additional fields.
One possible solution is to use jpa inheritance and create a new entity, suppose EmployeedPeople, which extends People.
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public class People {
...
#Entity(name = “EmployeedPeople”)
public class EmployeedPeople extends People {
Alternatively I can use unidirectional one to one relationship
#Entity(name = “EmployeedPeople”)
public class EmployeedPeople {
...
#OneToOne(optional = false)
private People commonPersonData;
I thought about a third way too: the new entity is based on a database view which joins People table with EmployeedData table.
This last approach is good for reading EmployeedPeople but impractical for inserting and updating because I have to work with different entities (People and EmployeedData).
Which criteria can help in choosing the strategy ?
Which are the pros and cons of each solutions ?
In internet I have already found the following guide which compares the inheritance strategies and this one on composition but my ideas are not clear yet.

JPA why OrderBy is applied to Set

JPA why OrderBy is applied to Set?
https://docs.oracle.com/javaee/7/api/javax/persistence/OrderBy.html
#Entity
public class Person {
...
#ElementCollection
#OrderBy("zipcode.zip, zipcode.plusFour")
public Set<Address> getResidences() {...};
...
}
The Set is supposed to be not ordered. Is it meaningful to annotate #OrderBy
on attributes with Set type?
I think the answer marked as checked on this question can answer also yours.
As mentioned there, the annotation "Specifies the ordering of the elements of a collection valued association or element collection at the point when the association or collection is retrieved."
From what I understand, the annotation is not necessarily connected with the order that the elements are inserted on the Collection type that we use in the entity class.

Possible to ignore #TextIndexed on fields with Spring Data MongoDB?

I have class along the lines of:
public class Person {
#TextIndexed
String name;
List<Person> contacts;
// getters and setters
...
}
The #TextIndexed allows me to search people by name. However, after I recently added a list of contacts I discovered that their names will also be added to the text index. Is there a way around this other than having a separate class - identical to Person but without the #TextIndexed annotations? Perhaps an annotation that will serialize the field but not utilize its indexes?
I am not aware of such an annotation, but one possible way to go about this would be to use polymorphism. For example, an abstract Person class that is extended by both versions (indexed and non-indexed). Then only annotate the name attribute inside the class where you want it indexed.

JPA relation OneToMany

I was thinking that I understand the relations. But now.. Im not sure. I have a problem to add correct annotations.
I have classes Members and Relations.
In Relations
private GT_Member Mother;
private GT_Member Father;
private List<GT_Member> children;
One Member can be in several Relations as Mother or Father (reference to his sex) but he can be only in One relation as child.
I thought annotate Mother and Father as #OneToMany.
But I'm not sure if I can annotate List as #OneToOne ??
This seems like a problem in modeling the correct entity-relationship model for your database schema and visualizing your ORM (Object Relationship Model).
Rather than starting with classes Members and Relations, please first see what are the dominant data-entities in your system. And how would they be related to each other.
Personally I do not think Relation would be a good JPA entity.
Member looks more like a good entity and could embody the relations
Assuming one Father and one Mother, One to Many seems wrong but as a father or mother can have many children, the correct annotation should be #ManyToOne.
Children is definitely OneToMany, and yes you can annotate the List children as #OneToMany.
Member could have the following properties:
#Entity
public class Member implements Serializable{
#ManyToOne
private Member mother;
#ManyToOne
private Member father;
#OnetoMany
private List<Member> children;
}
This solves both your use cases and in this simple example Relation class is not needed.
hope this helps.
Employment of Relation entity is because I want to save information about status of relation. Donc I will store information about all married etc. Entity relation has other fields like type (neutral, married, fiance etc...).

JPA 2.0 retrieve entity by business key

I know there have been a number of similar posts about this, but I couldn't find a clear answer to my problem.
To make it as simple as possible, say I have such an entity:
#Entity
public class Person implements Serializable {
#Id
private Long id; // PK
private String name; // business key
/* getters and setters */
/*
override equals() and hashCode()
to use the **name** field
*/
}
So, id is the PK and name is the business key.
Say that I get a list of names, with possible duplicates, which I want to store.
If I simply create one object per name, and let JPA make it persistent, my final table will contain duplicate names - Not acceptable.
My question is what you think is the best approach, considering the alternatives I describe here below and (especially welcome) your own.
Possible solution 1: check the entity manager
Before creating a new person object, check if one with the same person name is already managed.
Problem: The entity manager can only be queried by PK. IS there any workaround Idon't know about?
Possible solution 2: find objects by query
Query query = em.createQuery("SELECT p FROM Person p WHERE p.name = ...");
List<Person> list = query.getResultList();
Questions: Should the objects requested be already loaded in the em, will this still fetch from database? If so, I suppose it would still be not very efficient if done very frequently, due to parsing the query?
Possible solution 3: keep a separate dictionary
This is possible because equals() and hashCode() are overridden to use the field name.
Map<String,Person> personDict = new HashMap<String,Person>();
for(String n : incomingNames) {
Person p = personDict.get(n);
if (p == null) {
p = new Person();
p.setName(n);
em.persist(p);
personDict.put(n,p);
}
// do something with it
}
Problem 1: Wasting memory for large collections, as this is essentially what the entity manager does (not quite though!)
Problem 2: Suppose that I have a more complex schema, and that after the initial writing my application gets closed, started again, and needs to re-load the database. If all tables are loaded explicitly into the em, then I can easily re-populate the dictionaries (one per entity), but if I use lazy fetch and/or cascade read, then it's not so easy.
I started recently with JPA (I use EclipseLink), so perhaps I am missing something fundamental here, because this issue seems to boil down to a very common usage pattern.
Please enlighten me!
The best solution which I can think of is pretty simple, use a Unique Constraint
#Entity
#UniqueConstraint(columnNames="name")
public class Person implements Serializable {
#Id
private Long id; // PK
private String name; // business key
}
The only way to ensure that the field can be used (correctly) as a key is to create a unique constraint on it. You can do this using #UniqueConstraint(columnNames="name") or using #Column(unique = true).
Upon trying to insert a duplicate key the EntityManager (actually, the DB) will throw an exception. This scenario is also true for a manually set primary key.
The only way to prevent the exception is to do a select on the key and check if it exists.