Let's say if I have an Entity named person with lots of information including SSN. When other user query this person, I want to show a 'lite' version of person Entity. I could've done so by annotating SSN with #Transient, but that means the person himself would not get this field too. Is it possible to reuse the same Entity but return two different json to client? I'm using spring boot.
First of all #Transient just means that the value, the SSN in your case, won't be persisted to the database.
As for your problem annotations are static and cannot be applied dynamically.
You have 2 Options:
Define a new View class for your user.
Look at JacksonJsonViews
Related
Suppose I have a Employee class. It has got many fields like id, firstName, lastName, designaton, age, salary and other fields too. Now I am making a Get Query where I want to use all of these fields (required=false) to be passed as Request Params.
But the question is, there could be many combinations like (firstName,age) or (age,salary,lastName) or (designation,age,salary,lastName) and many more like this. So how should I handle all this filters. Shall I have to write each query for each case?
PS: I am using Spring Boot with Spring Data Jpa.
For this you will have to send Object from where you can get your combination. There may be many combination. So from this perspective you will send value as object and for database query you will select your combinations from that object.
If you want different combination, it won't be a good practice to write controller for every combination. So you can send a Object instead of RequestParam value where you can get your combinations from the Object
Example :
Class Employee{
// Your class instance variable
// Which is called your combinations
}
public Employee getEmployeeByName(Employee employee){
// now you send your desired combination from employee class for
// database query
}
Where you have too many fields, it's not a good practice to send all fields as RequestParam. Think of your class getting bigger day by day and you editing the controller method continously.
Better way is send as a object. No need to edit controller later. Only change the entity class
I want to implement a filtering feature based on the properties of an entity that I have stored in my db.
I'm using a JPA query to do so. The problem that I'm facing is concerned with entity manager which requires the class of the object that is required to return.
public List<CountryEntity> getSortedCountries(String field, String type) {
return entityManager.createQuery(GET_ALL_SORTED.concat(field).concat(" " + type), CountryEntity.class).getResultList();
}
When I select only one field, let's say the name of the country, the query returns a String and not an object of type CountryEntity.
What is the best approach to handle this problem? Should I create classes for every single case or is there another way that I'm missing?
Spring data jpa + postgres.
Have an entity
class Entity {
#Id
#GeneratedValue// generator from here https://stackoverflow.com/questions/60989691/how-to-manually-set-a-value-for-generatedvalue/61007375#61007375
private int id;
private String value;
}
And what I wish to do is to UPDATE an existing entity, setting a different id (be it a bad practice or not) value.
By default it of course is treated as a new entity and is attempted to be INSERTed.
Going by the flow of #Modifying seems to do the job right, but currently struggling to find if I can pass the whole entity instead of pinpointing every field:
update Entity e set e.id=?1, e.value=?2 where...
to
update Entity e set e=?1
So the questions here would be:
1. Is there a way to gracefully do an "UPDATE" with modified id in terms or regular spring-data-jpa flow?
2. If not, is there a way to provide the full entity to be consumed by the #Query?
Is there a way to gracefully do an "UPDATE" with modified id in terms or regular spring-data-jpa flow?
If you are using GenerationType.AUTO strategy for #GeneratedValue (AUTO is the default strategy), then you can set id of Entity to null before calling save. It will insert a new record with rest of the fields being the same as original. id of new record will be generated automatically by database engine.
If you are using GenerationType.AUTO strategy for #GeneratedValue
If not, is there a way to provide the full entity to be consumed by the #Query?
You can chose not use #Query. A far simpler approach can be using default save method provided by JPA repositories to directly pass an Entity object.
I'm making a system (using Spring + JPA with MySQL) that shows the best applicants for a certain job offer. The company and the applicants have their respective user account, and with that, they can fill in their personal/company information and their job profile/job offer conditions. With that, the system should match the job conditions (like 3+ years of experience in C) with the applicant's job profile.
My problem is that the User Account is created first, and should be independent, but these two different entities (Applicant and Company), with different attributes, are using it. So if I do something like create an applicant and company in the User Account, one of them will be always null.
How can I solve this? I guess the problem would be something like: how to implement a user account that can hold data from different entities that have different attributes (therefore, can't be grouped)? (In fact, I need one more entity, but I tried to simplify it to illustrate the problem more clearly).
I think, you should make marker interface, like public interface UserAccountable or smth. Implement this interface in your Applicant and Company classes. Then you can make a field in UserAccount class, like private UserAccountable someUser; and throught setters and getters you can assign and get this variable to Applicant or Company.
Hope this helps!
I found what I needed here: https://thoughts-on-java.org/complete-guide-inheritance-strategies-jpa-hibernate/
The problem was the mapping, not the class design per se. I could create interfaces and abstract classes to solve it in the Java world, but in the SQL world that's not possible, so the mapping is the key. In this case, I was looking for the Joined table mapping, but I realized I needed it just to not have null fields in my UserAccount, because I don't need a polymorphic query (e.g. give me the names of every 'user type' (Person, Company)), and it would be too costly performance wise to implement it that way, so I'll trade off space for performance, and I'll just reference all three user types in the User Account, leaving two of those three fields null forever.
PS: Single table mapping won't help because I do need to use not null conditions.
If i have several entites, lets say :
#Entity
class Book{
String name;
Author author;
}
#Entity
class Author{
String name;
City hometown;
}
#Entity
class City{
String cityName;
}
If i want to retrieve all the books, if i use classic JPA Repository and Spring Data and just do a findAll(), it will get me all the books with all the Authors with all their home towns. I know i can use #JsonIgnore, but i think that only prevents whats being returned, not whats being looked up in the database. And also i have methods that DO want to return both books and authors, so #JsonIgnore -ing does not work for me. Is there anything like this ? To tell Spring Data what to look up and what to return ? Any links or guides or methods i don't know of, would be appreciated.
Spring Data has the concept of 'projections' which allow you to return different representations of the same Entity.
Official Documentation:
Spring Data query methods usually return one or multiple instances of
the aggregate root managed by the repository. However, it might
sometimes be desirable to create projections based on certain
attributes of those types. Spring Data allows modeling dedicated
return types, to more selectively retrieve partial views of the
managed aggregates.
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections
Where a Projection is a 'closed' projection (a projection interface whose accessor methods all match properties of the target aggregate) then the documentation notes that additionally:
Spring Data can optimize the query execution [to select only the relevant fields], because we know about
all the attributes that are needed to back the projection proxy
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections.interfaces.closed
Spring Data also allows for Projections to be specified dynamically at runtime. See further:
https://github.com/spring-projects/spring-data-commons/blob/master/src/main/asciidoc/repository-projections.adoc#dynamic-projections
First mark your relations as LAZY
Then specify what data needs to be fetched on a per-query basis.
See for example:
https://vladmihalcea.com/eager-fetching-is-a-code-smell/