I am developing a web project using Spring Boot, Spring Data JPA and Spring Data Rest technologies. I am able to setup everything successfully and able to get JSON of a simple POJOs. I have customized two classes to have OneToMany and ManyToOne relationship like this:-
#Entity
#Table(name="t_profile")
public class Profile {
#Id
#column(name="profile_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
#JoinColumn(name = "cat_id", referencedColumnName = "category_id")
#ManyToOne(optional=false)
private Category category;
// getters and setters
}
#Entity
#Table(name="t_category")
public class Category {
#Id
#column(name="category_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
#OneToMany(mappedBy="category")
private List<Profile> profile;
// getters and setters
}
http://localhost:8080/project/profiles
When I am accessing profiles using rest client; I am able to get json format with field of id, name but ManyToOne field is not coming in json, whle debugging in controller, profile list has values of category. But it is not coming in json.
Any thoughts?
you can use #RestResource(exported = false) in you ManyToOne field.
ManyToOne field will comes as a link. That is on accessing category, profile field will be listed under "_links" in JSON body like shown below:
"_links" : {
"profile" : {
"href" : "http://<host>/<baseUrl>/category/<categoryId>/profile"
}
Further to get details of profile for a given category call below api:
http://<host>/<baseUrl>/category/<categoryId>/profile
Related
I have an entity called Order which has a reference to an entity called project like below:
#Entity
#Table(name = "customer_order")
public class Order {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "project_id", nullable = false)
private Project project;
#Column(name = "user_id")
private String userId;
#Column(name = "created_at")
#CreationTimestamp
private Date createdAt;
}
And my repository is as below:
#Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
}
When I call my rest get endpoint to get a list of all orders, in the response, I get a project object inside the main order object with all properties of the 'project' class as well. I dont want this. I need a lean order response object with just the project id that it references. I tried using the below annotation over the 'project' property in the Order class, but it completely got rid of project details.
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
I still need the id of the project that is associated.
How do I do it?
I assume that your endpoint rerturns JSON.
In that case you would have to write your own Serializer.
For Gson this can be achieved by implementing JsonSerializer and register it as a type adapter
For ObjectMapper (Jackson) you would have to extend StdSerializer and add it as a serializer to the ObjectMapper or use the annotation #JsonSerialize(using = ItemSerializer.class) on the model class
How to bind my new object user with an role object in my spring boot application when I receive an request post with a json/application that has all data for the new user?
What is the best approach (inform the role in the json)? If yes, how must be the json concerned the role information?
I will try to explain myself. First, I am sorry, I am not a native English speaker.
I want to create a new object user mapping the json received from a HTTP request post. The problem is that I have an internal object from my model named role. Roles are always either a common or an admin. Then I want to reference an already instantiated role object.
So, I want to know how to indicate the role from my user. You should consider that the model can not be modified because some internal team restriction. I don't know if the correct restful approach is send the role information in the json. How would you do this task?
My code
Class Controller
#RestController
public class UserController {
#RequestMapping(method=RequestMethod.POST, value="/users", produces = "application/json")
public #ResponseBody ResponseEntity<EntityUser> create(#Validated #RequestBody EntityUser user)
{
return new ResponseEntity<>(userService.add(user), HttpStatus.CREATED);
}
}
The Service class
#Service
public class UserService {
public EntityUser add(EntityUser user)
{
if (userRepository.findByName(user.getName()) == null)
return userRepository.save(user);
return null;
}
}
My plain object EntityUser (the json is mapped to it).
#Entity
public class EntityUser {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator="user_sequence")
private long id;
#Column(name = "name")
#NotNull
private String name;
#Column(name = "email", unique = true)
#NotNull
private String email;
#ManyToOne(fetch=FetchType.EAGER)
// #NotNull
private EntityRole role;
...
}
and finally my EntityRole class
#Entity
public class EntityRole {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="role_sequence")
private long id;
#NotNull
private String label;
#NotNull
private String permission;
...
}
I have the problem, I am using Spring Data Rest. So i have some Domain Model like this:
#Entity
public class Sample implements Serializable {
#Id
#GeneratedValue
private Long id;
#Column(name = "name")
private String name;
#Column(name = "is_main")
private Boolean isMain;
#LastModifiedDate
#Column(name = "last_modified")
private Date lastModified;
#ManyToOne
#JoinColumn(nullable = false,name = "user_id")
private User user;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(nullable = false,name="state_id")
private SampleState state;
}
So from client I am sending POST request to http://{server.host}:8080/samples
to create Sample with JSON:
{"name":"sample","user":{"id":1},"state":{"id":1}}
Hoping that it will automatically map "user" of json to Model param "user", but HttpMessageConverter just ignore the "state" JSON Object and "user" Json Object. Can you help how can I manage to Customize converter or any other ways to create sample?
Thanks in advance!
What you mean by ignore?
BTW, if you have 'user' and 'state' objects with the 'id' value '1'; then the association should persisted with new sample object successfully in the database.
But if you want to create the whole object graph into db, then the id value should be null and perhaps you might need to setup the proper cascade options.
I've got two entity objects in my database: UserEntity and ItemEntity and they're mapped with OneToMany relationship.
Here is my code:
UserEntity:
#Entity
#Table(name = "users")
public class UserEntity {
#Id
#Column(name = "user_id")
#GeneratedValue
public int user_id;
#Column(name = "userlogin")
public String userlogin;
#Column(name = "userpass")
public String userpass;
#Column(name = "name")
public String name;
#Column(name = "email")
public String email;
....
#JsonBackReference
#OneToMany(mappedBy="user", cascade = { CascadeType.MERGE },fetch=FetchType.EAGER)
private List<ItemEntity> items;
ItemEntity:
#Entity
#Table(name = "items")
public class ItemEntity {
#Id
#Column(name = "id")
#GeneratedValue
private int id;
#Column(name = "title")
public String title;
#Column(name = "info")
public String info;
#JsonManagedReference
#ManyToOne
#JoinColumn(name="user_id")
private UserEntity user;
And now I'm trying to read all my Items from my database with specific fields from users that owns current item. I need only UserEntity name and email.
This code:
Query query = this.sessionFactory.getCurrentSession().createQuery("from ItemEntity WHERE title = :title");
returns all fields from UserEntity also, because it's mapped, but I don't want that, because I'm sending that data as JSON, and someone can see all informations about user who own that item (like user login and password) in some dev tools like Chrome.
How to reach that?
I'd suggest you use DTO.
Covert your entities to DTO and then transform the DTO objects to
json string.
In the DTO populate only those field that you want as part of your response.
This would make your design more clean.
In addition to what's jitsonfire is suggesting, you can write a query like this
select name, email from ItemEntity WHERE title = :title
than get your results like
List<Object[]> result = query.list();
The object array will contain your columns, the list element will equal to rows, so you can do something like
for (Object[] tuple : result) {
tuple[0]; //name
tuple[1]; // email
}
(***Edited*:**I am looking for the JSON representation of the solution provided here: Spring REST multiple #RequestBody parameters, possible?)
I have the following entity Account which has a member variable of another entity called Customer
#Entity
public class Account {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id=0;
#ManyToOne
#JoinColumn(name = "customer_id")
private Customer customer;
...
}
#Entity
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id=0;
private String customerId;
public Customer(){}
public Customer(String customerId){
this.customerId = customerId;
}
public long getId(){
return id;
}
public String getCustomerId(){
return customerId;
}
public void setCustomerId(String customerId){
this.customerId = customerId;
}
}
I need to post a JSON object representation of an Account. Here is the Controller method:
#Autowired
private AccountRepository accounts;
#RequestMapping(value="/accounts/account",method=RequestMethod.POST)
public #ResponseBody Account addAccount(#RequestBody Account account){
return accounts.save(account);
}
AccountRepository is an interface that extends CrudRepository
I have an existing customer with the URI http://localhost:8084/customers/customer/1
I have attempted to post the following JSON objects and received a 400 Bad Request response.
{"customer":"1"}
{"customer":"http://localhost:8084/customers/customer/1"}
{"customer":{"href":"http://localhost:8084/customers/customer/1"}}
Just to make sure that an Account can be created if correct data is received, I modified the controller method as per the following code, which created the account when I post to http://localhost:8084/accounts/account
#RequestMapping(value="/accounts/account",method=RequestMethod.POST)
public #ResponseBody Account addAccount() throws Exception{
Customer customer = customers.findOne(1);
Account account = new Account();
account.setCustomer(customer);
return accounts.save(account);
}
So my question is, how do I format a JSON object so as to Create an Entity whose member is an existing Entity?
I found out that the correct format is to provide the URI of the referenced entity, i.e in this case it should be
{"customer":"http://localhost:8084/customers/customer/1"}
However, this only worked after I added the data-rest dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
<version>{spri}</version>
</dependency>
Without this dependency, the request fails with a JsonMappingException