Compare two class attributes using a JPA method - java

I want to compare two attributes using JPA method convention.
This is my class
#Entity
#Table(name = "aircrafts")
public class Aircrafts {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Size(max = 45)
#Column(name = "number", length = 45)
private String number;
#Column(name = "capacity")
private int capacity;
#Column(name = "seats_taken")
private int seatsTaken;
}
And this the method I want to implement :
public interface AircraftsRepository extends JpaRepository<Aircrafts, Long> {
public List<Aircrafts> findBySeatsTakenLessThanCapacity();
}
However I got this exception:
PropertyReferenceException: No property lessThanCapacity found for type int! Traversed path: Aircrafts.seatsTaken.
I've tried using int and Integer but I got the same exception. Which is the correct method name?

I think #benji2505, correctly mentioned that the data model mixes things that "should" be in different tables. Normally one would expect two tables: Aircrafts, Flights.
Then you could easily use:
List<Flight> flightsWithFreeSeats = aircraftRepository
.findAll()
.stream()
.map(aircraft ->
flightRepository.findByAircraftAndSeatsTakenLessThen(aircraft, aircraft.getCapacity)
)
.collect(Collectors.toList)
With current model probably #JZ Nizet already posted the best answer in his comment.

Related

Eradicate boilerplate

public class Toponym {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public int id;
#Column(columnDefinition="TEXT default ''", nullable = false)
public String name;
}
public class LevelOneEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public int id;
#Column(columnDefinition = "boolean default false", nullable = false)
private boolean archived;
}
public class LevelTwoEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public int id;
#Column(columnDefinition = "boolean default false", nullable = false)
private boolean archived;
}
These two classes definitely have some boilerplate code. If multiple inheritance were a reality, I'd organize two mixins here: IdMixin and ArchivedMixin. Therefore classes would contain no bodies at all. But in Java it is not possible.
It may be possible to use multiple interfaces but they can't contain the code itself if I'm not mistaken.
How to cope with such a problem in Java?
If those annotations are allowed on methods, not only on fields (e.g. getters or setters), you can declare them in interfaces and implement as many interfaces as you want. The fields will still be declared in each derived class, though, but you won't need to restate the annotations for them.
Otherwise, you'll have to create a class hierarchy that allows for the flexibility you need:
class Entity // contains annotated ID field and declares the generic ID type
class ArchivedEntity extends Entity // if you don't expect to have non-entity archived classes (i.e. archived objects with no ID)
... etc
This can get pretty complex as you add more combinations.

Get entity with ordered items by field from OneToOne relation in item [duplicate]

I need some help with the JPA Framework.
I've read some answers "kind of" about this topic but I couldn't reach any conclusion.
First heres an examplo of the design i'm wooking with.
#BusinessObject
public class ClassA {
#Column(name = "ID", nullable = false)
private Long id;
#OneToMany(mappedBy = "classAAttr")
private Collection<ClassAB> classABCollection;
//STUFF AND OTHER COLUMNS.....
}
public class ClassAB {
#Column(name = "ID", nullable = false)
private Long id;
#JoinColumn(name = "TABLE_A_ID", referencedColumnName = "ID")
#ManyToOne
private ClassA classAAttr;
#JoinColumn(name = "TABLE_B_ID", referencedColumnName = "ID")
#ManyToOne
private ClassB classBAttr;
//STUFF AND OTHER COLUMNS.....
}
#BusinessObject
public class ClassB {
#Column(name = "ID", nullable = false)
private Long id;
#Column(name = "ORDERCLAUSE", nullable = false)
private String orderClause;
//STUFF AND OTHER COLUMNS.....
}
So I need to order the classABCollection in ClassA by the orderClause attribute in ClassB, but I can't find the right #OrderBy() clause AND/OR location for it.
I've read some things about the Comparator Interface but, unfortunately, due to business policy, I need to be sure that there is no other way...
How Should I Do It?
Thank you guys in advance.
The API docs for #OrderBy note:
The property or field name must correspond to that of a persistent
property or field of the associated class or embedded class within :
http://docs.oracle.com/javaee/6/api/javax/persistence/OrderBy.html
so sorting AB in A by a property of B is not possible.
The alternatives are to write a query or do an in memory sort by some means. Hibernate, for example, has an #Sort annotation which you can use to apply an in-memory sort on load, either by having the target Entity implement Comparable or by specifying a Comparator:
See section 2.4.6.1:
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/
So - I found a roundabout. A query like one below wont work:
select * from A a where xyz
order by a.reference or a.reference.id
However, I found that by adding a function, we can make the query work:
(Do note, the reference need not be null.. and use appropriate values.)
select * from A a where xyz
order by coalesce(a.reference , 0)

Group and sort a collection of collections using JPA

I am looking to make a REST controller that will return a sorted list of various objects.
I have created a DTO to hold these collections like the following, but this will not work as it will group by entity:
public class AllReportsDTO {
private List<AReport> aReports;
private List<BReport> bReports;
private List<CReport> cReports;
...
}
I then have the following Domain objects
#Entity
#Table(name = "a_report")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class AReport implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "title")
private String title;
#Column(name = "description")
private String description;
#Column(name = "time_of_report")
private ZonedDateTime timeOfReport;
And one for each Report.
What I want to do is create an endpoint that will return a list of all these reports but in order of time of the report and not grouped by report. How can I achieve this?
I have tried writing it in the repository with a HQL query and grouping by time, but the issue is that each time field has a different name in each report which I can not alter due to this system being used in other places.
You can create methode that sort your sets. Try to adept this one
Collections.sort( aReports, new Comparator<Object>() {
public int compare(MyObject o1, Object o2) {
return o1.getTimeOfReport().compareTo(o2.getTimeOfReport());
}
});
I wouldn't try a pure HQL solution, or a solution from your ORM. I would go to the Java way.
Add an interface
public interface ITimedReport {
ZonedDateTime getTime();
}
Make all your report class implements this interface by returning their own timestamp
Add a method getAllReports on AllReportsDTO.
This method should fill a List<ITimedReport> with all reports, and then sort the list with a Comparator<ITimedReport>. This comparator would rely on the getTime() to compare.
You can add anything meaningfull for a report in the interface, like a getTitle, getDescription, ...

Hibernate relationship OneToMany(fetch=Lazy) using array of value

Studying hibernate with spring, I've got one question. How can I create relationship OneToMany(fetch=Lazy) using array of value?
In table Path.categoryIds saved a few Place.ids as string, which using #Converter converting from String to int array.
So, how to fill List "places" using int[] placeIds values?
Place table
- int id
- String name
Path table
- int id
- String place_ids (Place.id`s written by comma (ex:"1,2,3"))
#Entity
#Table(name="place")
public class Place {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private int id;
private String name;
}
#Entity
#Table(name="path")
public class Path {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private int id;
#Column(name="category_ids")
#Convert(converter = PlaceIdsConverter.class) // "1,2,3" -> [1,2,3]
private int[] placeIds;
#OneToMany(fetch = FetchType.LAZY) // ???, how to fill using values from placeIds
private List<Place> places;
}
However, case with additional table for ManyToMany relationship is impossible by other causes. :(

JPA #OrderBy() Through Relational Table

I need some help with the JPA Framework.
I've read some answers "kind of" about this topic but I couldn't reach any conclusion.
First heres an examplo of the design i'm wooking with.
#BusinessObject
public class ClassA {
#Column(name = "ID", nullable = false)
private Long id;
#OneToMany(mappedBy = "classAAttr")
private Collection<ClassAB> classABCollection;
//STUFF AND OTHER COLUMNS.....
}
public class ClassAB {
#Column(name = "ID", nullable = false)
private Long id;
#JoinColumn(name = "TABLE_A_ID", referencedColumnName = "ID")
#ManyToOne
private ClassA classAAttr;
#JoinColumn(name = "TABLE_B_ID", referencedColumnName = "ID")
#ManyToOne
private ClassB classBAttr;
//STUFF AND OTHER COLUMNS.....
}
#BusinessObject
public class ClassB {
#Column(name = "ID", nullable = false)
private Long id;
#Column(name = "ORDERCLAUSE", nullable = false)
private String orderClause;
//STUFF AND OTHER COLUMNS.....
}
So I need to order the classABCollection in ClassA by the orderClause attribute in ClassB, but I can't find the right #OrderBy() clause AND/OR location for it.
I've read some things about the Comparator Interface but, unfortunately, due to business policy, I need to be sure that there is no other way...
How Should I Do It?
Thank you guys in advance.
The API docs for #OrderBy note:
The property or field name must correspond to that of a persistent
property or field of the associated class or embedded class within :
http://docs.oracle.com/javaee/6/api/javax/persistence/OrderBy.html
so sorting AB in A by a property of B is not possible.
The alternatives are to write a query or do an in memory sort by some means. Hibernate, for example, has an #Sort annotation which you can use to apply an in-memory sort on load, either by having the target Entity implement Comparable or by specifying a Comparator:
See section 2.4.6.1:
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/
So - I found a roundabout. A query like one below wont work:
select * from A a where xyz
order by a.reference or a.reference.id
However, I found that by adding a function, we can make the query work:
(Do note, the reference need not be null.. and use appropriate values.)
select * from A a where xyz
order by coalesce(a.reference , 0)

Categories