Inject data in json entity with Spring Data REST - spring

I have JPA entity for department:
public class Department {
#Id
#Column(unique = true, nullable = false)
private long id;
#Basic
#Column
#Nationalized
private String name;
#Basic
#Column(length = 400)
#Nationalized
private String branch;
...
}
And REST repository
#RepositoryRestResource(collectionResourceRel = "departments", path = "departments")
public interface DepartmentRestRepository extends PagingAndSortingRepository<Department, Long> {
...
}
Entity's branch field is IDs of entity parent departments separated by space, e.g. 1 2 3.
When I query specific department via /api/departments/ID is it possible to attach to it field like parents with all parent entities queried?
I tryed to add getParents method to entity, but it obviously gave me unneeded parents queries with all entities recursively.
Update 2019.01.17:
As a workaround I splitted Department entity into Department and DepartmentWithParents. I added Department getParents() method to DepartmentWithParents entity and exposed REST API method that returns DepartmentWithParents.
Is there better way?

As a workaround I splitted Department entity into Department and DepartmentWithParents. I added Department getParents() method to DepartmentWithParents entity and exposed REST API method that returns DepartmentWithParents.

Related

Spring data jpa insert child into parent using rest call

Let's assume we have two entities A and B which have such a relation:
public class A {
#Id
private Integer id;
#OneToMany(mappedBy = "parent")
private Set<B> childs = new HashSet<>();
// getters and setters
}
public class B {
#Id
private Integer id;
#ManyToOne
private A parent;
// getters and setters
}
I'm having 2 repositories, one for each entity (ARepository and BRepository) and i'm using spring data rest starter so i've got generated rest api.
Let assume we have an instance of A, which has as id=12
In order to insert a B entity and link it to A i have to: POST the url http://localhost:8080/appContext/b/ and giving it a request body as follow: {"parent": "a/12"}
It works fine, but it is possible to have the same thing by posting http://localhost:8080/appContext/a/12/childs/ with the same request param except the "parent" JSON attribute ? as it's actually possible to fetch the childs of a parent using this last url.

how to put entity associations in JSON (inside POST HTTP request) while performing CREATE operation of entity has association of another entity?

I am using Spring Boot as my backend framework and I have a PERSON entity which has a one-to-one relation with GENDER entity.
I am using #RepositoryRestResource for PersonRepository and GenderRepository.
The GENDER table is already filled with two records of MALE and FEMALE and I have an angular form which creates a new PERSON.
In angular form, there is a list of genders with two items gotten from GenderRepository (male/female). how can I put the genderId in JSON of POST Request body to create a new Person.
I see that most of people use text/uri-list to update existing records however I want to set it while creating not updating.
You can do that by giving a link to the gender entity.
Person Entity
#Entity
public class Person {
#Id
#GeneratedValue
private Long id;
#OneToOne
private Gender gender;
//Other columns and getter/setters are removed for brevity
}
Gender Entity
#Entity
public class Gender {
#Id
#GeneratedValue
private Long id;
#Column
private String gender;
}
The following POST request to localhost:8080/api/persons with Content-Type header set to application/json creates a new Person entity and sets it's gender to the Gender with the id of 1.
{
"name": "Mahsum",
"surname": "Demir",
"gender": "http://localhost:8080/api/genders/1"
}

Fetch child entities when finding by a normal field in Spring Data JPA

I am using Spring Data JpaRepository to find List of entities matching a particular field. Consider the following code snippet:
Entity:
#Entity
#Table(name = "master")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Master implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
#Column(name = "id", nullable = false)
private Long Id;
#NotNull
#Column(name = "user_id", nullable = false)
private String userId;
#OneToOne(fetch = FetchType.EAGER)
#JoinColumn(name="id", referencedColumnName="id", insertable=false, updatable=false)
private Details Details;
Spring Data Custom JpaRepository:
public interface MasterRepository extends JpaRepository<Master,Long> {
List<Master> findMasterByUserId(String userId);
}
When i am using findBookingMasterByUserId repository method to find all records with specific user id, I am getting the List of Master entity but I am not getting the Details entity that has id as foreign key in it.
However, I get all the dependent entities when I use out of the box findAll method of JpaRepository but with custom findMasterByUserId repository method, child entities are not being fetched eagerly.
Any type of help would be highly appreciated. Thanks!
You can use #EntityGraph in your repo to eagerly get associated data:
#EntityGraph(attributePaths = {"details"})
List<Master> findBookingMasterByUserId(String userId);
P.S. Don't forget to change 'Details' field to details;
Your entity name is "Master" not "booking_master".
Change your method to:
List<Master> findByUserId(String userId);
Refer to below spring docs for more information on query creation mechanism for JPA.
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/
Alternatively,
#Query("SELECT m FROM Master m WHERE m.userId = :userId")
List<Master> findByUserId(#Param("userId") String userId);
The query generation from the method name is a query generation strategy where the invoked query is derived from the name of the query method.
We can create query methods that use this strategy by following these rules:
The name of our query method must start with one of the following
prefixes: find…By, read…By, query…By, count…By, and get…By.
If we want to limit the number of returned query results, we can add
the First or the Top keyword before the first By word. If we want to
get more than one result, we have to append the optional numeric
value to the First and the Top keywords. For example, findTopBy,
findTop1By, findFirstBy, and findFirst1By all return the first entity
that matches with the specified search criteria.
If we want to select unique results, we have to add the Distinct
keyword before the first By word. For example, findTitleDistinctBy or
findDistinctTitleBy means that we want to select all unique titles
that are found from the database.
We must add the search criteria of our query method after the first
By word. We can specify the search criteria by combining property
expressions with the supported keywords.
If our query method specifies x search conditions, we must add x
method parameters to it. In other words, the number of method
parameters must be equal than the number of search conditions. Also,
the method parameters must be given in the same order than the search
conditions.

Get entity property with Spring JPA

I'm using Spring JPA in my DAO layer. I have an entity Projet having inside an entity property Client:
Project.java
#Entity
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int projetId;
private String libelle;
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name="client_id")
private Client client;
// ... constructors, getters & setters
}
Client.java
#Entity
public class Client {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int clientId;
private String denomination;
// ... constructors, getters & setters
}
in my DAO interface I have the following specifications:
ProjetDao.java
#Repository
#Transactional
public interface ProjetDao extends CrudRepository<Projet, Integer> {
#Transactional
public Projet findByLibelle(String libelle);
#Transactional
public Projet findByProjetId(int projetId);
}
My question is: How can I specify in my DAO interface a method that will return all clients distinct in List<Client>?
From the documentation and JIRA:
List<Project> findAllDistinctBy();
The query builder mechanism built into Spring Data repository infrastructure is useful for building constraining queries over entities of the repository. The mechanism strips the prefixes find…By, read…By, query…By, count…By, and get…By from the method and starts parsing the rest of it. The introducing clause can contain further expressions such as a Distinct to set a distinct flag on the query to be created. However, the first By acts as delimiter to indicate the start of the actual criteria. At a very basic level you can define conditions on entity properties and concatenate them with And and Or.
You are dealing with a one-to-one relationship, in this case I guess the list that you need is not really related to specific project, you just want a distinct list of clients.
You will need to create another repository (ClientRepository) for the Client entity and add a findAllDistinct method in this repository.

How to update a REST Resource with Spring Data Rest that has a OneToMany and nested a ManyToOne relation

I have a simple Invoice System where I need to create and update Invoices. I'm trying to use Spring Data Rest for that, but from what I get from the docs I really would end up doing a lot of calls to implement an update.
#Entity
class Article {
#Id
#GeneratedValue
Long ID;
#Basic
String name;
}
#Entity
class Invoice {
#Id
#GeneratedValue
Long ID;
#Basic
String customer;
#OneToMany(cascade=CascadeType.ALL)
List<InvoiceItem> items;
}
#Entity
class InvoiceItem {
#Id
#GeneratedValue
Long ID;
#Basic
double amount;
#ManyToOne
private Article article;
}
I'm using Spring Data Rest to expose this model to my web fronend via these Spring Data Rest/JPA Repositories
#RepositoryRestResource(collectionResourceRel = "articles", path = "articles")
interface ArticleJPARepository extends JpaRepository<Article, Long> {}
#RepositoryRestResource(collectionResourceRel = "invoices", path = "invoices")
interface InvoiceJPARepository extends JpaRepository<Invoice, Long> {}
#RepositoryRestResource(collectionResourceRel = "invoiceitems", path = "invoiceitems")
interface InvoiceItemJPARepository extends JpaRepository<InvoiceItem, Long> {}
So let's say I have an update form that looks like this:
where I can do several things:
Update Invoice customer
Change an Article of an existing InvoiceItem
Remove some of the InvoiceItems
Append a new InvoiceItem
From what I get from the Spring Rest Docs is that I need to make several calls now.
Update of the invoice customer I need to PUT /invoices/1
then update n the Article and amount in an InvoiceItem PUT n times PUT /invoiceitems/<x>/
Append m new InvoiceItems m times POST /invoiceitems then POST /invoices/1/items
Delete InvoiceItem 2 DELETE /invoiceitems/2 and then DELETE /invoices/1/items/<2>
Is there a simpler way to realise such an update with Spring Data Rest?

Resources