Как получить только выбранные атрибуты сущности с помощью Spring JPA?

Я использую Spring Boot (1.3.3.RELEASE) и Hibernate JPA в моем проекте. Моя сущность выглядит так:

@Data
@NoArgsConstructor
@Entity
@Table(name = "rule")
public class RuleVO {

    @Id
    @GeneratedValue
    private Long id;

    @Column(name = "name", length = 128, nullable = false, unique = true)
    private String name;

    @Column(name = "tag", length = 256)
    private String tag;

    @OneToMany(mappedBy = "rule", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<RuleOutputArticleVO> outputArticles;

    @OneToMany(mappedBy = "rule", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<RuleInputArticleVO> inputArticles;
}

мой репозиторий выглядит так:

@Repository
public interface RuleRepository extends JpaRepository<RuleVO, Long> {
}

в некоторых случаях мне нужно получить только id и имя атрибуты сущности рулево. Как я могу достичь этого? Я нашел уведомление, что это должно быть выполнимо с использованием API критериев и проекций, но как? Большое спасибо заранее. Войтех!--3-->

5 ответов


обновление:

Как мне было указано, я ленив, и это очень хорошо можно сделать, поэтому я обновляю свой ответ после того, как посмотрел в интернете для правильного.

вот пример того, как получить только идентификаторы и только фамилия:

@Repository
public interface RuleRepository extends JpaRepository<RuleVO, Long> {

    @Query("SELECT r.id FROM RuleVo r where r.name = :name") 
    List<Long> findIdByName(@Param("name") String name);

    @Query("SELECT r.name FROM RuleVo r where r.id = :id") 
    String findNameById(@Param("id") Long id);
}

надеюсь, это обновление окажется полезным


Ответ:

только получение определенных атрибутов имя / id невозможно, поскольку это не так, как spring был разработан или любая база данных SQL, поскольку вы всегда выбираете строку, которая является сущностью.

что вы можете сделать, это запросить переменные в сущности, например:

@Repository
public interface RuleRepository extends JpaRepository<RuleVO, Long> {

    public RuleVo findOneByName(String name);
    public RuleVo findOneByNameOrId(String name, Long id);
    public List<RuleVo> findAllByName(String name);
    // etc, depending on what you want
}

вы можете изменить их, как вы хотите w.r.т. ваши потребности. Вы можете вызвать эти методы непосредственно через Autowired repository

см.http://docs.spring.io/spring-data/jpa/docs/current/reference/html/ раздел 5.3 дополнительные параметры и примеры


Да, вы можете достичь этого с помощью проекций. У вас есть много способов применить их:

если вы смогли модернизировать к Хопперу данных весны, то он обеспечивает легкую для использования поддержки для проекций. Смотрите, как использовать их в документация.

в противном случае, прежде всего, создайте DTO с атрибутами, которые вы хотите загрузить, что-то вроде:

package org.example;

public class RuleProjection {

    private final Long id;

    private final String name;

    public RuleProjection(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

конечно, вы также можете использовать аннотации Ломбока.

затем вы можете использовать в JPQL такие запросы:

select new org.example.RuleProjection(rule.id, rule.name) from RuleVO rule order by rule.name

другой вариант, если вы хотите избежать использования имен классов DTO в запросах, - реализовать свой собственный метод запроса с помощью QueryDSL. С весенними данными JPA вы должны:

  • создать новый интерфейс с новым методом. Ex:

    public interface RuleRepositoryCustom {
       public List<RuleProjection> findAllWithProjection();
    }
    
  • измените свой репозиторий, чтобы расширить новый интерфейс. Ex:

    public interface RuleRepository extends JpaRepository<RuleVO, Long>, RuleRepositoryCustom {
    ...
    
  • создать реализацию пользовательского репозитория использование поддержки Spring Data JPA QueryDSL. Вы должны ранее генерировать Q-классы QueryDSL, используя его плагин Maven. Ex:

    public class RuleRepositoryImpl {
    
        public List<RuleProjection> findAllWithProjection() {
            QRuleVO rule = QRuleVO.ruleVO;
            JPQLQuery query = getQueryFrom(rule);     
            query.orderBy(rule.name.asc());
            return query.list(ConstructorExpression.create(RuleProjection.class, rule.id, rule.name));
        }
    }
    

вы можете сделать это, используя аннотацию @Query(HQL).

пожалуйста, обратитесь к весенним документам ниже:

http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query

(поиск @Query в весеннем документе)


вы также можете определить пользовательский конструктор для извлечения определенных столбцов с помощью JPQL.

пример:

заменить {javaPackagePath} на полный путь пакета java класса использовать в качестве конструктора в JPQL.

public class RuleVO {
   public RuleVO(Long id, String name) {
    this.id = id;
    this.name = name;
   }
}


@Repository
public interface RuleRepository extends JpaRepository<RuleVO, Long> {

    @Query("SELECT new {javaPackagePath}.RuleVO(r.id, r.name) FROM RuleVo r where r.name = :name") 
    List<RuleVO> findIdByName(@Param("name") String name);
}

interface IdOnly{
    String getId();
}

@Repository
public interface RuleRepository extends JpaRepository<RuleVO, Long> {
    public List<IdOnly> findAllByName(String name);
}

Я заметил, что это очень старый пост, но если кто-то все еще ищет ответ, попробуйте это. У меня получилось.