Как получить только выбранные атрибуты сущности с помощью 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);
}
Я заметил, что это очень старый пост, но если кто-то все еще ищет ответ, попробуйте это. У меня получилось.