Like Button Implementation in Spring Boot - spring

In my application users can post articles. And other users can like these articles.
Article class :
#Entity
public class Article {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "article_id")
private int id;
#Column(name = "article_title")
private String articleTitle;
#OneToMany(mappedBy = "event")
private List<PeopleWhoLiked> peopleWhoLiked;
}
#Entity
public class PeopleWhoLiked {
#EmbeddedId
private PeopleWhoLiked id;
#ManyToOne #MapsId("articleId")
private Article article;
#ManyToOne #MapsId("userId")
private User user;
}
And there is category entity.Every article has one category.
public class Category {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "category_id")
private int id;
#NotEmpty
#Column(name = "categoryName")
private String categoryName;
#OneToMany(mappedBy = "article")
private List<Article> articleList;
}
My Like Table
Article_id User_id
x x
These are both foreign keys to related tables.
With
category.getArticleList(); function i can show articles to users.They can like articles.But the thing is the system doesn't know that if the article was liked by user already. So always like button is active.
Querying (select statement for every article on Like table) is looks like has huge time complexity and overload to the system.) Even if i do how can i post this into thymeleaf th:each statement with only Article object.
I think querying 10 article's like per time with one select statement sounds good .But again how can i pass this to thymeleaf with Article object.

Your problem with performance is caused by additional request for every row.
For 1 select returning 100 rows you make additionals 100 select to database.
If you need display complicated result build view and than map result of view to your #Entity class, which will used only for presentation purpose.

Related

How to generate an entity from another entity JPA - Spring boot

I have a spring boot JPA project with an entity called Customers and another one CustomerReports
#Entity
public class Customers {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private int id;
private String Name;
#JsonIgnore
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "customer_id", referencedColumnName = "id")
private Reports reports;
//getter and setters..etc
}
#Entity
public class CustomerReports {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private int id;
private BigDecimal monthlyPayment;
//done
#JsonIgnore
#OneToOne(mappedBy = "reports")
private Customers customers;
//constructors, getters...etc.
}
I want whenever I insert a Customer, a report to also be generated for that customer. The column "monthlyPayment" in reports is also generated through a reference from another table so I don't want to insert those columns manually if that makes sense.
Is there a way to do that? I'm not sure what to google so it would be great if anyone can give me an idea
If I understand your question properly, you can derive CustomerReports entity based on Customers via simple java utility method & then call save if you are using jparepository :
CustomerReports customerReports=reportUtil(customerEntity);
jpaRepository.save(customerEntity);
jpaRepository.save(customerReports);
...
private CustomerReports reportUtil(Customers customerEntity){
/*Derive values for CustomerReports based on Customers & return*/
}
Or if you don't want to do by this way then check if your underlying database support triggers which you can use for inserting data into CustomerReports while doing insert to Customers

Spring Boot JPA - OneToMany relationship and database structure

I wonder what database structure would be the best option in my case:
I have entity Questionnaire:
#Table(name = "questionnaire")
public class Questionnaire extends BaseEntity {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#OneToMany(mappedBy = "fieldStatus")
private List<QuestionnaireField > fieldStatusList;
}
#Table(name = "questionnaire_field")
public class QuestionnaireField extends BaseEntity {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "questionnaire_id")
private Long questionnaireId;
#Column(name = "field_id")
private Long fieldId; //this is id related to the other table Field
#Column(name = "completed")
private boolean completed; //because I need some additional informations like completed I think I can't use ManyToMany between Questionnaire and Field
#ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
#JoinColumn(name = "questionnaire_id")
private Questionnaire questionnaire;
As you see each Questionnaire can have multiple QuestionnaireFields, BUT each QuestionnaireField is of type Field (hence I added private Long fieldId). Table Field can have 10.000 different fields.
Summary:
one questionnaire can have e.g. 10 Fields, the second one 20 another Fields etc. To store fields related to some particular Questionnaire I created QuestionnaireField table with 2 columns: private Long questionnaireId; and private Long fieldId; . The question is if it is a good approach? That are plain columns not related to any Foreign Key... I try to find the best solution to save Questionnaire with related QuestionnaireFields that are a subset of a big Field table...

How to make sure country is not added twice in mysql database in hibernate using spring mvc one to many relationship?

I have two entity first one is Student and the other one is an address. It is one too many relations ie one address can have many students. Now I have is a registration page. When I first register a student say with country name united states, it is saved in database giving primary id as 1 to united states and correspondingly gives correct id in student's database. But when I again try to register the next student with different information but the same country in my case united states it gives me a new primary key for the same country. But as this one is, one to many relationships I am thinking if there is anything in hibernate that maps to the same id in address database, therefore, I will only have one value of the united states in the address database. I need to have only a single entry of the united states a database. What is the appropraite way of doing need? Thank you
This one is Address table
#Entity
#Table(name = "tbl_address")
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "address_id")
private int addressId;
private String country;
#OneToMany(targetEntity = Student.class, mappedBy = "address")
private List<Student> student;
This one is Student table
#Entity
#Table(name = "tbl_student")
public class Student {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "student_id")
private int studentId;
#Column(name = "first_Name")
private String firstName;
#Column(name = "second_Name")
private String secondName;
private String email;
#Column(name = "mobile_no")
private float mobileNo;
#DateTimeFormat(pattern = "yyyy-MM-dd")
#Temporal(TemporalType.DATE)
private Date dob;
private String gender;
#ManyToOne(cascade = {CascadeType.MERGE , CascadeType.ALL} )
#JoinColumn(name = "address_id")
private Address address;
}
This one is just the implementation in StudentRepositoryImpl class
#Override
public void saveUserInfo(Student user) {
Session session = HibernateUtil.getSession(sessionFactory);
session.save(user);
}
#Override
public void saveAddressInfo(Address address) {
// TODO Auto-generated method stub
Session session = HibernateUtil.getSession(sessionFactory);
session.save(address);
}
First option. On UI you should have a list of available countries (so I expect you already have populated country table in database). So UI will display to users available country names, but on backend side you will operate with countryId.
Second option. In case on UI you want users insert any string as country name, and if you want to register country on any new provided country name. For that you need to have unique index in country table on country name (it's up to you to decide whether it will be case insensitive or not).
Before saving student entity, you should fetch available country by it's name. if such one exist - use countryId with saving studend. if not exist - create a new country entity, and use generated countryId in studend entity.
Second option is risky in that way users could provide any values for country names, and probably with typo, so the first option is preferable.
Have a separate table for Country (That would be called master data). Then the Address entity would be something like this:
#Entity
#Table(name = "tbl_address")
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "address_id")
private int addressId;
#ManyToOne
private Country country;
#OneToMany(targetEntity = Student.class, mappedBy = "address")
private List<Student> student;
You can get the list of students doing a join query with Country and Address tables.
Hope this is helpful

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!

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

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.

Resources