How to add column name to the query result SPRING JPA - java

For example, I've got such query:
#Query("SELECT u.name FROM User u")
public List<User> findAllUsers();
I know, this is not an optimal way to show all users, but it's just for example, my query is more complex.
I've got such answer:
[{"Tom Wally"}]
But I want to get:
[{"name":"Tom Wally"}]
How to add column name to custom query?

Maybe you are talking about how return a response in a json format.
If you want a response in json-format you should create two classes like these, one when creating your object, and the other when creating the response from a list.
public class UserResponseList extends ArrayList<UserResponse>(){
public UserResponseList(List <UserResponse> myList){
super(myList);
}
}
public class UserResponse(){
private String name;
}
finally ,you instantiate UserResponseList sending your list in constructor, and you have your json response with your specific format.

Related

How to ignore field/column only when return response from spring boot

I need to ignore the field when return the response from spring boot. Pls find below info,
I have one pojo called Student as below
Student {
id,
name,
lastName
}
i am getting a body for as PostRequest as below
{
id:"1",
name:"Test",
lname:"Test"
}
i want get all the data from frontEnd (id,name,Lname) But i just want to return the same pojo class without id as below,
{
name:"Test",
lName:"Test"
}
I have tried #JsonIgnore for column id, But it makes the id column as null(id=null -it is coming like this even when i send data to id field from postman) when i get the data from frontEnd.
I would like to use only one pojo to get the data with proper data(withoud getting id as Null), and need to send back the data by ignoring the id column.
Is there any way to achieve it instead of using another pojo?
You just need to use #JsonInclude(JsonInclude.Include.NON_NULL) at class level and it will be helpful for ignore all your null fields.
For example :
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Test {
// Fields
// Constructors
// Getters - setters
}
As of now you are using only one POJO it's not good practice because it's your main entity into your project, so good practice is always make DTO for the same.
This is possible via the #JsonView annotation that is part of Jackson. Spring can leverage it to define the views used on the controller.
You'd define your DTO class like this:
class User {
User(String internalId, String externalId, String name) {
this.internalId = internalId;
this.externalId = externalId;
this.name = name;
}
#JsonView(User.Views.Internal.class)
String internalId;
#JsonView(User.Views.Public.class)
String externalId;
#JsonView(User.Views.Public.class)
String name;
static class Views {
static class Public {
}
static class Internal extends Public {
}
}
}
The Views internal class acts as a marker to jackson, in order to tell it which fields to include in which configuration. It does not need to be an inner class, but that makes for a shorter code snippet to paste here. Since Internal extends Public, all fields marked with Public are also included when the Internal view is selected.
You can then define a controller like this:
#RestController
class UserController {
#GetMapping("/user/internal")
#JsonView(User.Views.Internal.class)
User getPublicUser() {
return new User("internal", "external", "john");
}
#GetMapping("/user/public")
#JsonView(User.Views.Public.class)
User getPrivateUser() {
return new User("internal", "external", "john");
}
}
Since Spring is aware of the JsonView annotations, the JSON returned by the /public endpoint will contain only externalId and name, and the /internal endpoint will additionally include the internalId field.
Note that fields with no annotation will not be included if you enable any view. This behaviour can be controlled by MapperFeature.DEFAULT_VIEW_INCLUSION, which was false in the default Spring ObjectMapper when I used this for the last time.
You can also annotate your #RequestBody parameters to controller methods with JsonView, to allow/disallow certain parameters on input objects, and then use a different set of parameters for output objects.

Fetch only some attributes from table using jpa findall java

I want to select just a few columns from a table.. The catch is that I'm using a specification and pagination from the front end filter, and I don't think I can concatenate those with criteriabuilder. My original idea was to create a #MappedSuperClass with the attributes I wanted (in this case, just the id and date), and fetch using a dao repository from an empty subclass. I have done something similar to this before and it worked, but the subclasses used different tables so it's a different ball game. In this case, since both subclasses use the same table, and there's nothing to differentiate between the classes other than one doesn't have any attributes, it keeps fetching the original bigger class. I want to avoid creating a view with just the columns I want or processing the data in the backend after the fetching, but I think that's the only possible solution.
Superclass
#MappedSupperClass
public class Superclass
{
#Column( name = "id" )
private Integer id;
#Column( name = "date" )
private Date date;
}
Original Subclass
#Entity
#Table( name = "table" )
public class OriginalSubclass
extends Superclass
{
#Column( name = "code" )
private Integer code;
#Column( name = "name" )
private String name;
}
New Subclass
#Entity
#Table( name = "table" )
public class NewSubclass
extends Superclass
{
}
I created a new dao for the new subclass
#Repository
public interface NewSubclassDao
extends JpaRepository<NewSubclass, Integer>, JpaSpecificationExecutor<NewSubclass>
{
}
Is there a way to get only the attributes I want with something similar to my idea?
Or is it possible to do it with criteriabuilder?
If none of the options are viable, would you prefer to use a view or process the data?
EDIT
To make it perfectly clear, I want Spring to bring me only the id and date attributes, using JPA findAll or something very similar, without messing the pagination or filter from the Specification.
You should be able to use #Query to do something like:
#Repository
#Transactional(readOnly = true)
public interface NewSubclassDao
extends JpaRepository<NewSubclass, Integer>, JpaSpecificationExecutor<NewSubclass>
{
#Query("SELECT table.code FROM #{#entityName} table")
public Set<Integer> findAllCodes();
}
There are many ways to do this, but I think this is a perfect use case for Blaze-Persistence Entity Views.
I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.
A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:
#EntityView(User.class)
public interface UserDto {
#IdMapping
Long getId();
String getName();
Set<RoleDto> getRoles();
#EntityView(Role.class)
interface RoleDto {
#IdMapping
Long getId();
String getName();
}
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
UserDto a = entityViewManager.find(entityManager, UserDto.class, id);
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
Page<UserDto> findAll(Pageable pageable);
The best part is, it will only fetch the state that is actually necessary!

spring data mongodb multiple entity in same collection

I am in a situation where I have to store data belonging to multiple entities in a single collection. But when I query then back, I dont want unwanted records in my result. How can we achieve this using spring? Below is what I have done so far.
1. I give same collection name in entity as shown below.
#Document(collection = "livingThings")
#Data
public class AnimalEntity {
//contains id, type, bla, bla
}
#Document(collection = "livingThings")
#Data
public class HumanEntity {
//contains id, gender, address
}
2. I create independent mongoRepository interfaces
public interface AnimalRepository implements MongoRepository<AnimalEntity, String> {
}
public interface HumanRepository implements MongoRepository<HumanEntity, String> {
}
3. And the problem is
when I do animalRepo.findAll or humanRepo.findAll, I get all records available in the collection.
4. What I expect
animalRepo.findAll returns only those records where document structure is same as AnimalEntity.
Thank you very much for your time and patience to attend this query.
MongoDB automatically adds _class field to entities in a collection. Even though it is not the best solution, you can try this:
#Query("_class:your package name here.AnimalEntity")
public AnimalEntity findAllAnimals();

How to find letter in all columns with Spring Data JpaRepository

Here is my Repository
public interface NoteRepository extends JpaRepository<Note,Long> {
List<Note> findByContentContains(String content);
and my method in class NoteController which return me words with "e" in column Content
#GetMapping("/notesletter")
public List<String> getLetters(){
return noteRepository.findByContentContains("e")
.stream()
.map(note -> note.getContent())
.collect(Collectors.toList());
}
Please, help me to find a method which will return every words with letter "e",for example, from all columns.
I am working with Postman
Of course you can you native queries
#Query("select u from Note u where u.COL1 = ?1 and u.COL2 = ?1")
List<Note> findByContentContains(String content)
or use jpa feature as given below, Note findByLastnameOrFirstnameStartingWith is mentioned to understand easily, so replace your firstname,lastname as colu1name,col2name respectively.Refer here for more jpa method conventions`
public interface NoteRepository extends JpaRepository<Note,Long> {
List<Note> findByLastnameOrFirstnameStartingWith(String param1,String param2)
static List<Note> findByContentContains(String content){
findByLastnameOrFirstnameStartingWith(content,content);
}
}
You can try the or operation in the method name like below.
Or findByLastnameOrFirstname
https://docs.spring.io/spring-data/jpa/docs/1.5.0.RELEASE/reference/html/jpa.repositories.html
Other approaches are possible too.
If you know the native query or JPQL equivalent that returns the results checking all the columns of the entity.
Use of
#Query above the method in repository interface can take a JPQL or native query.
#NamedQuery annotation is also available if you know the query. This annotation to be used over the Entity class, name attribute is used to specify the accessing method name which returns the data, this can be used in repository interface.

java- dto to model convert Error

i have dto and model layer.And i want convert dto to model layer like this code.How do i fix this error?I have all getter and setter i need
model/travel class
public Travel convert(TravelDTO dto) {
this.setTravelID(dto.getTravelID());
this.setTravelCost(dto.getTravelCost());
this.setTravelStart(dto.getTravelStart());
this.setTravelEnd(dto.getTravelEnd());
this.setLocation(dto.getLocation());
this.setTravelPurpose(dto.getTravelPurpose());
this.setUser(new User().convert(dto.getUser()));
return this;
}
dto/travelDTO class
public TravelDTO convert(Travel entity) {
this.setTravelID(entity.getTravelID());
this.setTravelCost(entity.getTravelCost());
this.setTravelStart(entity.getTravelStart());
this.setTravelEnd(entity.getTravelEnd());
this.setLocation(entity.getLocation());
this.setTravelPurpose(entity.getTravelPurpose());
this.setUser(new UserDTO().convert(entity.getUser()));
return this;
}
userDto / convert code
public UserDTO convert(User entity) {
this.setUserID(entity.getUserID());
this.setFirstName(entity.getFirstName());
this.setLastName(entity.getLastName());
this.setManagerId(entity.getManagerId());
this.setPassword(entity.getPassword());
this.setRegNumber(entity.getRegNumber());
this.setUserName(entity.getUserName());
this.setDepartment(new DepartmentDTO().convert(entity.getDepartment()));
this.setTravel(new TravelDTO().convert(entity.getTravel()));
return this;
}
The error message explains the issue :). It says the entity.getUser() is returning a list of users. But the method accepts one User object.
The problem is your entity.getUser() is returning List whereas your convert method of UserDTO is expecting single User model object.
As I can see from you screenshot, UserDTO.convert method accepts argument of type User, and you are trying to pass argument with type List. I guess, the possible solution is to make Travel.getUser() return User instead of List.
UPDATE
You may iterate through your list of Users, converting each one to UserDTO and then adding it to collection, then passing it as an argument to this.setUser. Something like this: `
List<UserDTO> userDTOs = new ArrayList<>();
List<User> users = entity.getUser();
for (User user : users) {
UserDTO userDTO = new UserDTO.convert(user);
userDTOs.add(userDTO);
}
this.setUser(userDTOs);
And please pay attention that your TravelDTO class has List<User> user field. I guess, it should be List<UserDTO> users.

Categories

Resources