it-roy-ru.com

Как получить только выбранные атрибуты объекта, используя 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 и name атрибуты сущности RuleVO. Как мне этого добиться? Я нашел уведомление, что это должно быть выполнимо, используя API Критерии и Прогнозы, но как? Спасибо заранее. Войтех

9
Vojtech

Обновление:

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

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

@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);
}

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


Старый ответ:

Только получение определенных атрибутов name/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
}

Вы можете изменить их так, как вы хотите. твои нужды. Вы можете вызывать эти методы напрямую через хранилище с автоматическим подключением

См. http://docs.spring.io/spring-data/jpa/docs/current/reference/html/ Раздел 5.3 для дополнительных опций и примеров.

10
Roel Strolenberg

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

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

В противном случае сначала создайте 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;
    }
}

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

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

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

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

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

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

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

    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));
        }
    }
    
3
Cèsar

Вы можете сделать это с помощью аннотации @Query (HQL).

Пожалуйста, обратитесь к документации Spring ниже:

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

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

2
shankarsh15

Вы также можете определить пользовательский конструктор для извлечения определенных столбцов, используя 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);
}
1
Abhilekh Singh
interface IdOnly{
    String getId();
}

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

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

0
Pranjal Gore