Filter data in spring boot - spring

Dont know if this is possible but I want to call my data and filter it , so for example notification type will be for example 1 or 2 and then give me everything with a 1 and a 2
My Model
public class Notifications {
#Id
private String id;
private String notificationMsg;
private String notificationType;
private Date createdDate = new Date();
//Get all Notification by type
#RequestMapping(value = "/all/{notificationType}", method = RequestMethod.GET)
public List<Notifications> getAllByNotificationType(#PathVariable("notificationType") String notificationType) {
List<Notifications> notifications= this.notificationRepository.findByNotificationType(notificationType);
return user;
}
Or should I add to the model and create a interface like this
List<Notifications> findByNumber1ORNumber2ORNumber3(String Number1,String Number2,String Number3);

You can use in clause :
https://javadeveloperzone.com/spring/spring-jpa-query-in-clause-example/
List<Employee> findByEmployeeNameIn(List<String> names);

Related

Pagination of an complex object into DTO. JPA #Query

I have the following query to take some data regarding two entities in the same time and I receive an error.
#Query(value = "select new base.models.HRTableEntity( yr.user.gid, yr.user.id, yr.user.lastName || ' ' || yr.user.firstName, yr.user.position, yr.user.created,yr.genericField1,yr.genericField2) from YearlyReview yr where yr.year = :yr and yr.user.realDepartment = :dep and yr.user.city = :ct",
countQuery = "select count(yr.id) from YearlyReview yr where yr.year = :yr and yr.user.realDepartment = :dep and yr.user.city = :ct",
nativeQuery = false)
Page<HRTableEntity> getAllTableEntity(Pageable pageRequest, #Param("yr") int year, #Param("dep") String department, #Param("ct") String location);
I call this cunction with default Sort (gid: ASC) and receive the following error
org.hibernate.QueryException: could not resolve property: gid of: base.entities.YearlyReview
Repo interface:
public interface PageableYearlyReview extends CrudRepository<YearlyReview, UUID>
Yearly review have a member (user) of type ApplicationUser and I want to put information into DTO from yr.user.gid into HRTableEntry.gid.
What is the right way to do that ?
EDIT:
function call:
crunRepoYearTable.getAllTableEntity(PageRequest.of(pageNo - 1, pageSize, sort), year, realDepartment, user.getCity())
sort building
sortDir.equalsIgnoreCase(Sort.Direction.ASC.name()) ? Sort.by(sortedField).ascending() : Sort.by(sortedField).descending();
Entity structure:
public class YearlyReview {
#Id
private UUID id;
private int year;
#OneToOne
private ApplicationUser user;
....
}
public class ApplicationUser {
#Id
private String id;
private String gid;
.....
}
Problem solved:
for sort by gid need to send from the fronted like this user.gid. User is required to refer at AppUser and gid to access information. And change interface like this
public interface PageableYearlyReview extends CrudRepository<ApplicationUser, String>

JPA - How to copy and modify it's content of Page object?

I have this Meeting and Favorite models;
public class Meeting implements Serializable {
private long id;
private String meetingTitle;
private Date meetingStartDate;
private User host;
}
public class MeetingFavorite implements Serializable {
private long id;
private boolean active = false;
private Meeting meeting;
private Date updatedDate;
}
And I can successfully fetch MeetingFavorite page object like;
#GetMapping(value = "/favorite-meetings", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE)
public ResponseEntity searchFavoriteMeetings(
MeetingFavoriteSpecification search, HttpSession session) {
Page<MeetingFavorite> page = meetingsService.findFavoriteMeetings(search);
return ResponseEntity.ok(page);
}
Is it possible to get Meeting contents only from MeetingFavorite Page w/ it's pagination data?
I tried this and it returns Meeting objects. But pagination data is lost.
Page<MeetingFavorite> page = meetingsService.findFavoriteMeetings(search);
List<Meeting> meetings = new ArrayList<Meeting>();
page.forEach(entity -> meetings.add(entity.getMeeting()));
final Page<Meeting> meetingPage = new PageImpl<>(meetings);
return ResponseEntity.ok(meetingPage);
Oh, I found the way. Thanks.
List<Meeting> meetings = new ArrayList<Meeting>();
page.forEach(entity -> meetings.add(entity.getMeeting()));
Sort sort = new Sort(Sort.Direction.DESC, "updatedDate");
Pageable pageable = new PageRequest(search.getOffset() / search.getLimit(), search.getLimit(), sort);
final Page<Meeting> meetingPage = new PageImpl<Meeting>(meetings, pageable, page.getTotalElements());
return ResponseEntity.ok(meetingPage);

Spring MongoRepository custom query

Hi I am new to using Spring with MongoRepository and I'm working on creating a custom query for MongoDB using Spring's MongoRepository.
What I would like to do is return a custom query for another variable in my model instead of the Object id.
for my model I have:
#Document(collection = "useraccount")
public class UserAccounts {
#Id
private String id;
private String accountNumber;
private String firstName;
private String lastName;
// getters and setters
}
inside of my repository I just extend the generic MongoRepository:
#Repository
public interface UserAccountsRepository extends MongoRepository<UserAccounts, String> {
}
I am trying to create a custom query that returns the accountNumber inside of my UserAccountsService:
#Service
public class UserAccountsService {
private final UserAccountsRepository userAccountsRepository;
public UserAccountsService(UserAccountsRepository userAccountsRepository) {
this.userAccountsRepository = userAccountsRepository;
}
// generic find by Object id
public UserAccounts findOne(String id) {
Optional<UserAccounts> userAccountsOptional =
userAccountsRepository.findById(id);
if(!userAccountsOptional.isPresent()) {
throw new RuntimeException("User Account Not Found");
}
return userAccountsOptional.get();
}
// would like to implement custom query to return UserAccount if
// found by accountNumber variable
public UserAccounts findOneByUserAccountNumber(String accountNumber) {
return dormantAccountsRepository.findOne(*need query here*);;
}
}
How would I go about creating a custom query to find a User Account by the accountNumber instead of the object id?
Any help would be great thanks!

How to send Java collections containing subclasses to spring controller

I'm trying to send collections to my spring MVC controller:
#RequestMapping("/postUsers.do")
public #ResponseBody ResponseDTO postUsers(#ModelAttribute("mapperList") MapperList mapperList) {
//prints {"users":null}
System.out.println(new ObjectMapper().writeValueAsString(mapperList));
return new ResponseDTO();
}
this is the code posting my users :
public ResponseDTO postUsers(ArrayList<User> users) {
ResponseDTO serverResponse = null;
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
connection.setRequestMethod("POST");
// prints {"users":[{"property1":"x","property1":y}]}
System.out.println(objectMapper.writeValueAsString(new MapperList(users)));
objectMapper.writeValue(connection.getOutputStream(), objectMapper.writeValueAsString(new MapperList(users)));
//blabla ...
}
and this is the object containing my list :
public class MapperList implements Serializable {
private static final long serialVersionUID = 8561295813487706798L;
private ArrayList<User> users;
public MapperList() {}
public MapperList(ArrayList<User> users) {
this.setUsers(users);
}
public ArrayList<User> getUsers() {
return users;
}
public void setUsers(ArrayList<User> users) {
this.users = users;
}
}
and this is the users type to post:
public abstract class User implements Serializable {
private static final long serialVersionUID = -1811485256250922102L;
private String property1;
private String property2;
public User() {}
public User(String prop1, String prop2) {
// set properties
}
// getters and setters
}
the problem is, when I output the value of the users's array before to post it to the controller, I got the following json value :
{"users":[{"property1":"x","property1":y}]}
but in the controller, when I print what I get from the request body, I only get :
{"users":null}
I also tryed with the annotation #RequestBody instead of #ModelAttribute("mapperList") and a JSONException is displayed :
*A JSONObject text must begin with '{' at 1 [character 2 line 1]\r\n*
My array list of users contains only one user that should be displayed. I don't understand why this doesn't work...
Thanks for any help !
You can chnage your MapperList class definition as public class MapperList extends ArrayList<User>{ ..} you dont need to define any instance variable like private ArrayList users inside MapperList class. Use #Requestbody annotation. You will be able to use MapperList as a ArrayList
Try to use:
public class MapperList{
private List<User> users;
//setter and getter
//toString
}
public class User{
private String property1;
private String property2;
//getter + setter
}
json:
{"users":[{"property1":"x", "property2":"y"}]}
in controller use #RequestBody. In that case Jackson will map your json to ArrayList of users.
#ResponseStatus(HttpStatus.OK)
#RequestMapping("/postUsers.do")
public #ResponseBody ResponseDTO postUsers(#RequestBody MapperList users) {
System.out.println(users);
return null;
}
no need to get objectMapper in that case. Don't forget to set content-type in request header to application/json. It required by Spring to handle #RequestBody processing.
If not working try to change MapperList:
List<User> users = new ArrayList<User>();
On the server side keep the #RequestBody annotation:
public #ResponseBody ResponseDTO postUsers(#RequestBody MapperList mapperList)
...
But this line causes problems:
objectMapper.writeValue(
connection.getOutputStream(),
objectMapper.writeValueAsString(new MapperList(users))
);
First it converts the object to JSON and then again uses objectMapper to JSON-encode the string into output stream. Try the following instead:
connection.getOutputStream().write(
objectMapper.writeValueAsString(new MapperList(users))
.getBytes("UTF-8")
);
or directly output to stream:
objectMapper.writeValue(
connection.getOutputStream(),
new MapperList(users))
);
Zbynek gave me part of the answer. Indeed
objectMapper.writeValue(
connection.getOutputStream(),
objectMapper.writeValueAsString(new MapperList(users))
);
doesn't work properly in my case
But moreover, my User class was an abstract class, with many type of User as subclasses. so the #RequestBody annotation couldn't work without specified the object type in the Json.
I used the following annotations on User class to make it working :
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
#JsonSubTypes({
#JsonSubTypes.Type(value = SubClassA.class, name = "a"),
#JsonSubTypes.Type(value = SubClassB.class, name = "b")
})
Thanks a lot for all your answers.

Upsert Mongo Document using spring data mongo

I have a Class
#Document
public class MyDocument {
#Id
private String id;
private String title;
private String description;
private String tagLine;
#CreatedDate
private Date createdDate;
#LastModifiedDate
private Date updatedDate;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getTagLine() {
return tagLine;
}
public void setTagLine(String tagLine) {
this.tagLine = tagLine;
}
}
i have added annotated application with #EnableMongoAuditing
i have created interface which implements mongorepository
public interface MyDocumentRepository extends MongoRepository<MyDocument, String> {
}
when i have created RestController with GET,POST,PATCH methods
in POST I'm sending
{'title':'first'}
Controller Class POST method is
#RequestMapping(value = "/", method = RequestMethod.POST)
public ResponseEntity<?> saveMyDocument(#RequestBody MyDocument myDocument) {
MyDocument doc = myDocumentRepo.save(myDocument);
return new ResponseEntity<MyDocument>(doc, HttpStatus.CREATED);
}
Its saving the data in mongo.
{
"_id" : ObjectId("56b3451f0364b03f3098f101"),
"_class" : "com.wiziq.service.course.model.MyDocument",
"title" : "test"
}
and PATCH request is like
#RequestMapping(value = "/{id}", method = RequestMethod.PATCH)
public ResponseEntity<MyDocument> updateCourse(#PathVariable(value = "id") String id,
#RequestBody MyDocument myDocument) {
myDocument.setId(id);
MyDocument doc = courseService.save(myDocument);
return ResponseEntity.ok(course);
}
when in make PATCH request with data {"description":"This is test"}
it update the docuent BUT it removes title field and createdDate form the document, its doing update which is ok. But i wanted to do an upsert, i can do its using mongoTemplate,
but there i have to set each property which i want to set.
Is there any generic way to that if i get a PATCH request i can update only not null properties.. properties which are coming in request
spring-data-rest seems to do it using #RepositoryRestResource. How can i achieve the same.
I don't want to code like this
Update update = new Update().set("title", myDocument.getTitle()).set("description", myDocument.getdescription());
Unfortunately its the behavior in MongoDB, you can verify the same using shell.
So to update create an Update Object and using
Query query = new Query(Criteria.where("id").is(ID));
Here ID is the document which you want to update.Based on your requirement set upsert after that using findAndModify update document.
mongoTemplate.findAndModify(query, update,
new FindAndModifyOptions().returnNew(true).upsert(false),
someclass.class);
If you have a model like MyModel.class and you need a smooth way to create an Update object from it there is no real clear way how to do this but you can use MongoConverter bean that is created in Spring Data Mongo auto configuration and then just use replaceOne method of MongoCollection.
#Autowired
private MongoTemplate template;
#Autowired
private MongoConverter mongoConverter;
...
#Override
public void upsertMyModel(MyModel model) {
Document documentToUpsert = new Document();
mongoConverter.write(model, documentToUpsert);
template.getCollection(collectionName).replaceOne(
Filters.eq("_id", model.getId()),
documentToUpsert,
new ReplaceOptions().upsert(true));
}
Upsert can be done in Spring data mongodb using BulkOperations.
Suppose there are two entities Entity1 and Entity2. Entity1 has foreginId which is primary id of Entity2. Both have a field title. Now, to upsert from entity2 to entity1, we can do it as follows:
Query query = new Query(Criteria.where("foreignId").is(entity2.getId()));
Update update = new Update();
update.set("title",entity2.getTitle());
List<Pair<Query, Update>> updates = new ArrayList<Pair<Query, Update>>();
updates.add(Pair.of(query, update););
BulkOperations bulkOps = this.mongoTemplate.bulkOps(BulkMode.UNORDERED, Entity1.class);
bulkOps.upsert(updates);
bulkOps.execute();

Resources