I want to transform a sql query in JPA.
SELECT status, count(*)
FROM abc
WHERE type='XXX'
GROUP BY status
I need something in a JPARepository with sql.
#Repository
public interface ABCRepository extends JpaRepository<abc, Long> {
long countByStatusAndType(final A type, final B status);
}
Is it Possible?
Firstly, create class containing parameters status and count for handling results, then create method in repository with query
#Query("SELECT status, count(*) as count FROM abc WHERE type=:type GROUP BY status")
List<CustomResultClass> countByStatus(String type);
Related
public interface UserDao {
User getUserById(Long id);
void saveUser(User user);
List<UserDto> getAllUsers();
boolean isExistUserByEmail(String email);
boolean isExistUserByUserName(String userName);
// get users by id list
List<User> getUsersByIdIn(List<Long> idList);
// get all active users
List<UserDto> getAllActiveUsers();
User getUserByEmail(String email);
void saveAllUsers(List<User> userList);
List<Object[]> getAllInstructors();
}
This my dao impl method
#Override
public List<Object[]> getAllInstructors() {
return userRepository.getAllInstructors();
}
This is the query from my repository layer
#Query(value = "select distinct u.first_name, u.last_name, u.full_name, u.id from public.user u inner join public.users_group ug on u.id = ug.user_id and ug.group_list_id=1 WHERE status=1 ORDER BY u.id DESC", nativeQuery = true)
This is the method in my controller layer
#GetMapping("/instructors")
public List<Object[]> getAllIntsructors() {
return userService.getAllInstructors();
}
Result when I call the api on postman
The result I expect is:
first_name: "Iresha"
second_name: "Vishwakala"
But I don't get the key. I only get an array of objects showing me the values.
The way you are using your Repo is not a good practice. To be honest I have never seen it before.
This would be the correct way to do it:
public interface UserRepository extends JpaRepository<UserEntity, Long> // Here the first is the Entity which will be fetched by this repo, and the second is the type of ID that this Entity has.
{
// I am supposing that your entity is UserEntity and has an ID of type Long.
// Here come the queries which must return primitives or UserEntity (list, set etc.)
// An example query would be:
#Query(value = "....", nativeQuery = true) List<UserEntity> getUsersAsYouWant();
}
The JpaRepository makes use of Java Generics (hence the <>), that is why you must supply the class the types that it has to map the DB rows/data to. If you want to return specific types/Dtos/List you may use the same Repo but with different Query building (not native but JPQL). But that would be yet another question. If you want to check more, see my answer here.
Is it possible to map the results of a Hibernate #Query like this (in a #Repository interface extending #JpaRepository):
#Query("select u.id, u.email, u.status from user u")
public SimpleUserDTO getAllUsersSimpleData();
directly to a Java object like this:
public class SimpleUserDTO {
private Long id;
private String email;
private String status;
}
What I know, is that doing something like this:
Query query = session.createQuery("select u.id, u.email, u.status from user u");
the result can be extracted to a List<Object[]>:
List<Object[]> users = (List<Object[]>) query.list();
But is it possible to map it directly to a List<SimpleUserDTO> without writing additional method that will map the values to SimpleUserDTO?
You have two options.
Option 1: Constructor Expression:
#Query("select new <insert_package_here>.SimpleUserDTO(u.id, u.email, u.status) from user u")
public List<SimpleUserDTO> getAllUsersSimpleData();
Option 2: Use Interface projection
Turn your DTO into an interface and you can use it without #Query annotation
public List<SimpleUserDTO> getAllUsersSimpleData();
Please find out more about projections and Spring Data JPA in the documentation:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections
Is there a way to return Iterable< IUser > where IUser is a projection of User entity.
Example<User> userExample = Example.of(user, userMatcher);
Iterable<User> foundUsers = userRepository.findAll(userExample, Sort.by("createdAt").descending());
Instead of sticking with spring data auto generated query and response type.
You can create your own HQL query by using #Query annotation so that you can except your custom return type.
Example :
#Query(" select user from User as user where user.userName like %:username% order by createdAt desc")
public List<User> findAllByUserName(String username);
Could some one help me how to read result set from JSON_VAL() in db2. I am having the below db2 query which am executing from CrudRepository named query from hibernate.
SELECT SYSTOOLS.BSON2JSON(data) FROM TABLE WHERE JSON_VAL(data,'column','s:25')=:value
Could some one help me how can I read the value.
My Hibernate repository class is
#Repository
public interface MyRepository extends CrudRepository<MyClass, Integer> {
#Query(value = "SELECT SYSTOOLS.BSON2JSON(data) FROM TABLE WHERE JSON_VAL(data,'column','s:25')=:value", nativeQuery = true)
com.ibm.db2.jcc.DB2Clob findById(#Param("idd") String id);
}
thanks in advance .
I have an entity, and the DAO with interface JpaRepository<MyEntity, Long>. Using EclipseLink.
I'm using the following method from the DAO:
Iterable<MyEntity> findAll(Iterable<Long> ids);
in this way:
List<Long> listOfIds = Arrays.asList(new Long[] {1,2,3});
Iterable<MyEntity> entities = dao.findAll(listOfIds);
I've got the MySQL exception:
java.sql.SQLException: Operand should contain 1 column(s)
The SQL query that is executed in the database has the following syntax:
SELECT id, creation_date, column1, column2 FROM my_entity WHERE (id IN ((1,2,3)))
The problem is in the last braces - there are too many of them. The working query is:
SELECT id, creation_date, column1, column2 FROM my_entity WHERE (id IN (1,2,3))
Any reason why the Spring Data adds these unnecessary braces? Any way to fix it?
FOUND WORKAROUND
First of all, your DAO must also implement the JpaSpecificationExecutor<MyEntity>.
Then, create a Specification-factory class like this:
public final class MyEntitySpecifications {
public static Specification<MyEntity> idsIn(final Collection<Long> ids) {
return new Specification<MyEntity>() {
#Override
public Predicate toPredicate(Root<MyEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
return root.get("id").in(ids);
}
};
}
}
and use your DAO like this:
Iterable<MyEntity> entities = dao.findAll(MyEntitySpecifications.idsIn(listOfIds));
Produced query is now as expected.