How do I include a related object when serving JSON in Spring? - java

I have this basic controller method:
#GetMapping
List<Employee> all() {
return employeeRepository.findAll();
}
By default, it seems to serve the JSON representation of Employee just fine, except there's one problem: there's no associated Department in the JSON output.
I've googled and googled and googled, and I can't seem to find an answer.
Employee:
#Entity
#Getter
#Setter
public class Employee {
#Id
#GeneratedValue
private Long id;
#NotNull
private String firstName;
#NotNull
private String lastName;
#NotNull
#Column(unique = true)
private String emailAddress;
#ManyToOne
#JsonBackReference
private Department department;
private String phoneNumber;
}
Department
#Entity
#Getter
#Setter
public class Department {
#Id #GeneratedValue private Long id;
private String name;
#OneToMany(mappedBy="department")
#JsonManagedReference
private Set<Employee> employees;
}

Your issue is probably the mix with JPA.
As you are already using Lombok (#Getter, #Setter).
You can do this:
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Employee {
private Long id;
private String firstName;
private String lastName;
private String emailAddress;
private Department department;
private String phoneNumber;
}
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Department {
...
}

Related

What should be the POST JSON body for ManyToMany mapping in JPA?

Say I have two entities User.java and Topic.java
#Entity
#Table(name="T_USR")
#Getter
#Setter
public class User {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="USR_ID", updatable=false, nullable=false)
private Long userId;
#Column(name="FST_NM", nullable=false)
private String firstName;
#Column(name="LST_NM")
private String lastName;
#Column(name="EMAIL")
private String email;
#Column(name="CREATED_DT")
#CreationTimestamp
private Date createdDate;
#ManyToMany
#JoinTable(name="T_USR_TOPIC",
joinColumns= { #JoinColumn(name="USER_ID") },
inverseJoinColumns= { #JoinColumn(name="TOPIC_ID") })
private Set<Topic> topics;
}
#Entity
#Table(name="T_TOPIC")
#Getter
#Setter
public class Topic {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="TOPIC_ID",updatable=false, nullable=false)
private Long topicId;
#Column(name="TOPIC_TAG")
private String topicName;
#Column(name="TOPIC_DS")
private String topicDesc;
#ManyToMany(mappedBy="topics")
private Set<User> users;
}
I already have few entries in T_TOPIC table say
TOPIC_ID | TOPIC_DS | TOPIC_TAG
1 | UI | Angular
2 | Java | Spring
I want to register a new user. But how do form the JSON body?
Should it be like
{
"firstName": "Myname",
"lastName": "LastName",
"email": "example#example.com",
"interests": [1,2]
}
Request Object.
#Getter
#Setter
public class UserRequest {
#NotBlank
#JsonProperty
private String firstName;
#Email
#NotBlank
#JsonProperty
private String lastName;
#NotBlank
#JsonProperty
private String email;
#JsonProperty("interests")
Set<Long> topics;
}
Also, is it good idea to use bidirectional ManyToMany Mapping?

Can I map multiple database tables to a unique Entity using JPA?

I am trying to add multi-language to the description and title fields of one of my Entities but without success. My Entity is like below and my database is MySQL:
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "project")
public class ProjectEntity implements Serializable {
#Id
#Column(name="id")
private Integer id;
#Column(name="team_size")
private Integer teamSize;
#Column(name="description")
private String description;
#Column(name="title")
private String title;
#OneToMany
private List<DetailsEntity> details;
}
I alreaady tried to add a projectDetails entity that contains the description and title, but as I need multilanguage, the Project will now have a list of ProjectDetails in my backend, what I don't need.
Here is what the projectDetails could looks like:
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "project_details")
public class ProjectDetails implements Serializable {
#Id
#Column(name="id")
private Integer id;
#Column(name="title")
private String title;
#Column(name="description")
private String description;
#Column(name="language")
private String language;
#Column(name="project_id")
private Integer projectId;
}
I would like to be able to do something with the JPA repository requests, like this:
#Repository
public interface ProjectEntityRepository extends JpaRepository<ProjectEntity, Integer> {
#Query("select p from ProjectEntity p left outer join ProjectDetails d on p.id=d.project_id and d.language=:language")
List<ProjectEntity> findAllForLanguage(String language);
}
Any idea on how to change part of this to return the Project entity with values of only 1 ProjectDetails?
Thank you

Multiply ID mapping throw BaseEntity

I'm mapping classes via Hibernate and I need to map multiple ID for Relationship.
All ID's extend from BaseEntity. How can I implement multiple ID mapping for Relationship which contains Foreign Key for User in DataBase ?
Basicly fields userIdOne and userIdTwo in Relationship has to contain user's id which send request.
User extend own ID from BaseEntity.
Each time I run it - get en error:
This class [class com.mylov.springsocialnetwork.model.Relationship]
does not define an IdClass
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#MappedSuperclass
#EqualsAndHashCode
public class BaseEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
#Builder
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#EqualsAndHashCode(exclude = {"posts"}, callSuper = false)
#Entity
public class User extends BaseEntity {
private String userName;
private String realName;
private String email;
private String phoneNumber;
private LocalDate birthDate;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userPosted")
private Set<Post> posts = new HashSet<>();
private String password;
public User(Long id, String userName, String realName, String email, String phoneNumber, LocalDate birthDate,
Set<Post> posts, String password) {
super(id);
this.userName = userName;
this.realName = realName;
this.email = email;
this.phoneNumber = phoneNumber;
this.birthDate = birthDate;
this.posts = posts;
this.password = password;
}
}
#Builder
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Entity
public class Relationship implements Serializable {
//#Id not working
private Long userIdFrom;
//#Id
private Long userIdTo;
#Enumerated(value = EnumType.STRING)
private RelationshipStatus status;
private LocalDate friendsRequestDate;
}
It appears that you are looking to establish a Relationship between two different users. This would mean that each Relationship is an object/entity of its own and should have its very own #Id (unrelated to user IDs).
The linkage to each User that form part of this Relationship should be mapped as foreign keys instead (probably #ManyToOne and a #JoinColumn).
For example:
#Entity
public class Relationship implements Serializable {
#Id
private Long relationshipId;
#ManyToOne(...)
#ForeignKey(name="FK_USER_ONE") //for generation only, it isn't strictly required
#JoinColumn(name="from")
private Long userIdFrom;
#ManyToOne(...)
#ForeignKey(name="FK_USER_TWO") //for generation only, it isn't strictly required
#JoinColumn(name="to")
private Long userIdTo;
#Enumerated(value = EnumType.STRING)
private RelationshipStatus status;
private LocalDate friendsRequestDate;
}
Edit:
It isn't required to specify the #ForeignKey annotations. They will be used if the database tables are generated automatically (ok for testing, but usually not something you'll want in production) and will create the FOREIGN KEY constraint on the table accordingly, but JPA mapping will work fine without it, because it takes the relationships from your defined model, not from the database itself.

Spring Boot - how to validate nested enteties

So lets say I have User object like this
#Entity
public class User {
#Id
#GeneratedValue
private long id;
private String name;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "address", referencedColumnName = "id")
private Address address;
}
#Entity
public class Address {
#Id
#GeneratedValue
private long id;
private String city;
private String country;
}
Now I don't want to write validation annotations in entities. What I would like to do is validate User in #RestController like this
#RestController
public class InvoiceController {
#RequestMapping(value="/users/add", method = RequestMethod.POST)
public Invoice addInvoice(#Validated #RequestBody ValidUser user) {
... do stuff
}
}
The validation annotations would be in ValidUser being like this.
public class ValidUser extends User {
#NotNull
private String name;
#Valid
private Address address;
}
public class ValidAddress extends Address{
#NotNull
private String city;
#NotNull
private String country;
}
The validation works when I remove the address field from the ValidUser but not when it is there. How can I make address validation also work?

Spring JPA mapping - first steps

I have class User:
#Entity
public class User {
#Id
#GeneratedValue
private Integer id;
private String name;
private String password;
#ManyToMany
#JoinTable
private List<Role> roles;
}
Class Owner inherits from User
#Entity
public class Owner extends User {
private String pesel;
private String adress;
#OneToMany(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
private List<Pet> pets;
}
and Owner had Pet
public class Pet {
#Id
#GeneratedValue
private Integer id;
private String name;
private String weight;
#ManyToOne
private Owner owner;
}
Why when starting the application gets the error:
org.springframework.data.mapping.PropertyReferenceException: No
property user found for type Pet!
--EDIT
First I have version, which was as follows:
now I try to share User instance to a doctor and the owner of the animal
The problem is that I do not know whether I am doing the mapping , and therefore wanted to ask whether it must look like
--edit2
I've simplified the scheme just a bit to better illustrate what happens
--edit3
Currently my Object's was presented:
#Entity
public class Pet {
#Id
#GeneratedValue
private Integer id;
private String name;
private String weight;
}
User
#Entity
public class User {
#Id
#GeneratedValue
private Integer id;
private String name;
private String password;
#ManyToMany
#JoinTable(name="user_roles")
private List<Role> roles;
}
PetOwner
#Entity
public class PetOwner extends User {
private String pesel;
private String adress;
#OneToMany(mappedBy="petOwner")
private List<Pet> pets;
}
I replace
#ManyToOne
private PetOwner petOwner;
for
#ManyToOne
private Owner petOwner;
and it works. Do you have a PetOwner class?
Also provide the log error to get more information about it

Categories