I have created simple CRUD service. With 4 entities: Customer, Provider, Product, Deal.
Customer and Provider entities has composed id AppId with the following structure:
#Getter
#Setter
#Embeddable
#NoArgsConstructor
public class AppId implements Serializable {
private String app;
private String id;
//...
}
Here is business logic I want:
Providers entity cascades and creates Product entities.
When the customer makes deal with provider I need to create entity Deal, which doesn't cascade any other entities.
It just has fields which refer to provider, customer and product of the deal.
I created some providers and customers.
Then I tried to create deal, but I got fields customer and provider null.
Here are my entities definitions:
Provider:
#Entity
#Getter
#Setter
#ToString
#NoArgsConstructor
#Table(name = "provider")
public class Provider implements Serializable {
#EmbeddedId
#Column(name = "appid")
private AppId appId;
#Column(name = "name")
private String name;
#Column(name = "firstname")
private String firstName;
#Column(name = "lastname")
private String lastName;
#Column(name = "latitude")
private float latitude;
#Column(name = "longitude")
private float longitude;
#Column(name = "work_date")
private Date workDate;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "provider_product"
, joinColumns = {
#JoinColumn(name = "provider_app"),
#JoinColumn(name = "provider_id")
}
, inverseJoinColumns = #JoinColumn(name="product_id"))
private Set<Product> products;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumns({
#JoinColumn(name = "app", referencedColumnName = "app", updatable = false, insertable = false),
#JoinColumn(name = "id", referencedColumnName = "id", updatable = false, insertable = false)
})
private List<Deal> dealList = new ArrayList<>();
}
Customer:
#Entity
#Getter
#Setter
#ToString
#NoArgsConstructor
#Table(name = "customer")
public class Customer implements Serializable {
#EmbeddedId
#Column(name = "appid")
private AppId appId;
#Column(name = "firstname")
private String firstName;
#Column(name = "lastname")
private String lastName;
public Customer(AppId appId, String firstName, String lastName) {
this.appId = appId;
this.firstName = firstName;
this.lastName = lastName;
}
}
Product:
#Entity
#Getter
#Setter
#ToString
#NoArgsConstructor
#Table(name = "product")
public class Product implements Serializable {
#Id
#GeneratedValue
private long id;
#Column(name = "name")
private String name;
#Column(name = "cost")
private long cost;
}
Deal:
#Entity
#Getter
#Setter
#ToString
#NoArgsConstructor
#Table(name = "deal")
public class Deal implements Serializable {
#Id
#GeneratedValue
private long id;
#ManyToOne
#JoinColumns({
#JoinColumn(name = "provider_app", referencedColumnName = "app", insertable = false, updatable = false),
#JoinColumn(name = "provider_id", referencedColumnName = "id", insertable = false, updatable = false)
})
private Provider provider;
#ManyToOne
#JoinColumns({
#JoinColumn(name = "customer_app", insertable = false, updatable = false),
#JoinColumn(name = "customer_id", insertable = false, updatable = false)
})
private Customer customer;
#ManyToMany
#JoinTable(name = "deal_product"
, joinColumns = #JoinColumn(name="deal_id", insertable = false, updatable = false)
, inverseJoinColumns = #JoinColumn(name="product_id", insertable = false, updatable = false))
private Set<Product> product;
// deal is complete when provider entered deal id
#Column(name = "closed")
private boolean closed = false;
}
By removing insertable = false for customer and provider fields in the Deal entity, everything works fine.
{
"id": 5,
"provider": {
"appId": {
"app": "vk",
"id": "123"
},
"name": null,
"firstName": null,
"lastName": null,
"latitude": 0,
"longitude": 0,
"workDate": null,
"products": null,
"dealList": []
},
"customer": {
"appId": {
"app": "vk",
"id": "123"
},
"firstName": null,
"lastName": null
},
"product": [
{
"id": 2,
"name": "Temp",
"cost": 100
}
],
"closed": false
}
I could get the following response.
insertable = false on a field means when you are saving the entity you won't be saving the value for that field and will set the field explicitly somewhere.
insertable = true doesn't mean you will create a new Customer or Provider, that is handled by CascadeType
Related
I was able to get this ManyToOne relationship with a composite pk working for GET requests but I am having issues with saving new entries.
I have a parent entity with an embedded id.
#Embeddable
public class AnnualServiceHistoryPK implements Serializable {
#Column(name = "year", columnDefinition = "int(4)")
Integer year;
#Column(name = "month", columnDefinition = "char(3)")
String month;
#Column(name = "route", columnDefinition = "varchar(32)")
String route;
This is placed in the parent entity:
#Entity(name = "AnnualServiceHistory")
#Table(name = "annual_service_history")
public class AnnualServiceHistory extends Auditable<String> implements Serializable
{
#EmbeddedId
AnnualServiceHistoryPK annualServiceHistoryPK;
... other variables
#OneToMany(mappedBy = "annualServiceHistory", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
List<AnnualServiceHistoryNonMachine> annualServiceHistoryNonMachineList;
I have the child entity which maps the embedded id from the parent and adds and additional local PK.
public class AnnualServiceHistoryNonMachine extends Auditable<String> implements Serializable {
#Id
#MapsId
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "year", referencedColumnName = "year")
#JoinColumn(name = "month", referencedColumnName = "month")
#JoinColumn(name = "route", referencedColumnName = "route")
private AnnualServiceHistory annualServiceHistory;
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "toy_inventory", referencedColumnName = "id")
ToyInventory toyInventory;
... other variables
My issue is, when I save the parent with a list of children for some reason during the cascading processes, when it is generating the child key it is only creating the key from the MapsId parts and complains that the toyInventory key is null. I'm not sure why it loses this ID because prior to performing the repository save the child class has the toyInventory key in the object.
This is the error I am receiving:
"java.sql.SQLIntegrityConstraintViolationException: Column 'toy_inventory' cannot be null"
Solution found. - https://medium.com/#bhagyajayashani/composite-key-handling-using-idclass-annotation-in-spring-boot-java-26f40bbd38a2
Changed from using #embeddedId to using #classId. Then created a separate join object, and created join based off individual variables not the embeddedId.
#Embeddable
public class AnnualServiceHistoryPK implements Serializable {
Integer year;
String month;
String route;
public AnnualServiceHistoryPK() {
}
#Entity(name = "AnnualServiceHistory")
#Table(name = "annual_service_history")
#IdClass(AnnualServiceHistoryPK.class)
public class AnnualServiceHistory extends Auditable<String> implements Serializable {
#Id
#Column(name = "year", columnDefinition = "int(4)")
Integer year;
#Id
#Column(name = "month", columnDefinition = "char(3)")
String month;
#Id
#Column(name = "route", columnDefinition = "varchar(32)")
String route;
... other variables ...
#OneToMany(mappedBy = "annualServiceHistory", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
Set<AnnualServiceHistoryNonMachine> annualServiceHistoryNonMachineList;
#Embeddable
public class AnnualServiceHistoryNonMachinePK implements Serializable {
Integer year;
String month;
String route;
ToyInventory toyInventory;
public AnnualServiceHistoryNonMachinePK() {
}
#Entity(name = "AnnualServiceHistoryNonMachine")
#Table(name = "annual_service_history_non_machine")
#IdClass(AnnualServiceHistoryNonMachinePK.class)
public class AnnualServiceHistoryNonMachine extends Auditable<String> implements Serializable {
#Id
#Column(name = "year", columnDefinition = "int(4)")
Integer year;
#Id
#Column(name = "month", columnDefinition = "char(3)")
String month;
#Id
#Column(name = "route", columnDefinition = "varchar(32)")
String route;
... other variables ...
#ManyToOne
#JoinColumns({
#JoinColumn(name = "year", referencedColumnName = "year", insertable = false, updatable = false),
#JoinColumn(name = "month", referencedColumnName = "month", insertable = false, updatable = false),
#JoinColumn(name = "route", referencedColumnName = "route", insertable = false, updatable = false)
})
#JsonIgnore
private AnnualServiceHistory annualServiceHistory;
i have 3 tables in mySQL, User, Institution and Role
1)one to many relation from user to institution (one user can work at one institution, and one institution can have many users)
2)many to many relation between role and user
the institutions in my database are already inserted and the user can only work in a specific existing institution.
and also the rolesin my database are already inserted and the user can only have an existing role.
i manually added 7 roles to my DB for user and for institution.
i want to add a user and specify his role in the API request but it wont work.
-------user model-------
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="user_Id")
private int userId;
#Column(name="name")
private String name;
#Column(name="lastname")
private String lastname;
#Column(name="email")
private String email;
#Column(name="password")
private String password;
#Column(name="isActive")
private boolean isActive;
#Column(name="lastActive")
private String lastActive;
#Column(name="createdDate")
private String createdDate;
#Column(name="isBlocked")
private boolean isBlocked;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "institution_id", nullable = false)
private Institution institution;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
#JoinTable(name = "user_has_role",
joinColumns = {
#JoinColumn(name = "user_id", referencedColumnName = "user_id",
nullable = false, updatable = true)},
inverseJoinColumns = {
#JoinColumn(name = "role_id", referencedColumnName = "role_id",
nullable = false, updatable = true)})
private Set<Role> roles = new HashSet<>();
}
--------role model------------
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity
#Table(name = "role")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="role_Id")
private int roleId;
#Column(name="name")
private String name;
#Column(name="description")
private String description;
#ManyToMany(mappedBy = "roles", fetch = FetchType.LAZY)
private Set<User> users = new HashSet<>();
}
----------institution model------------
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity
#Table(name = "institution")
public class Institution {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="institution_Id")
private int institutionId;
#Column(name="name")
private String name;
#Column(name="type")
private String type;
#Column(name="location")
private String location;
#OneToMany(mappedBy = "institution", fetch = FetchType.LAZY)
private Set<User> user;
}
--------controller-----------
#PostMapping("/addUser")
public String addUser(#RequestBody User user) {
userrepository.save(user);
return "user saved with name: " + user.getName();
}
--------- my api request---------
{
"name": "user1",
"lastname": "lastname",
"email": "user1#hotmail.com",
"password": "user1123",
"lastActive": "02/01/20",
"createdDate": "06/05/19",
"institution": {
"institutionId": 3
},
"roles": [
{
"role_id": 2
}
],
"active": true,
"blocked": false
}
but this is not working properly its creating a new role with empty fields...
i just need it to add into the user_has_role table the correspondent id for user_id and role_id
please help
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 having a weird problem with Jackson serialization - I have a Role entity have a nested Permission entity which, in turn, contains a nested Metadata entity. When these entities are retrieved from a Spring MVC #RestController as a list, Jackson serializes the Permission collection into a JSON array. The problem is that sometimes the element placed in this array is just the id of the Permission rather than a serialized representation of the object.
Role.class:
#Entity
#Table(name = "t_db_roles")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Role.class)
public class Role implements GrantedAuthority {
private final static Logger log = LoggerFactory.getLogger(Permission.class);
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "auto_id")
private int id;
#Column(name = "role", length = 50)
private String name;
#OneToMany(fetch = FetchType.EAGER)
#JoinTable(name = "t_db_role_permissions",
joinColumns = {#JoinColumn(name = "roleid", referencedColumnName = "auto_id")},
inverseJoinColumns = {#JoinColumn(name = "permid", referencedColumnName = "auto_id")}
)
private Set<Permission> permissions;
// getters and setters omitted
}
Permission.class:
#Entity
#Table(name = "t_db_permissions")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Permission.class)
public class Permission implements GrantedAuthority {
private final static Logger log = LoggerFactory.getLogger(Permission.class);
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "auto_id")
private int id;
#Column(name = "name")
private String name;
#OneToOne(mappedBy = "permission")
private Metadata metadata;
}
Metadata.class
#Entity
#Table(name = "t_report_data")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Metadata.class)
public class Metadata {
#Id
#Column(name = "id", insertable = false, updatable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "file_name")
private String fileName;
#Column(name = "human_name")
private String humanName;
#Column(name = "links_to")
#JsonIgnore
private Integer linksTo;
#Column(name = "is_subreport")
#JsonIgnore
private Boolean isSubreport;
#OneToOne(cascade = javax.persistence.CascadeType.ALL, fetch = FetchType.EAGER, optional = false)
#JoinColumn(name = "permid")
private Permission permission;
}
The controller:
#RestController
public class RoleRestController {
private final static Logger log = LoggerFactory.getLogger(PermissionRestController.class);
private RoleService roleService;
private MetadataService metadataService;
#Autowired
public void setRoleService(RoleService service) {
this.roleService = service;
}
#Autowired
public void setMetadataService(ReportMetadataService service) { this.metadataService = service; }
#RequestMapping(value = "/admin/roles/", method = RequestMethod.GET)
public List<Role> getRoles() {
return roleService.getRoles();
}
}
I'm fairly sure that the problem is in serialization - echoing the List<Role> to the console works as expected, but here is the JSON returned (note the first element of the permissions array is an integer rather than a JSON object):
{
"id": 10,
"name": "ROLE_TESTER",
"permissions": [
14,
{
"id": 7,
"name": "ViewDailySettlementSummaryGL",
"metadata": {
"id": 41,
"fileName": "acct_summary_gl.rptdesign",
"humanName": "Daily Settlement Summary GL",
"permission": 7
},
"authority": "ViewDailySettlementSummaryGL"
},
{
"id": 6,
"name": "ViewDailySettlementSummary",
"metadata": {
"id": 24,
"fileName": "acct_summary_os.rptdesign",
"humanName": "Daily Settlement Summary",
"permission": 6
},
"authority": "ViewDailySettlementSummary"
}
],
"authority": "ROLE_TESTER"
}
I can work around this by handling Role serialization manually, but since the SpringMVC/Jackson serialization works for other classes in the project it seems like there must be a problem in these classes that i'm overlooking. Any ideas?