Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Data JPA getting a Projection from an Entity with a Query

In my application I have a Hero Entity. I also want to be able to return a list of each hero id and name. I got it working with this:

@Repository
public interface HeroEntityRepository extends JpaRepository<HeroEntity, Long> {
@Query("select s.id, s.name from HEROES s")
List<Object> getIdAndName();
}

// in controller:
@GetMapping
public List<Object> getHeroNames() {
    return heroEntityRepository.getIdAndName();
}

I tried the suggestion in another post to substitute the Object with a Interface, but then I receive a list of null values ( [{"name":null,"id":null},{"name":null,"id":null}, // etc ). The custom Interface:

public interface HeroNameAndId {

    Long getId();
    String getName();
}

When making a Entity with only id and name values I received a 'ConverterNotFoundException'. Im not sure what the right way to go is. I have it working with Object but this doesn't seem very clean.

My HeroEntity:

@Getter
@Builder
@Entity(name = "HEROES")
@AllArgsConstructor
public class HeroEntity extends HasId<Long> {

    private String name;
    private String shortName;
    private String attributeId;

    @ElementCollection private List<String> translations;

    @OneToOne(cascade = CascadeType.ALL) private HeroIconEntity icon;

    private String role;
    private String type;
    private String releaseDate;

    @OneToMany(cascade = CascadeType.ALL) private List<AbilityEntity> abilities;

    @OneToMany(cascade = CascadeType.ALL) private List<TalentEntity> talents;
}

@MappedSuperclass
public abstract class HasId<T> {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Setter
    @Getter
    private T id;
}
like image 287
Bowerick Avatar asked Jul 31 '18 08:07

Bowerick


People also ask

How do you return Dtos from native queries with Spring data JPA?

Interface-based DTO projections You first need to define an interface that defines a getter method for each attribute your projection shall contain. At runtime, Spring Data JPA then generates a class that implements that interface. you can then use that interface as the return type of a repository method.

What is a DTO projection?

A DTO projection is a Java Object that contains the column values that were fetched by a given SQL projection query. The DTO projection can be a POJO (Plain Old Java Object), a JPA Tuple , or a Java Record, and we can fetch all those DTO projection types using Spring Data JPA.

What does findById return in JPA?

Its findById method retrieves an entity by its id. The return value is Optional<T> . Optional<T> is a container object which may or may not contain a non-null value. If a value is present, isPresent returns true and get returns the value.

Can we use JPA with R2DBC?

JPA cannot deal with reactive repositories such as provided by Spring Data R2DBC. This means you will have to do more things manually when using R2DBC. There are other reactive drivers around such as for example Quarkus Reactive Postgres client (which uses Vert.


1 Answers

You must use field aliases to make @Query with projection work:

@Query("select s.id as id, s.name as name from HEROES s")

The aliases must match the names in your HeroNameAndId interface.

like image 142
Simon Martinelli Avatar answered Oct 18 '22 08:10

Simon Martinelli