let be the following entities:
#Entity
public class Person {
#Id
long id;
#ManyToOne
Family fam;
#ManyToOne
Job job;
}
#Entity
class Family{
#Id
long id;
#OneToMany(mappedBy="fam")
#OrderBy("job")
List<Person> p;
}
#Entity
class Job implements Comparable<Job>{
#Id
long id;
String descr;
public int compareTo(Job o) {
return descr.compareTo(o.descr);
}
}
the problem i'm facing comes from the #orderby annotation which, far from what i was expecting, seems to be not supporting the comparable entities.
I'm using the eclipselink 2.3 and wondering if there's any other facility that deals with this problem.
Best Regards
George
#OrderBy is used to sort the entities using an "order by" clause in the generated SQL queries. So, of course, it doesn't the compareTo method. If you want to sort using Java, then just return a sorted list in the getter getPersons().
Related
I have an entity EncodingResult that references three others. I want to find out how to use the repository's findBy() methods to return an entity based on its foreignKey so that I can, for example, make a GET request passing a Video's foreign key as a parameter and return whether or not there is an EncodingResult containing a Video with the given foreignKey.
How would you go about doing this? I tried reading a bit on EntityGraphs and was rather confused. There also doesn't seem to be a great number of content explaining these parts of the framework.
It would be better if you posted the code for your entities, but from your description, I think you have something like this:
#Entity
public class EncodingResult {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#OneToMany(mappedBy = "encodingResult")
private List<Video> videos=new ArrayList<Video>();
//...boilerplate
}
#Entity
public class Video {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
#ManyToOne
EncodingResult encodingResult;
//...boilerplate
}
So you can define findBy methods in your EncodingResultRepository like so.
public interface EncodingResultRepository extends JpaRespository<EncodingResult, Integer> {
public Optional<EncodingResult> findByVideoName(String name);
public Optional<EncodingResult> findByVideoId(Integer id);
}
In my spring data project, there is an entity that looks like:
public class Employee {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(name="id")
private Integer id;
#Column(name="category")
private Category category;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="element_id")
private Department department;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="agency_id")
private Agency agency;
public Employee() {}
// routine getters and setters
}
In my EmployeeRepository, I find that I can derive a method, findEmployeeById() that seems to work in exactly the same way as the usual findById() (but I'm not sure). Can someone explain the difference between these two methods?
Optional<Employee> findEmployeeById (Integer id);
vs
Optional<Employee> findById (Integer id);
I "discovered" this by accident via autocomplete in my side (IntelliJ).
The difference is that while findEmployeeById() searches - as it states - employee by its field named id, findById searches by field annotated as #Id disregarding what is the name of the entity's id field.
In your case - as with many else's - the thing is that the #Id field happens to be named id so the result is the same.
I found similar questions, but they did not answer my question.
I have two entities with a many-to-one relationship - unidirectional.
But most importantly, the relationship is lazy. Because it is correct to use a lazy connection, everyone knows it.
Code:
#Entity
public class User implements BaseEntity {
#Id
#Column
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String name;
#ManyToOne(fetch = FetchType.LAZY)
private City city;
}
#Entity
public class City implements BaseEntity {
#Id
#Column
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String name;
}
interface BaseEntity {
void setId(Long id);
Long getId();
}
I wrote a method that allows you to search by the transferred fields of the entity.
An example of how this works:
public class Search<T extends BaseEntity> {
public List<T> getByFields(T entity, List<FieldHolder> data) {
// create criteria with passed field name and value by reflection
}
}
class FieldHolder {
private String fieldName;
private Object value;
/**
* "true" - means that the field "value" contains id related object
* "false" - elementary type like: String, Wrapper, Primitive
*/
private boolean isRelationId;
}
The problem is that problems start when you need to search and related objects - by creating related queries.
The following entry is used to send the associated field: "city.id" and the problem is that when I transfer the essence of the related object (City) it is in a proxy and I cannot get id by reflection from City.
My function works perfectly if you specify:
#ManyToOne(fetch = FetchType.EAGER)
private City city;
But it will greatly affect performance, since I have a lot of related objects. Therefore, I want to solve this problem for a lazy load.
I know that this is not an easy task. But perhaps there is some opportunity to somehow get around this problem.
I am working on JPA project and I need your help.
I have two classes, “Person” and “Leader” which inherits from Person.
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Person implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(unique = true)
private String personId;
}
And
#Entity
public class Leader extends Person implements Serializable {
private List < Person > listTeam;
public void addPersonInTeam(Person e) {
listTeam.add(e);
}
}
My question Is, do I need to have JPA annotations #OneToMany or something else before private List listTeam in class Leader?
Thank you very much
You need to specify a mapping between the two classes because for Hibernate the association is not relevant here, you have to use annotations in both sides and I guess you will need a OneToMany mapping here :
Here's the mapping that you are seraching for:
In Person class:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Person implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(unique = true)
private String personId;
#ManyToOne
#JoinColumn(name="leader_id")
private Leader leader;
//getter and setter
}
In Leader class:
#Entity
public class Leader extends Person implements Serializable {
#OneToMany(mappedBy = "leader")
private List <Person> listTeam;
//getter and setter
public void addPersonInTeam(Person e) {
listTeam.add(e);
}
}
For further information you can see these links:
Hibernate – One-to-Many example (Annotation).
Hibernate One To Many Annotation tutorial.
Note:
I don't see the use of the field personId in the Person class, there's no need to use two differents ids.
EDIT:
To answer your questions:
The #JoinColumn(name="leader_id") is not mandatory, but it's used to specify the foreign key name.
If the relation is ManyToMany the mappedBy property is used to specify the owner of the relationship, you can see this answer for more details.
I would like to know if there exists some way to use generics in JPA 2.0?
Consider this scenario:
#Entity
public class GenericPhoto<T> implements Serializable {
#Id
#GeneratedValue
private long id;
#NotNull
private byte[] file;
#ManyToOne(cascade = { CascadeType.DETACH })
#JoinColumn(name = "PARENTID", nullable = false)
#NotNull
private T parent;
//...
}
#Entity
public Car {
#OneToMany(mappedBy = "parent")
private Set<GenericPhoto<Car>> photos;
//...
}
#Entity
public Truck {
#OneToMany(mappedBy = "parent")
private Set<GenericPhoto<Truck>> photos;
//...
}
I hope the code explains it all. I simply want to make a generic class for photo, which I think makes it easier to implement services etcetera.
Best regards
When you use a generic, it is similar to not typing the field (i.e. Object parent), so you need to tell JPA how to map the relationship. For this you can use targetEntity in JPA.
For this to work, you will need a common superclass to Car and Truck i.e. Auto, and set the targetEntity in the #ManyToOne to Auto (you may also consider moving photos up to Auto).
If you can't use inheritance for some reason, (it is best to use inheritance). Then if you use EclipseLink you could use a #VariableOneToOne relationship.