FindBy and OrderBy doesn't order accordingly - Spring Data Jpa - spring

I am using this method :
List<Client>findTop10ByGenderOrderBySurvey_Results_ScoreDesc(char gender);
The logic is this :
I have a Client Model, with a reference OneToMany to the Survey Model, and the Survey Model has a reference of OneToOne with the Results model which has the score field.
So one Client can have many surveys each of which has a score.
I wanted to order the Clients By their score, in descending order, and then get top10 Male Clients with highest score.
The method I'm using does filter By Gender, and returns 10 Clients.
But it returns the same Client more than once,because it has several surveys. And not in an ordered manner.
What am I doing wrong and how do I fix this ?
public class Client {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "client_id")
private Long id;
#Column(name = "gender")
private char gender;
#OneToMany(mappedBy = "client", cascade = CascadeType.ALL)
#JsonManagedReference
private List<Survey> survey= new ArrayList<Survey>();
}
public class Survey{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "SURVEY_ID")
private Long Id;
#ManyToOne
#JsonBackReference
#JoinColumn(name = "client_id")
public Client client;
#OneToOne(cascade=CascadeType.ALL)
#JsonManagedReference
#JoinColumn(name = "surveyresult_id")
private Results surveyResults;
}
public class Results {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "SURVEYRESULT_ID")
private Long Id;
private Double score;
}

To filter out duplicate results, use the distinct keyword:
List<Client> findDistinctTop10ByGenderOrderBySurvey_Results_ScoreDesc(char gender);
The OrderBy syntax is incorrect. To order by multiple properties, simply append them like this:
List<Client> findDistinctTop10ByGenderOrderBySurveyDescResultsDescScoreDesc(char gender);
Note: When method names become very long, it is a sign the query might be too complex to be a derived query. It is then recommended to use #Query with a shorter, higher-level method name to describe the query.

Related

How to save an object that contains a list of integers in a postgres database

i have an object called Cart i want to save it in the database with an array/list of integers that rappresents Product's id.
This is my Cart class at the moment:
public class Cart {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Integer id;
#Column(name = "customer_fk")
private Integer customerFk;
#Column(name = "product_list")
private List<Integer> productList;
}
i saw that postgres has the integer[] datatype
I'm using spring.jpa.hibernate.ddl-auto=create to create the database
How do i tell to spring and jpa to save that list as an integer in the DB?
(if i can)
Is this a good solution?
I actually found a solution that works, using Strings, but im too curious to see if find a way to do it with arrays
The canonical approach here would be to maintain a table of products and then map carts to products in a one to many relationship. You could try:
#Entity
#Table(name = "Cart")
public class Cart {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Integer id;
#Column(name = "customer_fk")
private Integer customerFk;
#Column(name = "product_list")
#OneToMany(mappedBy="cart", cascade = CascadeType.ALL)
private List<Product> productList;
}
#Entity
#Table(name = "Product")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Integer id;
#ManyToOne
#JoinColumn(name = "FK_Cart")
private Cart cart;
// more fields, getters and setters
}
This is not a complete implementation, but the idea is that each product ID should exist in a dedicated products table, and each cart entity should track its product references via a foreign key relationship.

Troubles with Bidirectional One-To-One JPA

I'm coding a CRUD JPA web application. My goal is that a given parent Vehicle can only have a single child Driver, but during runtime this same Driver can instead be assigned to another Vehicle and vice versa. To my understanding, this could be accomplished via an OneToOne relationship.
I've tried some different approaches, but to no success. I can assign a Vehicle to a Driver just fine, but when I try to update/create a new Vehicle and give him a Driver, via controllers, nothing happens. I can only do it the other way around. I'm assuming this is because Vehicle is the parent and I can only create a new relation by updating a parent.
My question is, is it possible to make these updates bidirectional and how can I achieve that?
I've tried using a shared primary key, using a foreign key, using a join table. The result is always the same and I can't quite grasp why. I have an OneToMany relationship working on this application and it works as I expect it to work. I can update on one side or the other, delete on one side or the other. Both entities have been updated. OneToOne? Parent seems to have all the power.
This is what I'm working with right now:
Driver
#Entity
#Table(name= "drivers")
public class Driver {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(nullable = false)
private String name;
#Column(nullable = false)
private int age;
#OneToOne(mappedBy = "driver")
private Vehicle vehicle;
Vehicle
#Entity
#Table(name= "vehicles")
public class Vehicle {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(nullable = false)
private String make;
#Column(nullable = false)
private String model;
#Column(nullable = false)
private int mileage;
#Column(nullable = false)
private int year;
#Column(nullable = false)
private int fuel;
#OneToOne
#JoinColumn(name = "driver_id")
private Driver driver;
And just for reference, this is the OneToMany relationship I have and that I'm happy with. I'd like my OneToOne to have the same behavior, except I don't need to save a list of entities, only one.
#Entity
#Table(name="stops")
public class Stop {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(nullable = false)
private String name;
#ManyToOne
#JoinColumn(name="route_id")
private Route route;
#Entity
#Table(name="routes")
public class Route {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(nullable = false)
private String name;
#OneToMany
#JoinColumn(name = "route_id")
private List<Stop> stops = new ArrayList<>();
Any tips would be appreciated, thank you for your time.

JPA repository findBy foreign key for ManyToMany relationship

I have the following relationship in the data base
Database Diagram
And these are the entities
Apartment.java
#Entity
#Table(name = "apartment")
#Data
public class Apartment {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_apartment")
private long id;
#ManyToMany
#JoinTable(
name = "apartment_facility",
joinColumns = #JoinColumn(name = "id_apartment"),
inverseJoinColumns = #JoinColumn(name = "id_facility"))
#Column(name = "city")
private String city;
#Column(name = "country")
private String country;
}
Facility.java
public class Facility {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_facility")
private long id;
#Column(name = "name")
private String name;
}
My question is how can I create a findBy method in JpaRepository in order to find all Apartments having the required facilities
I'm thinking of the result of this request:
api/apartments/findByFacilities?facilities=gym,pool,parking
I have tried to do a query but couldn't quite get it. Also tried using Jpa as following
List<Apartment> findByFacilities(#RequestParam("facilities") List<String> facilities);
But I'm getting the following error. Is there a walkaround?
Failed to convert from type [java.lang.String] to type [java.lang.Long]
In your first code block List <Facility> facilities = new ArrayList<>(); I guess you forgot to add the code line.
When I look at your link below, I understand that you want to search by the name of the facility.
api/apartments/findByFacilities?facilities=gym,pool,parking
For this, your code in Repository should be as follows:
List<Apartment> findDistinctByFacilitiesNameIn(List<String> facilities);
If we don't add distinct supported keyword here, each record repeats as many as the facilities it contains.
If you want to search differently like, not like, etc., See the supported keywords inside method names table here: Query Creation document.

Spring: Persisting a list of attributes which has list of other attributes in itself

I am trying to make webservice for food order management . I have a Entities Product and Restaurant and I am struggling to make Order Entity .
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#ManyToOne
#JoinColumn(name = "restaurant_id", referencedColumnName = "id", insertable=false, updatable=false)
#JsonBackReference
private Restaurant restaurant;
private int restaurant_id;
private String name;
private float price;
}
#Entity
public class Restaurant {
#Id
#GeneratedValue
private int id;
#NotNull
private String name;
private String city;
private String phone;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "restaurant", cascade = CascadeType.ALL)
#JsonManagedReference
private List<Product> menu;
}
I want the Order entity to have a List. If i keep an attribute OrderId in Product , to Join tables Product and Order, will that be a good idea? Is there any better way to do it?
PS: I don't want to keep order Id with Product because i think Product should not be aware of it
Yes, that's a fine idea.
You can use List in Order entity and join them by having id of order in product.
it's kinda hard to tell what you really want, but this site (under headline relationships) has description of best practices for likely to all of your use cases!
https://vladmihalcea.com/tutorials/hibernate/
Cheers!

#ManyToMany with extra column - how to load via Spring Data?

I have many to many relation between User and Event. I need to have extra column in relational table. I did id:
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#OneToMany(mappedBy="user")
private Set<EventUser> eventUsers = new HashSet<>();
//
}
#Entity
public class Event {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private long id;
#OneToMany(mappedBy="event")
private Set<EventUser> eventUsers = new HashSet<>();
//
}
#Entity
#Table(name = "Event_User")
public class EventUser {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private long id;
private String reaction;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "user_id")
private User user;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "event_id")
private Event event;
//
}
But now... I don't know how to load all events where user has concrete email. Before it I used method:
findByUsersEmail(String email);
Now I can't do this, because Event doesn't have Set users field.
Any ideas ?
What you need here is property-expressions.
Just a quick idea to start:
findByEventUsers_UserEmail(String email);
Note: Dont forget that creating queries by method names is a very limited approach and only used by trivial cases. In any other case, don't be afraid of using the #Query annotation on the method or write JPQL/Criteria API manually.

Resources