I am building a Spring Rest Application, I need help with DTO's and parsing a result to a endpoint
This is json that I return at the moment to the endpoint:
{
"id": 1,
"name": "Ella - IPA Is Dead",
"description": "2015 IPA is Dead Series. Supremely floral, this hugely under-rated hop is related to Galaxy and was first cultivated in the Australian state of Victoria.",
"method": {
"mash_temp": [
{
"temp": {
"value": 65
}
}
]
}
}
I don't want to return "method" from this json, I just need "id", "name", "description", "mash_temp" - so it should look like this:
{
"id": 1,
"name": "Ella - IPA Is Dead",
"description": "2015 IPA is Dead Series. Supremely floral, this hugely under-rated hop is related to Galaxy and was first cultivated in the Australian state of Victoria. Initially given the same name as a certain Eurolager, their lawyers got involved and the St- prefix was dropped. Ella displays subtle notes of spice, but is fundamentally a truly floral bouquet, redolent of the Southern Hemisphere.",
"mash_temp": [
{
"temp": {
"value": 65
}
}
]
}
Those are the entities that I am using now:
Beer Entity:
#Entity
public class Beer implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "beer_id", unique = true, nullable = false)
private Integer id;
#Column(name = "name", nullable = false)
private String name;
#JsonProperty("description")
#Column(name = "description", nullable = false, columnDefinition = "TEXT")
private String description;
#JsonProperty("method")
#OneToOne(cascade = CascadeType.ALL)
private Method method;
}
Method Entity:
#Entity
public class Method implements Serializable
{
#JsonIgnore(value = true)
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#JsonProperty("mash_temp")
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "mash_temp")
private List<MashTemp> mash_temp = new ArrayList<>();
}
MashTemp Entity:
#Entity
public class MashTemp implements Serializable
{
#JsonIgnore(value = true)
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#OneToOne(cascade = CascadeType.ALL)
private Temp temp;
#ManyToOne
private Method method;
}
Temp Entity:
#Entity
public class Temp implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private Integer value;
#JsonIgnore(value = true)
private String unit;
#OneToOne
private MashTemp mashTemp;
}
Does anyone know how to create DTO's from this Entities but without "method" field?
Also this is my Controller:
#GetMapping("/beers")
public ResponseEntity<Set<Beer>> getAllBeers()
{
return new ResponseEntity<>(beerService.getAllBeers(), HttpStatus.OK);
}
#GetMapping("/beers/{id}")
public ResponseEntity<Beer> getById(#PathVariable Integer id) {
Beer beer = beerService.findById(id);
return new ResponseEntity<>(beer, HttpStatus.OK);
}
Have a look at the #JsonUnwrapped annotation (https://fasterxml.github.io/jackson-annotations/javadoc/2.8/com/fasterxml/jackson/annotation/JsonUnwrapped.html). You can put it on the method field in the Beer class, and then the properties of the Method class are serialized directly on the same level as the ones from Beer.
Related
I have two classes Post and Comment, one post can have multiple comments. So I have created my classes as follows:
Post:
#Entity
#Table(name = "posts")
public class Post extends AuditModel {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Size(max = 100)
#Column(unique = true)
private String title;
#NotNull
#Size(max = 250)
private String description;
#NotNull
#Lob
private String content;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "post")
private Set<Comment> comments = new HashSet<>();
}
Comment:
#Entity
#Table(name = "comments")
public class Comment extends AuditModel {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Lob
private String text;
#ManyToOne(fetch = FetchType.EAGER, optional = false)
#JoinColumn(name = "post_id", nullable = false)
#OnDelete(action = OnDeleteAction.CASCADE)
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
#JsonIdentityReference(alwaysAsId = true)
#JsonProperty("post_id")
private Post post;
}
Post method:
#PostMapping("/posts")
public Post createPost(#Valid #RequestBody Post post) {
return postRepository.save(post);
}
Swagger request:
{
"id": 0,
"title": "string",
"description": "string",
"content": "string",
"comments": [
{
"id": 0,
"text": "string",
"post_id": 0
}
]
}
When I do a POST using the above schema, I am expecting that hibernate will insert data in both the tables. But instead, I get below error:
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unresolved forward references for: ; nested exception is com.fasterxml.jackson.databind.deser.UnresolvedForwardReference: Unresolved forward references for:
at [Source: (PushbackInputStream); line: 1, column: 117]Object id [1] (for `com.example.jpa.model.Post`) at [Source: (PushbackInputStream); line: 1, column: 115].]
Can someone please help me to understand this and how can I achieve my requirement?
I have problems with Many to One relationship because I don't show correctly the entity.
Could anyone helps to me ?
I attached my code.
Invoice
#Entity
#Table(name = "invoices")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")
public class Invoice {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String clave;
#OneToMany(mappedBy = "invoice", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY, orphanRemoval = true)
private List<InvoiceLine> lines;
InvoiceLines
#Entity
#Table(name = "invoice_lines")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")
public class InvoiceLine {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "product", nullable = false)
private String product;
#ManyToOne
#JoinColumn(name = "invoice_id", referencedColumnName = "id", nullable = false)
private Invoice invoice;
Controller
#RestController
public class InvoiceController{
#Autowired
private InvoiceRepository invoiceRepository;
#Autowired
private InvoiceLineRepository invoiceLineRepository;
#GetMapping("/")
public Iterable<Invoice> findAllnvoices(){
return invoiceRepository.findAll();
}
#GetMapping("/invoiceLine")
public Iterable<InvoiceLine> findAllInvoiceLine(){
return invoiceLineRepository.findAll();
}
#GetMapping("/{id}")
public Optional<Invoice> findTagByInvoice(#PathVariable("id") Long id){
return invoiceRepository.findById(id);
}
}
The response when I call a endpoint invoiceLine :
[
{
"id": 1,
"product": "Tag1-ES",
"invoice": {
"id": 1,
"clave": "Tag1",
"lines": [
1,
{
"id": 2,
"product": "Tag1-FR",
"invoice": 1
},
{
"id": 3,
"product": "Tag1-IT",
"invoice": 1
}
]
}
},
2,
3
]
My question :Why is not showing correctly the response the ManyToOne entity if I have all correct ?
If I understood your problem correctly after the comments, you are bothered by the "numbers" that are displayed. Those numbers are used to avoid infinite recursion, and they refer to entities that were already displayed.
So the number "2" would be this actually:
{
"id": 2,
"product": "Tag1-FR",
"invoice": 1
}
If a representation like that is not used, then the whole invoice and it's items would be repeated infinitely.
There are several different ways to avoid this behavior, such as using #JsonIgnore or #JsonBackReference and #JsonManagedReference. Take a look at this explanation about their differences
Difference between #JsonIgnore and #JsonBackReference, #JsonManagedReference
i have the following two domain objects and it has the one to many relation between them
1.BOY (Boy.java)
2.CYCLE (cycle.java)
its a springboot based application,and i did javerse repository implementation with this application .
while fetching the shadows using JQL [javerse query language ] its not working properly
1.Pom file i added javers-spring-boot-starter-sql dependency
2.Boy entity class
#Entity
#Table(name = "boy")
public class Boy implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#Column(name = "name")
private String name;
#OneToMany(mappedBy = "boy")
private Set<Cycle> cycles = new HashSet<>();
}
3.Cycle entity class
#Entity
#Table(name = "cycle")
public class Cycle implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#Column(name = "cycname")
private String cycname;
#ManyToOne
#JsonIgnoreProperties("cycles")
private Boy boy;
}
4.Boy and Cycle repositories has been annotated with #JaversSpringDataAuditable
6.Audit Fetch API using Javerse Query Language
#PostMapping("/audit/shadowsboy/{id}")
#Timed
public String getShadows(#PathVariable Long id) {
JqlQuery queryBuilder = QueryBuilder.byInstanceId(id, Boy.class).withScopeCommitDeep().build();
List<Shadow<Object>> shadowList = javers.findShadows(queryBuilder);
System.out.println("shadows: ::::::::::::::::::::::::::" + javers.getJsonConverter().toJson(shadowList));
return javers.getJsonConverter().toJson(shadowList);
}
Output:
after adding a cycle to boy ,findShadows by Boy id returns
{
"commitMetadata": {
"author": "anonymousUser",
"properties": [],
"commitDate": "2019-07-20T13:11:24.076",
"commitDateInstant": "2019-07-20T07:41:24.076Z",
"id": 2.00
},
"it": {
"id": 951,
"name": null,
"cycles": []
}
},
{
"commitMetadata": {
"author": "anonymousUser",
"properties": [],
"commitDate": "2019-07-20T13:04:26.988",
"commitDateInstant": "2019-07-20T07:34:26.988Z",
"id": 1.00
},
"it": {
"id": 951,
"name": "gajendran.g",
"cycles": []
}
}
]
expected outcome : cycles object must not be empty or null
I have a question that I hope I can describe clearly. I have the following classes:
#Entity
public class Filter {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY,orphanRemoval = true)
#JoinColumn(name = "filter_id", nullable = false)
private Set<FilterMedication> medications;
//setter and getters are not show
...}
.
#Entity
public class FilterMedication {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#ManyToOne
#JoinColumn(name = "medication_id", nullable = false)
private Medication medication;
// Setters and getters are not shown
.....}
.
#Entity
#Table(name = "medication")
public class Medication {
#Column(name = "generic_name")
private String genericname;
private String name;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
// Setters and getters are not shown
.....}
Basically Filters one-to-many relationship with FilterMedicaton, and FilterMedication has many-to-one relationship with Medication.
I created a repository to query for Filters
public interface FilterRepository extends JpaRepository <Filter, Long> {}
I can add a new filter by sending the following JSON object to the save() function
{
"id": 1,
"name": "Test1",
"medications": [
{
"id": 2,
"medication": {
"genericname": "Oxymetazoline HCl Nasal Soln 0.05%",
"name": "12 HOUR NASAL SPRAY 0.05 % NA SOLN",
"strength": "0.05%",
"form": "Solution",
"route": "Nasal"
}
}
]
}
Now time for the question: Is there a way to pass the Medication Foreign Key instead of the complete Medication object, Spring JPA will convert the foreign key to the proper object? The JSON code will be something like this
{
"id": 1,
"name": "Test1",
"medications": [
{
"id": 2,
"FORIGEN KEY": 1
}
]
}
Technically, I can write a function to do so; however, I feel that there is a better and cleaner way to do it.
//convert json to java obj
Filter filter = new Gson().fromjson(yourjson, Filter.class);
//get the fiterMedication (id = 2)
int id = filter.getMedications().getId();
FilterMedication filterMedication = filterMedicationRepository.get(id);
Filter newFilter = new Filter();
newFilter.setId(filter.getId());
....//set name
newFilter.getMedications.add(filterMedication);//get the set of medications and add the element filterMedication
//save newFilter
I am using Spring JPA Restful, and I don't understand how to insert an entity with a foreign key.
Activity Entity:
#Entity
#Table(name= "Activity")
public class Activity implements Serializable{
#Id
#GeneratedValue(generator = "uuid")
#GenericGenerator(name="uuid", strategy = "uuid2")
#Column(name = "uuid", nullable = false, unique = true)
private UUID uuid;
#OneToOne(fetch = FetchType.EAGER, cascade=CascadeType.MERGE)
#JoinColumn(name="type", nullable = false)
private ActivityType type;
#Column(nullable = false)
private String label;
ActivityType Entity:
#Entity
#Table(name= "ActivityType")
public class ActivityType implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(nullable = false, unique = true)
private String code;
#Column(nullable = false
private String label;
Is it possible to insert Activity simply? With something like this JSON where ActivityType's id "1" exists:
createActivity:
{"label":"LABEL","type":1}
With this code I have to do:
createActivity:
{"label":"LABEL","type":{"id":1}}
which return value is:
{
"uuid": "a54b27aa-8d49-41fd-8976-70c019c40e3b",
"type": {
"id": 1,
"code": null,
"label": null
},
"label": "LABEL",
"details": null
}
I use the library gson for parsing domain classes into JSON.
//... code for making your activity, let's say you have an Activity object myActivity
Just add the following code where you want to parse your object into JSON.
Gson gson = new GSON();
String json = gson.toJson(myActivity);