Advantage of assigning the returned savedEntity in Spring Data - spring

I see in most of the coders save data(using spring data) as:
savedEntity = repo.save(savedEntity);
Long id = savedEntity.getId();
I am confused about why most of them assign back the returned value to the saved Entity while the following code also works exact(I have tested myself):
repo.save(savedEntity);
Long id = savedEntity.getId();
Did I miss some benefit of assigning back?

for example, let the entity be:
#Entity
public class SavedEntity {
#Id
private int id;
private String name;
//getter, setters, all arg-constructor, and no-arg constructor
}
Consider the object of SavedEntity is
SavedEntity entity = new SavedEntity(1,"abcd");
now for your first question,
SavedUser entity1 = repo.save(entity);
Long id = entity1.getId();
this entity1 object is the return object getting from the database, which means the above entity is saved in the database succesfully.
for the Second Question,
repo.save(entity);
Long id = entity.getId();//which you got it from SavedEntity entity = new SavedEntity(1,"abcd");
here the value of id is the integer you mentioned in place of id(the raw value).

Most of the time the id (primary key) is generated automatically while storing the entity to the database using strategies like AUTO, Sequence etc. So as to fetch those id's or autogenerated primary key values we assign back the saved entity.
For example:
#Entity
public class Customer {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
}
In this case you'll not pass the id externally but it will create a value for it automatically while storing the data to DB.

Related

Bulk data to find exists or not : Spring Data JPA

I get an Post request that would give me a List<PersonApi> Objects
class PersonApi {
private String name;
private String age;
private String pincode ;
}
And I have an Entity Object named Person
#Entity
#Table(name = "person_master")
public class Person{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
#Column(name = "name")
String name;
#Column(name = "age")
String age;
#Column(name = "pincode ")
String pincode ;
}
My record from Post request would look something like this (pseudocode representation of the data below)
[
"Arun","33","09876gh"
"James","34","8765468"
]
I need to do a bulk-validation using Spring JPA.. Give the List<PersonApi> and get a True or False based on the condition that all the entries in the PersonApi objects list should be there in the database.
How to do this ?
The selected answer is not a right one. (not always right)
You are selecting the whole database to check for existence. Unless your use case is very special, i.e. table is very small, this will kill the performance.
The proper way may start from issuing repository.existsById(id) for each Person, if you never delete the persons, you can even apply some caching on top of it.
exists
Pseudo Code:
List<PersonApi> personsApiList = ...; //from request
List<Person> result = personRepository.findAll();
in your service class you can access your repository to fetch all database entities and check if your list of personapi's is completeley available.
boolean allEntriesExist = result.stream().allMatch(person -> personsApiList.contains(createPersonApiFromPerson(person)));
public PersonApi createPersonApiFromPerson(Person person){
return new PersonApi(person.getName(), person.getAge(), person.getPincode());
}

Javers compare entity to DTO

i'm new to Javers, and i`m currently using it to create a patch update for my entity. But i'm having some struggle with one specific scenario
I want to compare a Entity against a EntityDTO/VO and get only the changes in values, the current comparison only returns that is a NewObject and ObjectRemoved changes.
Example:
public class Entity{
private ObjectId id;
private String name;
private String description;
}
public class EntityDTO{
private String name;
}
//
Entity oldState = new Entity(new ObjectId(), "oldName" , "oldDescription);
EntityDTO newState = new EntityDTO( "newName" );
JaversBuilder.javers().build().compare(oldState, newState).getChanges();
//This is returning only NewObject/ObjectRemoved changes, and the intended is to be ValueChange/ReferenceChange
The questions is, is there a way to compare only the similar attributes between the objects?
No, in JaVers, you can compare only objects of the same type.

Add data to database from Controller, different methods but same row

I have an entity model, for simplification purposes let's say it looks like this :
public class Results {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Long firstUser;
private Long secondUser;
private Double average;
private Double median;
private Double score;
}
This is my ResultsService Implementation:
public class ResultsServiceImpl implements ResultsService{
#Autowired
private CalculateDataRepository calculateDataRepository;;
#Autowired
private ResultsService resultsService;
Results results=new Results();
public void Average(Long id1, Long id2){
UserData firstClient = calculateDataRepository.findOne(id1);
userData secondClient = calculateDataRepository.findOne(id2);
clientId = firstClient.getClient().getId();
secondId = secondClient.getClient().getId();
Double average=(firstClient.getA()+secondClient.getA())/2;
results.setAverage(average);
}
public void Score(Long id1, Long id2){
SurveyData firstClient = surveyDataRepository.findOne(id1);
SurveyData secondClient = surveyDataRepository.findOne(id2);
clientId = firstClient.getClient().getId();
secondId = secondClient.getClient().getId();
Double average=(firstClient.getB()+secondClient.getB());
results.setScore(average);
results.setFirstUser(clientId );
results.setSecondUser(secondId );
resultsService.save(results);
}
....
I tried declaring Results results=new Results(); inside every method, but when I save them they get saved in different rows, instead of the same one.
How do I hold the reference so that when I call the setter of a field in one function, it's in the same row as the setter of a field in the other function.
To keep the problem focused, I tried to avoid showing the implementation of calculateDataRepository which is just the repository of an entity where some results are saved for different users.
The Results Method has no foreign field reference nor a reference from somewhere else, as there are fields firstUser and secondUser which I set from one of the methods;
Thank you.
Edit:
Results results=resultsService.findByFirstUserAndSecondUser(clientId, secondId);
if(results==null) {
results= new Results();
// Store to db ?
}
results.setAverage();
resultsService.save(results);
Actually you need a method in ResultsRepository
Results findByFirstAndSecond(Long first, Long second);
In the each Average and Score methods (BTW Java naming convention requires to have method names start from lowercase letter) call the findByFirstAndSecond(id1, id2)
If the method returns null (no such result) create a new instance and save in the DB (INSERT). If some Results is returned store the info there and save changes in DB (UPDATE).

Spring Data Rest save record with relation (foreign-key) in Java (repo.save())

I don't know how to save a record in SDR with a link to an existing table.
For example:
There is a lookup-table Flag and another table Account with name and n:1 relation to Flag-ID.
The IDs in Flag-table are already created.
#Entity
public class Account{
public Account(String name, Flag flag){
this.name = name;
this.flag = flag;
}
#Id
private int id;
#Column
private String name;
#ManyToOne
private Flag flag;
// Getter & Setter
}
#Entity
public class Flag{
public Flag(String title){
this.title = title;
}
#Id
private int id;
#Column
private String title;
// Getter & Setter
}
Now I want to add an account and link it to the flag-id like this:
AccountRepo accountRepo;
accountRepo.save(new Account("Name", 0));
But I declared an object in my account-function and if I want to execute the save-function, I have to add a flag-object like this:
accountRepo.save(new Account("Name", new Flag("title")));
However in this case, the framework will add a new Flag-record, what I don't want. I only want to link it.
So I need help for solving my problem.
Thanks!
Edit:
The two answers from #piotr-sołtysiak and #upesh-m helped and worked for me. Thanks for your help!
You can use 'merge' of hibernate, ie. entityManager.merge(new Account("Name", new Flag("title"))). But the Id of the Flag should be an existing Id , so that it just adds an entry to Account.
ie. If you already have a flag record existing in db with id = 1, and you want to add an account linked to this flag, then use entityManager.merge(new Account("Name", existingFlagObject)
Find desired flag entity using dedicated repository, e.g
Flag flag = flagRespository.findByTitle("title");
Set it in Account entity and save:
accountRepo.save(new Account("Name", flag));

Spring MVC - loading data

I have filled database and one entity which uses 2 tables like this:
#Entity
#Table(name="Product")
#SecondaryTable(name="B")
public class Product {
#Id
#GeneratedValue
private int idProduct;
#Column(name="name")
private String name;
#Column(table="B",name="aaaa")
private String aaa;
#Column(table="B",name="bbbb")
private String bbbb;
When I'm loading data from database table B is cleared, why?
I tried to change value in hibernate.hbm2ddl.auto from "create-drop" to "update" but I have an error like this:
"Can not set int field com.packt.webstore.domain.Product.bbbb to null value".
I need to load and write data to database so which value shoud I set and how to fix this error?
EDIT: When I set #Column(name="bbb", nullable=true) is the same error.

Resources