Spring Boot : Using JPA want to get the unique value from table - spring-boot

I have a table
CatID | CategoryName | scatID | subCategoryName
2 User 1 x
2 User 2 y
2 User 3 z
2 User 4 a
2 User 5 b
I am able to get all the value in JSON formate using SpringBoot.
My Requirement :
I want to get the unique CategoryName attribute but in current scenario I am getting all User coming 5 times.
I am looking for solution. Please any one can help to get over using Spring Boot JPA implementation.

You can use the Query annotation in your repository interface.
For example, below snippet code return all distinct categoryName.
Declare a simple bean class:
package com.example.test;
public class CategoryNameClass {
private String CategoryName;
public CategoryNameClass(String CategoryName) {
this.CategoryName = CategoryName;
}
public String getCategoryName() {
return CategoryName;
}
public void setCategoryName(String categoryName) {
CategoryName = categoryName;
}
}
Then use the below query:
public interface ARepo extends JpaRepository<A, String> {
#Query("SELECT DISTINCT new com.example.test.CategoryNameClass(a.categoryName) FROM A a ")
List<CategoryNameClass> findAllCategoryName();
}

Related

How to change the formatting of the output of Hibernate HQL query

I'm developing a Spring Boot application with Spring Data JPA. I'm using a custom JPQL query to group by some field and get the count. Following is my repository method.
#Query("SELECT v.status.name, count(v) as cnt FROM Pet v GROUP BY v.status.name")
List<Object[]> countByStatus();
It's working and result is obtained as follows:
[
[
"pending",
1
],
[
"available",
4
]
]
However, I would like my Rest endpoint to respond with an output which is formatted like this
{
"pending": 1,
"available": 4
}
How can I achieve this?
Basically you want to produce a JSON where its properties ("pending", "available") are dynamic and come from the SELECT v.status.name part of the query.
Create a DTO to hold the row values:
package com.example.demo;
public class ResultDTO {
private final String key;
private final Long value;
public ResultDTO(String key, Long value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public Long getValue() {
return value;
}
}
Change your query to create a new ResultDTO per row:
#Query("SELECT new com.example.demo.ResultDTO(v.status.name, count(v)) as cnt FROM Pet v GROUP BY v.status.name")
List<ResultDTO> countByStatus();
"com.example.demo" is my package, you should change it to yours.
Then from your service class or from your controller you have to convert the List<ResultDTO> to a Map<String, Long> holding all rows' keys and values.
final List<ResultDTO> repositoryResults = yourRepository.countByStatus();
final Map<String, Long> results = repositoryResults.stream().collect(Collectors.toMap(ResultDTO::getKey, ResultDTO::getValue));
Your controller should be able to transform final Map<String, Long> results to the desired JSON

Spring Boot JPA count query By Multiple Fields

Here down my code:
long contentCount = studentRepository.countBySubjectIdAndStudentTypeAndDepartmentIdIn(subjectId, studentType, departmentIds);
Repository
public interface StudentRepository extends MongoRepository<Student, String> {
long countBySubjectIdAndStudentTypeAndDepartmentIdIn(String subjectId, String studentType, List<String> departmentIds);
}
Here I have 8 records for subjectId I Passed and 8 records for studentType Passed here. But there are only 3 records for departmentIds I passed. But here this query returns 8 instead of 3.

Multiple dynamic parameters to search with Spring Boot, sometimes someparam can be empty

I am working on Angular 2 with a Spring Boot application, and I am passing some search parameters through my UI to SpringBoot RestController where I am using the CrudRepository<User, id> interface for CRUD operations and am using some methods like findByValue(), but in my app I have four search boxes, like
name, age, city, and country.
If I fill only two boxes then I would like to search for that given two parameters like Age=22, City=New York then only those people who lives in New York with age 22 should be as result if I add name also like name=James then it should search with name and age 22 and city New York.
How do I achieve this kind of functionality in my SpringBoot with a Angular 2 app?
Repository Class:
public interface UserRepository extends CrudRepository<User, Integer> {
public List<User> findAll();
public List<User> findByName(String name);
}
My Controller Code:
#CrossOrigin(origins = "http://localhost:4200", maxAge = 3600)
#RequestMapping(value = "/user/list", method=RequestMethod.POST)
public List<User> getRequestedUsers(#RequestBody User userObject) {
return userRepository.findByAllParam();
// I want to write some method here to get data with all or may be 3, 2, or 1 parameters
}
If your controller is simply returning the repository response, you're better off using Spring Data REST:
https://spring.io/guides/gs/accessing-data-rest/
Once setup, you can expose your repository endpoints directly over REST:
#RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
List<User> findByName(#Param("name") String name);
List<User> findByNameAndAge(#Param("name") String name, #Param("age") Integer age)
List<User> findByNameAndAgeAndCity(#Param("name") String name, #Param("age") Integer age, #Param("city") String city);
}
This then takes care of paging, sorting etc also.
You will end up with an API similar to:
curl -i -X POST -H "Content-Type:application/json" -d "{ \"name\" : \"...\", \"age\" : 0, \"city\" : \"...\" }" http://localhost: 4200/users
In terms of searching with optional parameters, you could manage this on the client side in JavaScript. The following solution doesn't scale but should help you get something working:
function hasValue(id) {
return document.getElementById("age").value !== ''
}
function doSearch() {
const nameHasValue = hasValue("name");
const ageHasValue = hasValue("age");
const cityHasValue = hasValue("city");
if (nameHasValue && ageHasValue && cityHasValue) {
// search by name, age and city
} else if (nameHasValue && ageHasValue) {
// search by name and age
} else if (nameHasValue && cityHasValue) {
// search by name and city
} else if (ageHasValue && cityHasValue) {
// search by age and city
} else if (nameHasValue) {
// search by name
} else if (ageHasValue) {
// search by age
} else if (cityHasValue) {
// search by city
}
}
public interface OrdersRepository extends CrudRepository<OrdersModel, Integer> {
List<OrdersModel> findAllByCityLikeAndPartLike(String city, String part);
}
And if you want searching by city = New York and part = any String:
findAllByCityLikeAndPartLike("New York", "%");
Not exactly problem like yours but I think that will be helpful.

Retrieve the record using Spring Data JPA

I'm having spring data jpa repository.I the entity contain primary key id int and ipaddress string. The table contain only 1 record at a time otherwise null.
How do i retrieve the record using JPA , if it is not found return null.
#Repository
public interface IpConfigRepository extends JpaRepository<IpConfig, Integer> {
//
IpConfig findIpConfig();
}
According to the naming convention, you should define the method with the name findById(Integer id) ( assume the Id is the primary key )
Suppose you have a class A as shown below
class A{
private int id;
private String data;
// getters and setters
}
You can now search the items by the following ways.
public interface ARepo extends JpaRepository<A,Integer>{
// get all the records from table.
List<A> findAll();
// find record by id
A findById(int id);
// find record by data
A findByData(String data);
// find by date created or updated
A findByDateCreated(Date date);
// custom query method to select only one record from table
#Query("SELECT * FROM a limit 1;")
A findRecord();
}

QueryDsl MongoDb Relation

I am trying to use Mongodb with spring-data and QueryDsl.
I have following entitys:
#QueryEntity
#Document(collection="groups")
public class GroupImpl implements Group {
private String name;
#DBref
private List<User> groupMembers;
and
#QueryEntity
#Document(collection="users")
public class UserImpl implements User{
public static final String FIRST_NAME = "firstName";
public static final String LAST_NAME = "lastName";
My Repositories are implemented like this:
public interface GroupRepository extends Repository<Group, String>,QueryDslPredicateExecutor<Group>{}
Every normal CRUD operations were running successfully.
Also operations like "getUserByEmail" etc working successfully.
Now I am trying to get all Groups of an User in a UnitTest.
#Before
public void setup(){
roles = Arrays.asList(new String[]{"admin","user","guest"});
user = new UserImpl();
user.setFirstName("Foo");
user.setLastName("Bar");
user.setShortname("fbar");
user.setEMail("foo#bar.com");
user.setRoles(roles);
user2 = new UserImpl();
user2.setFirstName("Foo");
user2.setLastName("Bar");
user2.setShortname("fbar");
user2.setEMail("foo#bar.com");
user2.setRoles(roles);
user = userRepository.save(user);
user2 = userRepository.save(user2);
group = new GroupImpl();
group.setGroupMembers(Arrays.asList(new User[]{user,user2}));
group.setName("testGroup2");
group2 = new GroupImpl();
group2.setGroupMembers(Arrays.asList(new User[]{user,user2}));
group2.setName("testGroup2");
}
#Test
public void findGroupsByUser(){
Group savedGroup = repository.save(group);
Group savedGroup2 = repository.save(group2);
Assert.assertTrue(savedGroup2.getGroupMembers().contains(user));
List<Group> foundGroup = (List<Group>)repository.findAll(QGroupImpl.groupImpl.groupMembers.contains(user));
Assert.assertNotNull(foundGroup);
Assert.assertEquals(2, foundGroup.size());
}
This test fails "expected:<2> but was:<0>"
I am confused because savedGroup2 contains the user but if I try to get all Groups with this groupmember using QueryDsl I get no result.
I already checked the database and the users are stored successfully.
I also debugged and checked if the "_id"s of the given user and the user in the database are equal.
I have no Idea whats wrong.

Resources