Search code examples
mysqlspringspring-bootspring-data-jpaentity

Spring boot, execute custom query


Im newbie to web development,and I did some examples like get data from mysql db and show them in a jsp pages.(use CRUDRepository ) but in that way we can only show only one table data. what should we do if we want to show combine two table data.

I found these while um searching,simply I m asking how we put a more complicated sql query to this.

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.lastname like ?1%")
  List<User> findByAndSort(String lastname, Sort sort);

  @Query("select u.id, LENGTH(u.firstname) as fn_len from User u where u.lastname like ?1%")
  List<Object[]> findByAsArrayAndSort(String lastname, Sort sort);
}

if we can put that complicated query (like three tables or more) here, should we create a new entity class according to query coloumns ?? then again is that work because actually there isn't any table like that.


Solution

  • To get more complex data from DB you can use projections, for example:

    public interface UserProjection {
        Long getId();
        Long getFirstNameLen();
    }
    
    @Query("select u.id as id, LENGTH(u.firstName) as firstNameLen from User u where u.lastname like ?1%")
    List<UserProjection> getProjections(String lastName, Sort sort);
    

    Note that you should use aliases in the query that must match with getters in the projection (... as firstNameLen -> getFirstNameLen())

    The same way you can get data from several (joined) entities.

    If you have an entity with some associations, for example:

    @Entity
    public class User {
        //...
        @OneToMany
        private List<Role> roles;
    }
    

    then you can use repository method to get the users and their roles data even without any projection, just for the main entity (User). Then Spring does the rest of the work itself:

    @EntityGraph(attributePaths = "roles")
    List<User> findByFirstNameContainingIgnoreCase(String firstName);
    

    or the same with query:

    @Query("select distinct u from User u left join fetch u.roles where upper(p.firstName) like concat('%', upper(?1), '%')")
    List<User> findWithQuery(String firstName);
    

    In this case all users will have their lists of roles are filled with data from the roles table.

    (Note to use distinct in the query to prevent the result from duplicated records, more info see here.)


    Useful resources:

    Spring Data JPA - Reference Documentation

    SpEL support in Spring Data JPA @Query definitions

    Hibernate ORM User Guide

    JPQL Language Reference