Save Entity Using Foreign Key - spring

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

Related

DTO and Entities mapping

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.

How to map the result set with specific columns of a JPQL query with dynamic projections to an entity

I am querying a database using jpql and my query is getting generated dynamically, i.e, both projections and predicates. However, I am not able to map the result set to get proper JSON response.
Entitlement Entity
#Entity
public class Entitlement{
#Id
#GenetedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(name = "license_id")
private String licenseId;
#Column(name = "customer_id")
private String customerId;
#OneToOne
#JoinColumn(name="product_uuid")
private Product product;
//setter getters and constructors
}
Product Entity
#Entity
public class Product{
#Id
#GenetedValue(strategy = GenerationType.AUTO)
#Column(name="product_uuid")
private Integer id;
#Column(name = "isbn")
private String isbn;
#Column(name = "title")
private String name;
//setter getters and constructors
}
EntitlementDaoImpl.java
Query query = entityManager.createQuery("select e.customerId,e.licenseId,p from Entitlement
e,Product p where e.product_uuid = p.product_uuid");
List<Entitlement> list = query.getResultList();
return list;
JSON response Received:
[
"customer101",
"license123",
"product": {
"id":201
"isbn":"abvhgfdWDMNB"
"name":"sample_book"
}
]
Expected JSON:
[
"customerId":"customer101",
"licenseId":"license123",
"product": {
"id":201
"isbn":"abvhgfdWDMNB"
"name":"sample_book"
}
]

One to Many bidirectional

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

Getting a tag as additional object returned in json while searching images by that tag

Okay first of all I don't even know how to describe it in one sentence to ask google ( yes I did and I failed).
I have this gallery spring boot back-end application.
So there is Image class and Tag class between which is manytomany relationship.
Here are these classes:
#Entity
#Table(name = "image")
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class)
public class Image {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "image_id")
private int id;
#Column(name = "name")
private String name;
#Column(name = "description")
private String description;
#Column(name = "height")
private int height;
#Column(name = "width")
private int width;
#Column(name = "date")
private Date date;
#ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
#JoinTable(
name="image_tag",
joinColumns = #JoinColumn(name="image_id"),
inverseJoinColumns = #JoinColumn(name = "tag_id")
)
private Set<Tag> tags = new HashSet<>();
// getters / setters further
And this is my tag class:
#Entity
#Table(name = "tag")
public class Tag {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "tag_id")
private int id;
#Column(name ="name", length= 50)
private String name;
#Column(name = "createddate", length = 100)
private Date createdDate;
public Tag(String name) {
this.name = name;
}
public Tag() {
}
#Override
public String toString() {
return "Tag{" +
"id=" + id +
", name='" + name + '\'' +
", createdDate=" + createdDate +
'}';
}
#ManyToMany(mappedBy = "tags")
private Set<Image> images = new HashSet<>();
This is how I get my Images by tag's name:
#Transactional
#Override
public List<Image> findByTag(String tag) {
Session session = entityManager.unwrap(Session.class);
Query<Image> query = session.createQuery("from Image as img inner join
img.tags as tags where tags.name=:tagname");
query.setParameter("tagname", tag);
List<Image> images = query.getResultList();
return images;
}
The problem is that whenever I make a get request with tag's name to get Images. Next to every Image object I receive there will also be that tag object with the name I used to look for images.
{
"#id": 2,
"id": 6,
"name": "peoples",
"description": "some people hanging",
"height": 501,
"width": 780,
"date": "2019-09-02T12:34:23.000+0000",
"tags": [
// there are more tags here I'm just saving space
{
"id": 7,
"name": "joy",
"createdDate": "2019-09-03T12:27:49.000+0000",
"images": [
2
]
}
],
"categories": [],
"picture": " byte array of picture"
},
Aand this is where magic happens, this object will be next to every Image object in Json response.
{
"id": 7,
"name": "joy",
"createdDate": "2019-09-03T12:27:49.000+0000",
"images": [
2
]
}
I'm using Angular for front end and I can't fetch Images like this because I'll get an error because there will be tag object there.
Really hoping to figure this out!
#GetMapping("/tags/{tagname}")
public List<Image> getImageByTag(#PathVariable("tagname") String tagName){
return imageService.findByTag(tagName);
}
And this is that service:
#Override
public List<Image> findByTag(String tag) {
return imageDao.findByTag(tag);
}
It's more like a json serialize problem. If you are using jackson as I guessed, you can try to manually control the output by following:
public class Image {
#JsonBackReference
private Set<Tag> tags = new HashSet<>();
}
If you do need to include tag in some occasions, you might have to implement a JSON view

Add entity with OneToOne Relation using JPA and REST

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);

Resources