I'm new in Spring Data. I know that I can do it by #Query but I would like too learn more about how to write method names for specific purpose.
This is my Entity:
#Entity
#Table(name = "MEMBER_RECENT_CONTENT")
public class MemberRecentContent {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "ID", unique = true, nullable = false)
private Long id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "MEMBER_ID", nullable = false)
private NCDMMember member;
#Column(name = "PRODUCT_ID", nullable = false)
private Long productId;
#Column(name = "VIEW_DATE", nullable = false)
private Date viewDate;
}
In my repository I have these two methods:
List<MemberRecentContent> findByMember_Id(Long memberId);
List<MemberRecentContent> findFirst10ByOrderByViewDateDesc();
Now I need to combine these two methods but I don't have any idea how to do this. I need to find 10 last record for specific MemberId. I have searched a lot but I couldn't find anything useful.
Maybe, you can define as below:
List<MemberRecentContent> findFirst10ByMemberId(Long memberId, Sort sort);
and then, you can use:
Sort sort = new Sort(Sort.Direction.DESC, "viewDate")
myRepository.findFirst10ByMemberId(memberId, sort)
Related
I am using Spring, JPA, Java17, MySQL.
IDE: IntelliJ IDEA 2022.2.4
JDK: Amazon Coretto 17.0.6
I am getting an error "Expected 0 arguments but found 3". (image)
Here is my Article entity class code and I am using Lombok to remove boilerplate code. For some reason RequiredArgsConstructor annotation cannot be well managed in test class and I need to create actual constructor to be able to work on it.
#Entity
#Getter
#Setter
#RequiredArgsConstructor
#Table(name = "article", schema = "chitchat")
public class Article {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "title", nullable = false, length = 150)
private String title;
#OneToOne
#JoinColumn(name = "category_id")
private Category category;
#Column(name = "comment_count", nullable = false)
private int commentCount;
#Column(name = "view_count", nullable = false)
private int viewCount;
#ToString.Exclude
#OneToMany(mappedBy = "article", orphanRemoval = true)
private Set<Tag> tags = new LinkedHashSet<>();
#Column(name = "modification_date")
private LocalDateTime modificationDate;
#Column(name = "creation_date", nullable = false)
private LocalDateTime creationDate;
#Column(name = "content", nullable = false, length = 50000)
private String content;
#OneToOne(optional = false, orphanRemoval = true)
#JoinColumn(name = "author_id", nullable = false)
private User author;
#Column(name = "published", nullable = false)
private Boolean published = false;
#OneToMany(mappedBy = "article")
private Set<Comment> comments = new LinkedHashSet<>();
}
I tried using AllArgsConstructor and creating constructor by hand (works fine).
As docs of #RequiredArgsConstructor suggests:
Generates a constructor with required arguments. Required arguments
are final fields and fields with constraints such as #NonNull.
So, your class does not have fields that match those criteria
Whereas #AllArgsConstructor :
Generates an all-args constructor. An all-args constructor requires
one argument for every field in the class.
So, everything works as expected.
I have an application where users can enter dates which are saved to a database. The problem is that the dates are saved in a random order.
If I enter three dates:
2023-01-01
2023-02-01
2023-03-01
They will appear in the database like this:
2023-01-01
2023-03-01
2023-02-01
Of course I do not want this to happen, so I started looking up how to sort SQL tables in Java, since that is the language that handles the backend for my application. I read about OrderBy and SortNatural. I tried to implement both without success.
This is my Java file:
#Getter
#Setter
#Entity
#Table(name = "regulated_unit_expense")
public class RegulatedUnitExpense {
#Id
#GeneratedValue(generator = "UUID")
#GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
#Column(name = "id")
private UUID id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "regulation_event_id", referencedColumnName = "id")
private RegulationEvent regulationEvent;
#Column(name = "regulation_takes_effect_date")
private LocalDate regulationTakesEffectDate;
#Column(name = "regulation_type")
#Enumerated(EnumType.STRING)
private RegulationType regulationType;
#Column(name = "regulation_value")
private BigDecimal regulationValue;
#Column(name = "creation_date_time")
private OffsetDateTime creationDateTime;
}
I wanted to sort by date, so I tried:
#Column(name = "regulation_takes_effect_date")
private LocalDate regulationTakesEffectDate;
#SortNatural
I also tried to do this with the ID, but nothing changes.
I then tried to use orderBy:
#Column(name = "regulation_takes_effect_date")
private LocalDate regulationTakesEffectDate;
#OrderBy("regulation_takes_effect_date ASC")
That didn't work either.
What am I missing?
I want to use check constraint to verify if there are more students in the subject more than vacancies. These are the entities:
SubjectOffer
#Entity
#SequenceGenerator(name = "SUBJECT_OFFER_SEQ", sequenceName = "SUBJECT_OFFER_SEQ")
#Table(name = "SUBJECT_OFFER", uniqueConstraints = {
#UniqueConstraint(name = "UQ_SUBJECT_OFFER_COURSE_SUBJECT_SEMESTER_CLASS", columnNames = {"COURSE_ID", "SUBJECT_ID", "SEMESTER", "CLASS_NUMBER"})})
#Check(constraints = "COUNT(STUDENT_SUBJECT_ID) <= VACANCIES")
public class SubjectOffer {
#Id
#GeneratedValue(generator = "SUBJECT_OFFER_SEQ")
#Column(name = "SUBJECT_OFFER_ID", nullable = false)
private Long id;
#OneToMany(fetch = FetchType.LAZY, orphanRemoval = true, cascade = CascadeType.ALL)
#JoinColumn(name = "STUDENT_SUBJECT_ID")
private Set<StudentSubject> studentSubjects = new HashSet<>();
//other attributes
#Column(name = "VACANCIES", nullable = false)
private int vacancies;
}
StudentSubject
#Entity
#Table(name = "STUDENT_SUBJECT")
public class StudentSubject {
#EmbeddedId
private StudentSubjectId id = new StudentSubjectId();
#MapsId("studentId")
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "STUDENT_ID", nullable = false)
private Student student;
#MapsId("subjectOfferId")
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "SUBJECT_OFFER_ID", nullable = false)
private SubjectOffer subjectOffer;
#Column(name = "SEMESTER", nullable = false)
private int semester;
#Column(name = "GRADE")
private BigDecimal grade;
}
I also tried column definition in Set #JoinColumn but it didn't work
SQL check constraints only work on a single table. What you want is a so called SQL assertion constraint, but no database implements that. The best you can do is to pre-create rows for the amount of vacancies and just assign students to these rows without ever creating more rows. This way, you can make sure that you only assign as many students as there are vacancies, given that you use optimistic/pessimistic locking when assigning a student.
I have the following Hibernate entity:
#Entity
#Table(name = "jobs")
public class Job {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "jobs_j_id_seq")
#SequenceGenerator(sequenceName = "jobs_j_id_seq", name = "jobs_j_id_seq", allocationSize = 1)
#Column(name = "j_id")
private Long id;
#Column(name = "j_description", length = 300, nullable = false)
private String description;
#Column(name = "j_category", length = 50, nullable = false)
#Enumerated(EnumType.STRING)
private JobCategory category;
#Column(name = "j_job_provided", length = 50, nullable = false)
private String jobProvided;
#ManyToOne(fetch = FetchType.EAGER, optional = false, cascade = CascadeType.ALL)
#JoinColumn(name = "j_provider_id")
private User provider;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "job")
private Set<Review> reviews;
#Transient
private Long averageRating;
.
.
.
}
What is the correct way of computing the value of the averageRating variable? I've read about #Formula, but I understand this only works the first time the entity is fetched. Meaning that if a new review is added to the Job instance, JPA will update the job but the #Formula will not run again, leading to my value not being recomputed.
Is there a way of having a dynamic #Formula, that will react to changes?
I can always iterate through the reviews and calculate the averageRating, but as we all know this is not the way to go.
If you want to denormalize the schema, you can add an actual column on the table and handle the update with SQL triggers. Then you just annotate the property with #Generated(GenerationTime.ALWAYS) and Hibernate will after every update refresh that property. This might work with #Formula as well, but I would advise against this. What is the point of having this average? IMO you should just always compute it on demand and think about storing it only if that becomes a performance issue.
I have 2 tables project and employee have multiple relationship. Project has many employees, employee can join many projects( many to many). project have one employee whose is team leader, an employee can manager many projects(many to one). So how do I design database, and classes model mapping with database. Some one help me
This is my code
class user
#Entity(name = "USERS")
public class Users {
#Id
#Column(name = "USER_ID", length = 6)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer userId;
#Column(name = "USER_NAME", length = 50, nullable = false)
private String userName;
#Column(name = "PASS_WORD", length = 50, nullable = false)
private String passWord;
#Column(name = "FULL_NAME", length = 50, nullable = false)
private String fullName;
#Column(name = "EMAIL", length = 50, nullable = false)
private String email;
#Column(name = "PHONE", length = 11, nullable = true)
private String phone;
#Column(name = "STATUS", nullable = true)
private Boolean status;
#ManyToMany(fetch = FetchType.LAZY)
#JsonIgnore
#JoinTable(name = "USERPROJECT", joinColumns = { #JoinColumn(name =
"USER_ID") }, inverseJoinColumns = {
#JoinColumn(name = "PROJECT_ID") })
private List<Project> projects;
#OneToMany(mappedBy = "teamlead")
private List<Project> projectOfTeamLead;
//get set.....
}
class project
#Entity(name = "PROJECTS")
public class Project {
#Id
#Column(name = "PROJECT_ID", length = 6)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer projectId;
#Column(name = "PROJECT_NAME", length = 50, nullable=false)
private String projectName;
#Column(name = "USER_CREATE_ID", length = 6, nullable=false)
private Integer userCreateId;
// #Column(name = "TEAM_LEAD_ID", length = 6, nullable=false)
// private Integer teamLeadId;
#Column(name = "TIME_START", nullable=true)
private Date timeStart;
#Column(name = "TIME_END", nullable=true)
private Date timeEnd;
#ManyToMany(mappedBy = "projects")
private List<Users> users;
#ManyToOne
#JoinColumn(name = "TEAM_LEAD_ID")
private Users teamlead;
//get set...
}
I think you need to make your database fit into 3nf (third normal form). You are describing a database that uses two tables, but I think you need three at least, that way you can describe what employees are on what project. A "team" table that uses the PK's from the other two tables should be used. Conventionally, you would name it something like "ProjectEmployees" as it is comprised of the PK's from the "Projects" table and the "Employees" table respectively. I hope that answers your question. If you don't understand what I'm talking about, I highly recommend you watch this.