I want the Employee object to only display the id property when adding a CV. When I put #JsonIgnore on the employee object in the CV, the id doesn't come either. How can I hide property that I do not want to appear in employee class (password, national identity) on the CV class?
Cv Class :
#Entity
#Table(name = "cvs")
#Data
#AllArgsConstructor
#NoArgsConstructor
public class CV {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#OneToOne
#JoinColumn(name = "employee_id")
private Employee employee;
#OneToMany(mappedBy = "cv", cascade = CascadeType.ALL, orphanRemoval = true)
List<Education> educations;
#OneToMany(mappedBy = "cv", cascade = CascadeType.ALL, orphanRemoval = true)
List<Work> works;
#OneToMany(mappedBy = "cv", cascade = CascadeType.ALL, orphanRemoval = true)
List<Languege> langueges;
#OneToMany(mappedBy = "cv", cascade = CascadeType.ALL, orphanRemoval = true)
List<Technology> technologies;
#Column(name = "github")
private String github;
#Column(name = "linkedin")
private String linkedin;
#NotNull
#NotBlank
#Column(name = "cover_letter")
private String coverLetter;
#Column(name = "photo")
private String photo;
}
Employee Class :
#Data
#AllArgsConstructor
#NoArgsConstructor
#Table(name = "employees")
#Entity
#PrimaryKeyJoinColumn(name = "user_id", referencedColumnName = "id")
public class Employee extends User {
#NotNull
#NotBlank
#Column(name = "first_name", length = 50)
private String firstName;
#NotNull
#NotBlank
#Column(name = "last_name", length = 50)
private String lastName;
#NotNull
#NotBlank
#Column(name = "national_identity", length = 11)
private String nationalIdentity;
#NotNull
#Column(name = "year_of_birth")
private int yearOfBirth;
#JsonIgnore
#OneToOne(mappedBy = "employee")
private CV cv;
}
I read data this format;
{
"id": 0,
"employee": {
"id": 0, //visible
"email": "string", //not visible
"password": "string", //not visible
"firstName": "string",
"lastName": "string",
"nationalIdentity": "string", //not visible
"yearOfBirth": 0 //not visible
},
"educations": [
{
"id": 0,
"schoolName": "string",
"department": "string",
"startingDate": "2022-02-11",
"graduationDate": "2022-02-11"
}
],
"works": [
{
"id": 0,
"workplace": "string",
"job": {
"id": 0,
"jobName": "string"
},
"startingDate": "2022-02-11",
"endDate": "2022-02-11"
}
],
"langueges": [
{
"id": 0,
"languege": "string",
"level": 0
}
],
"technologies": [
{
"id": 0,
"technology": "string"
}
],
"github": "string",
"linkedin": "string",
"coverLetter": "string",
"photo": "string"
}
You can use a custom serializer that you would use on your CV employee field : #JsonSerialize(using = CustomEmployeeSerializer.class)
public class CustomEmployeeSerializer extends SerializerBase<Employee> {
public CustomEmployeeSerializer() {
super(Employee.class, true);
}
#Override
public void serialize(Employee employee, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
jgen.writeString(employee.getId());
}
Related
I have created a many to many relationship. It is returning the data correctly. However, I noticed that if the data exist in canUse section of the json and has been called before by another Player, it does not print the data again only the new values are printed.
JOSN
[
{
"id": 12,
"firstname": "asdfghjkl ",
"surname": "asda",
"canUse": [
{
"id": 0,
"techniqueName": "JAVA"
},
{
"id": 1,
"techniqueName": "PHP"
},
{
"id": 2,
"techniqueName": "PYTHON"
}
]
},
{
"id": 49,
"firstname": "asc",
"surname": "as",
"canUse": []
},
{
"id": 90,
"firstname": "LOL",
"surname": "LOL",
"canUse": []
}*,
{
"id": 91,
"firstname": "Kareem",
"surname": "LOL",
"canUse": [
1,
2,
{
"id": 3,
"techniqueName": "HASKELL"
}
]
},*
{
"id": 92,
"firstname": "Omar",
"surname": "LOL",
"canUse": []
}
]
Player entity
#Entity
#Table(name = "players")
#EntityListeners(AuditingEntityListener.class)
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class Players {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="player_id")
private int id;
private String firstname;
private String surname;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(
name = "able_to_use",
joinColumns = {#JoinColumn(name = "player_id", referencedColumnName = "player_id")},
inverseJoinColumns = {#JoinColumn(name = "technique_id", referencedColumnName = "id")}
)
private List<Technique> canUse;
//Getters and Setters
Technique entity
#Entity
#Table(name = "technique")
#EntityListeners(AuditingEntityListener.class)
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class Technique {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(name = "technique_name")
private String techniqueName;
#JsonIgnore
#ManyToMany(mappedBy = "canUse", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Players> ableToUse;
//Getters and Setters
Thank you in advance, the problem is occurring for player with ID 91. this player should also print PHP and PYTHON but only the ID is printed.
I need return this Json to my project:
{
"data": {
"id": 1,
"username": "renato",
"name": "Renato",
"email": "asdasd#outlook.com",
"roles": [
{
"id": 1,
"name": "ROLE_USER",
"accessList": [
{
"id_access": 1,
"id_role": {
"id_role": 1,
"name": "ROLE_USER",
"authority": "ROLE_USER"
},
"id_program": {
"id_program": 1,
"code_program": "TEST",
"name": "test"
},
"id_view": {
"id_view": 1,
"code_view": "TEST",
"name": "test"
},
"menuYesNo": true,
"accessYesNo": true,
"saveYesNo": true,
"editYesNo": true,
"deleteYesNo": true
}
]
}
]
}
}
But it return this:
{
"data": {
"id": 1,
"username": "renato",
"name": "Renato",
"email": "asdasd#outlook.com",
"roles": [
{
"id": 1,
"name": "ROLE_USER",
"accessList": [
{
"id_access": 1,
"id_role": {
"id_role": 1,
"name": "ROLE_USER",
"authority": "ROLE_USER"
},
"id_program": {},
"id_view": {},
"menuYesNo": true,
"accessYesNo": true,
"saveYesNo": true,
"editYesNo": true,
"deleteYesNo": true
}
]
}
]
}
}
Only classes AccessModel and RoleModel have bidirectional relationship, exists a relationship unidirectional between ProgramModel and ViewModel with AccessModel.
OBS: I mapped UserModel to UserDTO using ModelMapper. Exists RoleModel inside a UserDTO. RoleModel and AccessModel have an #JsonManagedReference and #JsonBackReference respectively, but ProgramModel and ViewModel not.
#Data
#Entity
#Table(schema = "`SCH`", name = "`USER`")
public class UserModel implements UserDetails {
private static final long serialVersionUID = -2195101536379303067L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(table = "USER", name="`ID_USER`", nullable = true)
private Long id_user;
#Column(table = "USER", name="`USERNAME`", nullable = true, length = 50)
private String username;
#Column(table = "USER", name="`PASSWORD`", nullable = true, length = 255)
private String password;
#Column(table = "USER", name="`NAME`", length = 255)
private String name;
#Column(table = "USER", name="`EMAIL`", length = 255)
private String email;
#Column(table = "USER", name="`DATE_EXPERED`", nullable = true)
private LocalDate dateExpered;
#Column(table = "USER", name="`ACCOUNT_ACTIVE`", nullable = true)
private Boolean accountAtive;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(schema = "`SCH`", name = "`USER_ROLE`" ,
joinColumns = #JoinColumn(
name = "`CD_USER`", referencedColumnName ="`ID_USER`"
),
inverseJoinColumns = #JoinColumn(
name = "`CD_ROLE`", referencedColumnName = "`ID_ROLE`"
))
#JsonBackReference
private Collection<RoleModel> roles;
//METHODS USERDETAILS
}
#Data
#Entity
#Table(schema = "`SCH`", name = "`ROLE`")
public class RoleModel implements GrantedAuthority {
private static final long serialVersionUID = -1320143054659054908L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(table = "ROLE", name = "`ID_ROLE`", nullable = true)
private Long id_role;
#Column(table = "ROLE", name = "`NAME`", nullable = true, length = 255)
private String name;
#JsonBackReference
#OneToMany(cascade = CascadeType.ALL, mappedBy = "id_role", fetch = FetchType.LAZY)
private List<AccessModel> accessList;
}
#Data
#Entity
#Table(schema = "`SCH`", name = "`ACCESS`")
public class AccessModel implements Serializable {
private static final long serialVersionUID = -5590889002302223720L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(table = "ACCESS", name = "`ID_ACCESS`", nullable = true)
private Long id_access;
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "`CD_ROLE`")
#JsonManagedReference
private RoleModel id_role;
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "`CD_PROGRAM`")
private ProgramModel id_program;
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "`CD_VIEW`")
private ViewModel id_view;
#Column(table = "ACCESS", name = "`MENU_YES_NO`", nullable = true)
private Boolean menuYesNo;
#Column(table = "ACCESS", name = "`ACCESS_YES_NO`", nullable = true)
private Boolean accessYesNo;
#Column(table = "ACCESS", name = "`SAVE_YES_NO`", nullable = true)
private Boolean saveYesNo;
#Column(table = "ACCESS", name = "`EDIT_YES_NO`", nullable = true)
private Boolean editYesNo;
#Column(table = "ACCESS", name = "`DELETE_YES_NO`", nullable = true)
private Boolean deleteYesNo;
}
#Entity
#Table(name = "`PROGRAM`", schema = "`SCH`")
public class ProgramModel implements Serializable {
private static final long serialVersionUID = -726159076909575803L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(table = "PROGRAM", name = "`ID_PROGRAM`", nullable = true)
private Long id_program;
#Column(table = "PROGRAM", name = "`CODE_PROGRAM`", nullable = true)
private String code_program;
#Column(table = "PROGRAM", name = "`NAME`", nullable = true)
private String name;
#Column(table = "PROGRAM", name = "`ACTIVE`", nullable = true)
private Boolean active;
}
#Entity
#Table(name = "`VIEW`", schema = "`SCH`")
public class ViewModel implements Serializable {
private static final long serialVersionUID = 3900486010030569933L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(table = "VIEW", name = "`ID_VIEW`", nullable = true)
private Long id_view;
#Column(table = "VIEW", name = "`CODE_VIEW`", nullable = true)
private String code_view;
#Column(table = "VIEW", name = "`NAME`", nullable = true)
private String name;
#Column(table = "VIEW", name = "`ACTIVE`", nullable = true)
private Boolean active;
}
I forgot to put #Data in ProgramModel and ViewModel.
I have two entities. Customer which is mapped in one to many relation with the CustomerDepartment. CustomerDepartment table has a column to store customer Id.
I want to map them in such a way that Customer Object store a list of Customer Department, and the Customer Department stores the id of the customer it belongs to.
The code that is working compels me to send the all the customer details while creating or updating a customer Department.
Is there a way I can only send the id of the customer and it maps itself?
I have tried changing from -
#JsonBackReference
#ManyToOne
#JoinColumn(name = "customer_no", nullable = false)
private Customer customer;
to this -
#JsonBackReference
#ManyToOne(targetEntity = Customer.class)
#JoinColumn(name = "customer_no", nullable = false)
private Integer customer;
which gives me the requestbody I want but it does not work giving the following error -
2019-08-03 04:59:08 ERROR CustomerController:72 - org.springframework.orm.jpa.JpaSystemException: Error accessing field [private java.lang.Integer com.enquero.pulse.entity.Customer.customerNo] by reflection for persistent property [com.enquero.pulse.entity.Customer#customerNo] : 1; nested exception is org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private java.lang.Integer com.enquero.pulse.entity.Customer.customerNo] by reflection for persistent property [com.enquero.pulse.entity.Customer#customerNo] : 1
Working Code:
Customer:-
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder
#DynamicUpdate
#Entity
#Table(name = "customer")
public class Customer extends Auditable<Integer>{
#Id
#Column(name = "customer_no")
private Integer customerNo;
#NotBlank
#Column(name = "customer_name")
private String customerName;
#Column(name = "industry")
private String industry;
#Column(name = "country")
private String country;
#Column(name = "state")
private String state;
#Column(name = "city")
private String city;
#Column(name = "postal_code")
private String postalCode;
#Column(name = "address_line1")
private String addressLine1;
#Column(name = "address_line2")
private String addressLine2;
#Column(name = "address_line3")
private String addressLine3;
#Column(name = "payment_term")
private String paymentTerm;
#Column(name = "customer_segment")
private String customerSegment;
#JsonFormat(pattern="dd-MMM-yyyy")
#Column(name = "engagement_start_on")
private Date engagementStartOn;
#JsonManagedReference
#OneToMany(fetch = FetchType.LAZY, mappedBy = "customer")
private List<CustomerDepartment> customerDepartments;
}
CustomerDepartment:-
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder
#DynamicUpdate
#Entity
#Table(name = "customer_department")
public class CustomerDepartment extends Auditable<Integer>{
#Id
#Column(name = "dept_id", updatable = false, nullable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer deptId;
#Column(name = "dept_name")
private String deptName;
#Column(name = "primary_contact")
private String primaryContact;
#JsonBackReference
#ManyToOne
#JoinColumn(name = "customer_no", nullable = false)
private Customer customer;
}
Current RequestBody:-
{
"createdBy": 0,
"creationDate": "2019-08-02T23:05:33.993Z",
"customer": {
"addressLine1": "string",
"addressLine2": "string",
"addressLine3": "string",
"city": "string",
"country": "string",
"createdBy": 0,
"creationDate": "2019-08-02T23:05:33.993Z",
"customerDepartments": [
null
],
"customerName": "string",
"customerNo": 0,
"customerSegment": "string",
"engagementStartOn": "string",
"industry": "string",
"lastUpdateDate": "2019-08-02T23:05:33.993Z",
"lastUpdatedBy": 0,
"paymentTerm": "string",
"postalCode": "string",
"state": "string"
},
"deptId": 0,
"deptName": "string",
"lastUpdateDate": "2019-08-02T23:05:33.994Z",
"lastUpdatedBy": 0,
"primaryContact": "string"
}
expected requestbody:-
{
"createdBy": 0,
"creationDate": "2019-08-02T23:05:33.993Z",
"customer": 1, //id instead of json
"deptId": 0,
"deptName": "string",
"lastUpdateDate": "2019-08-02T23:05:33.994Z",
"lastUpdatedBy": 0,
"primaryContact": "string"
}
Have you considered a unidirectional #OneToMany: https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#associations?
For example on CustomerDeparment change
#JsonBackReference
#ManyToOne
#JoinColumn(name = "customer_no", nullable = false)
private Customer customer;
}
to
#JsonBackReference
#ManyToOne
#Column(name = "customer_no")
private int customer;
...and on Customer change
#JsonManagedReference
#OneToMany(fetch = FetchType.LAZY, mappedBy = "customer")
private List<CustomerDepartment> customerDepartments;
}
to
#JsonManagedReference
#OneToMany(cascade = CascadeType.ALL)
private List<CustomerDepartment> customerDepartments;
}
As a bit of an aside, I honestly find Hibernate relationships to sometimes be more a hindrance than a help. As an alternative, you may wish to consider dropping the explicit relationship properties, using "regular" columns (#Column(name="customer_no") private int customer') and just writing queries in your repo classes (ex. findByCustomerNo(int customNumber)) to meet your requirements.
I'm testing my app via Swagger and when trying to post an object, which contains a list of other objects, I get an error java.lang.StackOverflowError. Basically, I'm trying to write an invoice, represented as JSON in Swagger form, and while filling in the data for my invoice I've noticed that invoice item contains the duplicated fields for invoice.
{
"date": "2017-08-27",
"counterparty": {
"address": {
"houseNumber": "string",
"streetName": "string",
"townName": "string",
"zipCode": "string"
},
"bankName": "string",
"bankNumber": "string",
"companyName": "string",
"nip": "string",
"phoneNumber": "string"
},
"invoiceItems": [
{
"amount": 0,
"description": "string",
"id": 0,
"invoice": { //SHOULD NOT BE HERE
"id": 0,
"date": "2017-09-07",
"counterparty": {
"address": {
"houseNumber": "string",
"streetName": "string",
"townName": "string",
"zipCode": "string"
},
"bankName": "string",
"bankNumber": "string",
"companyName": "string",
"nip": "string",
"phoneNumber": "string"
},
"invoiceItems": [
{}
]
},
"numberOfItems": 0,
"vat": "VAT_23",
"vatAmount": 0
}
]
}
#Entity
#Table(name = "invoices")
public class Invoice implements Comparable<Invoice> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "invoice_id")
private int id;
#Column(name = "date")
private LocalDate date = LocalDate.now();
#OneToOne(mappedBy = "invoice", cascade = {CascadeType.DETACH, CascadeType.MERGE,
CascadeType.PERSIST, CascadeType.REFRESH})
private Counterparty counterparty;
#OneToMany(mappedBy = "invoice", cascade = {CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.DETACH, CascadeType.REFRESH})
private List<InvoiceItem> invoiceItems = new ArrayList<>();
#Entity
#Table(name = "items")
public class InvoiceItem {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "item_id")
private int id;
private String description;
private int numberOfItems;
private BigDecimal amount;
private BigDecimal vatAmount;
#JoinColumn(name = "vat_code")
#Enumerated(EnumType.ORDINAL)
private Vat vat;
#ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
CascadeType.REFRESH})
#JoinColumn(name = "invoice_id")
private Invoice invoice;
I have the very same mapping with Counterparty, but it doesn't show me invoice data in JSON:
#Id
private String nip;
private String companyName;
private String phoneNumber;
private String bankName;
private String bankNumber;
#OneToOne(fetch = FetchType.LAZY, mappedBy = "counterparty", cascade = CascadeType.ALL)
private Address address;
#ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
CascadeType.REFRESH})
#JoinColumn(name = "invoice_id")
private Invoice invoice;
Maybe there are some issues with my annotations that invoice is being called recursively?
You should mark your Invoice property on InvoiceItems with the #JsonIgnore annotation which means it won't be serialized into JSON when the InvoiceItems is serialized which should prevent your infinitely recursive JSON issue:
#Entity
#Table(name = "items")
public class InvoiceItem {
...
#ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
CascadeType.REFRESH})
#JoinColumn(name = "invoice_id")
#JsonIgnore
private Invoice invoice;
I have problem getting only ID from objects that are in nested collection in Hibernate.
Here is my code:
public class Company {
private int id;
private Set<Account> owners = new HashSet<Account>();
#Id
public int getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY, targetEntity = Account.class)
#Fetch(org.hibernate.annotations.FetchMode.JOIN)
#JoinTable(
name = "company_accountOwners",
joinColumns = #JoinColumn(name = "company_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "account_id", referencedColumnName = "id")
)
public Set<Account> getOwners() {
return owners;
}
public void setOwners(Set<Account> owners) {
this.owners = owners;
}
Account.class
public class Account {
private String id;
private String name;
private int age;
#Id
#GeneratedValue(generator = "uuid2")
#GenericGenerator(name = "uuid2", strategy = "uuid2")
#Column(columnDefinition = "VARCHAR(36)")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
How only get JSON with all Company.class data and array of owners (Account.class) that has only ID, not all other attributes (name, age)?
I'm in complete dark.
Json i get now:
{
"id": 1,
"owners": [
{
"id": "testID",
"name": "name",
"age": 45
},
{
"id": "testID2",
"name": "name2",
"age": 90
}]
}
I want json like:
{
"id": 1,
"owners": [
{
"id": "testID"
},
{
"id": "testID2"
}]
}