Ignore an Entity fields for a Spring REST call - java

I have two Entity classes "Teacher & Class" where there is a #OneToMany relationship between them. The first one has a rest interface at /teachers/{id} and the second one has a rest interface at /classes/{id}. When a user sends a GET request to the Teacher interface, he should receive all of the Teacher and Class fields. But, when the user sends a GET request to the Class interface, I would like him to receive all of the Class fields and only a part of the Teacher fields "firstName, lastName"
Here are the entities code:
#Entity
#DiscriminatorValue("Th")
public class Teacher{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String firstName;
private String lastName;
private String phone;
#Column(unique = true)
#Email
private String email;
private String password;
#OneToMany(mappedBy = "teacher", fetch = FetchType.EAGER)
private List<Class> classes;
#OneToMany(mappedBy = "teacher", fetch = FetchType.EAGER)
private List<Note> notes;
protected Teacher() {
}
}
#Entity
public class Class {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
#OneToOne()
#JoinColumn(name = "subject_id")
private Subject subject;
#Enumerated(EnumType.STRING)
private Grade grade;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "teacher_id")
private Teacher teacher;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "class_student", joinColumns = { #JoinColumn(name = "class_id", referencedColumnName = "id") }, inverseJoinColumns = { #JoinColumn(name = "student_id", referencedColumnName = "id") })
private List<Student> students;
protected Class() {
}
}
//getters and setters

Your request sounds mutualy exclusive, don't load Teacher object but do load it for it's ID.
You are better off then making the teacher object lazy load and then initialise it once class is loaded.
FYI
#JsonIgnore prevents loading of objects when RESTfull calls are made.

Related

How to make JPA query method about onetomany?

I'm stuck at deal with this problem. I have 'Review Entity', and 'Heart Entitiy'. And I tried to show them homepage and detailpage separately!
Long countHeartByBookReviewId(Long bookReview_id);
i used jpa query method for showing how many heart it gets in details page..
and now i want to show review descending related to heart count in main page!
how can i make the code..?
#Entity
public class BookReview extends Timestamped {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
private Long id;
...
#Column
private String review;
#JoinColumn(name = "member_id", nullable = false)
#ManyToOne(fetch = FetchType.EAGER)
private Member member;
#OneToMany(mappedBy = "bookReview" , cascade = CascadeType.REMOVE)
private List<Comment> comment;
#JsonIgnore
#OneToMany(mappedBy = "bookReview", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Heart> heart;
and the other entitiy is here.
public class Heart {
#GeneratedValue(strategy = GenerationType.AUTO)
#Id
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "bookReview_id")
private BookReview bookReview;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "member_id")
private Member member;
and this is function for get menthod...
public ResponseDto<?> getHome() {
List<BookReview> book_review = book_reviewRepository.findAllByOrderByHeartDesc();
List<HomeResponseDto> book_reviewResponseDtoList = new ArrayList<>();
for (BookReview home : book_review) {
book_reviewResponseDtoList.add(HomeResponseDto.builder()
.id(home.getId())
.username(home.getMember().getUsername())
.thumbnail(home.getThumbnail())
.title(home.getTitle())
.author(home.getAuthor())
.publisher(home.getPublisher())
.review(home.getReview())
.heart(heartRepository.countHeartByBookReviewId(home.getId()))
.createdAt(home.getCreatedAt())
.modifiedAt(home.getModifiedAt())
.build()
);
}
return ResponseDto.success(book_reviewResponseDtoList);
}
please help me ......

How to extend a class in Spring Boot without changing the MySQL schema?

For example, I have the User class, with looks like the next:
#Entity
#Table(name = "users")
public class User{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#NotBlank
#Size(max = 40)
#Column(name = "name")
private String name;
#NotBlank
#Size(max = 15)
#Column(name = "username")
private String username;
#NaturalId
#NotBlank
#Size(max = 40)
#Email
#Column(name = "email")
private String email;
#NotBlank
#Size(max = 100)
#Column(name = "password")
private String password;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "user_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles = new HashSet<>();
//Constructor
//Getters and Setters
And I have the Client class:
#Entity
#Table(name = "cliente")
public class Cliente {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "empresa")
private String empresa;
#Column(name = "telefono")
private Integer telefono;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(unique = true)
private Licencia licencia;
#OneToMany(cascade = {
CascadeType.PERSIST,
CascadeType.REMOVE
} ,fetch = FetchType.EAGER)
#JoinTable(name = "user_cliente",
joinColumns = #JoinColumn(name = "cliente_id"),
inverseJoinColumns = #JoinColumn(name = "user_id"))
private Set<User> users = new HashSet<>();
public Cliente(String empresa, Integer telefono) {
this.empresa = empresa;
this.telefono = telefono;
}
//Constructor
//Getters and Setters
Now, what I want to do is the Client class to extends the User class, so I can add a Client with name, username, email, etc. But I want two separate tables in MySQL, one for the users and its attributes, and other for clients only with the information of client, like the telephone or company. The problem is when I extends the User class in Client class, the MySQL databases updates and create the fields of telephone, company, etc. in the User table. How can I avoid this?
Use #MappedSuperclass:
#MappedSuperclass
public class BaseEntity {
// here you can add common fields for your entities
}
and then extend from it:
#Entity
public class User extends BaseEntity {
// user specific fields goes here
}
and Client:
#Entity
#Table(name = "cliente")
public class Cliente extends BaseEntity {
// client specific fields here
}
For more info read How to inherit properties from a base class entity using #MappedSuperclass with JPA and Hibernate

Hibernate ManyToMany HQL issue

My MySql tables:
db tables
And My Two Entity Classes are
#Entity
public class Tweet {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="tweet_id")
private int tweetId;
private String message;
private Date created;
#ManyToOne(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
#JoinColumn(name="user_id")
private Person person;
...
}
#Entity
public class Person {
#Id
#Column(name = "user_id")
private String userId;
private String password;
private String email;
private String fullName;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "following", joinColumns = { #JoinColumn(name = "user_id") },
inverseJoinColumns = { #JoinColumn(name = "following_id") })
private List<Person> following = new ArrayList<Person>();
...
}
Now I want to display messages of user praveen, and also all the messages mapped to praveen user in the following table. That means praveen user have 2 messages and his following users have 2 messages . Total 4 messages should be displayed. I really don't know how to retrieve this info using any technique in Hibernate. Please help me

Spring boot data rest/jpa #JoinTable insertion

I'm creating a MySQL database as followed :
database design
the Country and Province tables are pre-filled with data. I have the application running and can get stuff no problem, and also the join table person_has_address works when getting.
however, when I insert data using post I want to be able to set the ID of the province, and let spring data jpa just add that number to add_pro_id in the Address table. For example, when I post the following json:
{ "firstName":"bilbo", "lastName":"baggings", "address":{"street":"streetName", "streetNum":3, "zipcode":"1337GG", "city":"TheCity", "province":{"name":"aProvinceName"}} }
jpa should see that aProvinceName exists and grab that id and add that to add_pro_id.
Now it just insert aProvinceName as new value in province and add the new id to add_pro_id.
The person class:
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="per_id")
private int id;
#Column(name="per_name")
private String firstName;
#Column(name="per_surname")
private String lastName;
#Column(name="per_birth_date")
private String birthDate;
#Column(name="per_fax")
private String fax;
#Column(name="per_phone")
private String phone;
#Column(name="per_email")
private String email;
#OneToOne(optional = false, cascade = CascadeType.ALL)
#JoinTable(name="person_has_address", joinColumns = {#JoinColumn(name="pha_per_id", referencedColumnName = "per_id")}, inverseJoinColumns = {#JoinColumn(name="pha_add_id", referencedColumnName = "add_id")})
private Address address;
// getters and setters
This is the person repository:
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
List<Person> findByLastName(#Param("name") String name);
}
This is the address class:
#Entity
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="add_id")
private int id;
#Column(name = "add_street")
private String street;
#Column(name="add_street_num")
private int streetNum;
#Column(name="add_zip")
private String zipcode;
#Column(name="add_city")
private String city;
#JoinColumn(name="add_pro_id", referencedColumnName = "pro_id")
#ManyToOne(optional=false, cascade = CascadeType.ALL)
private Province province;
// getters and setters
Province class:
#Entity
public class Province {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="pro_id")
private int id;
#Column(name="pro_name")
private String name;
#ManyToOne
#JoinColumn(name="pro_cou_id")
private Country country;
// getters and setters
And lastly country class:
#Entity
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="cou_id", insertable = false, updatable = false)
private int id;
#Column(name="cou_name", insertable = false, updatable = false)
private String name;
// getters and setters
I've tried adding insertable = false and updatable = false, but the application then just inserts NULL values in my database. I've also tried working with #primarykeyjoins, but to no success.
if anyone knows how I should tackle this problem I would much appreciate it!
Thanks in advance.

JPA many to many Insert

I have 3 tables. 1 is parent, 1 is student and one is student_parent. This is a many to many relationship between the parent and student. The parentID is from the parent table and the studentID is from the student table. The student_parent table have studentID, parentID and childRelationship. I need to know how to update the childRelationship field using JPA(hibernate).
Note that I'm using Java Spring with the JPA/Hibernate to update my relational database and that there are several other tables but all I wanted to know was to update childRelationship field.
#Entity
#Table(name = "Student")
#Proxy(lazy = false)
public class Student{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "studentID", nullable = false)
private int studentID;
#Column(name="firstName")
private String firstName;
#Column(name="middleName")
private String middleName;
#Column(name="lastName")
private String lastName;
#Column(name="validationID")
private String validationID;
#Column(name="birthDate")
private Date birthDate;
#Column(name="gender")
private char gender;
#Column(name="ethnicity")
private String ethnicity;
#Column(name="photo") // character type has to confirmed
private byte[] photo;
#Column(name="gradeLevel")
private int gradeLevel;
#Column(name="rewardPoints")
private String rewardPoints;
#Column(name="dateCreated")
private Date dateCreated;
#Column(name="schoolID")
private Integer schoolID;
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "addressID")
private Address address;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "userName")
private UserAccount userAccount;
#ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
#JoinTable(name="student_parent",
joinColumns = {#JoinColumn(name = "studentID")},
inverseJoinColumns = {#JoinColumn(name = "parentID")})
private Set<Parent> parents = new HashSet<Parent>();
#ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
#JoinTable(name="student_community",
joinColumns = {#JoinColumn(name = "studentID")},
inverseJoinColumns = {#JoinColumn(name = "communityID")})
private Set<Community> communities = new HashSet<Community>();
//getter and setting
then the parent.
#Entity
#Proxy(lazy = false)
public class Parent {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int parentID;
#Column(name="userName")
private String userName;
#Column(name="firstName")
private String firstName;
#Column(name="middleName")
private String middleName;
#Column(name="lastName")
private String lastName;
#Column(name="validationID")
private String validationID;
#Column(name="maritalStatus")
private String maritalStatus;
#Column(name="noOfChildren")
private int noOfChildren;
#Column(name="birthDate")
private Date birthDate;
#Column(name="gender")
private char gender;
#Column(name="ethnicity")
private String ethnicity;
#Column(name="annualIncome")
private Float annualIncome;
#Column(name="dateCreated")
private Date dateCreated;
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "addressID")
private Address address;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "userName",unique = true, nullable = false, insertable=false, updatable=false)
private UserAccount userAccount;
//getter and setter
You already have an association table, you need to bring it into the entity world as an association class. The primary key of the association class is a composite key made of the student id and the parent id. Don't forget to implement hashcode and equals on the primary key class. With this mapping you can gain access to the attributes of the m:n relationships (i.e. the "childRelationship" column). You'll also need to add getters and setters or go with field access.
/**
* Maps to parent table in database
*/
#Entity
class Parent {
#Id
long id;
#OneToMany(mappedBy="parent")
Set<Relationship> relationships;
}
/**
* Maps to student table in database
*/
#Entity
class Student {
#Id
long id;
#OneToMany(mappedBy="student")
Set<Relationship> relationships;
}
/**
* Encapsulates primary key in relationship table
*/
class RelationshipId {
long studentId;
long parentId;
#Override
public int hashCode() {
return ((Long)(studentId + parentId)).hashCode();
}
#Override
public boolean equals(Object obj) {
return obj != null
&& obj instanceof RelationshipId
&& ((RelationshipId)obj).studentId == studentId
&& ((RelationshipId)obj).parentId == parentId;
}
}
/**
* Maps to relationship table in database
*/
#Entity
#IdClass(RelationshipId.class)
class Relationship {
#Id
#ManyToOne(optional = false)
#JoinColumn(name="parent")
Parent parent;
#Id
#ManyToOne(optional = false)
#JoinColumn(name="student")
Student student;
#Column
String childRelationship;
}

Categories