所以我试图在spring数据中进行投影查询。这是我的模型(为了不让大量的类、省略构造函数和一些注释(:
public class TutorialDAO implements Serializable {
private UUID id;
private LocalDateTime created;
private String createdBy;
private LocalDateTime lastModified;
private String lastModifiedBy;
private int version;
private boolean exclusive;
@ManyToMany(mappedBy = "tutorials", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private Set<TopicDAO> topics = new HashSet<>();
@ElementCollection(fetch = FetchType.EAGER)
private Set<SectionDAO> sections = new HashSet<>();
@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
@JoinTable(name = "tutorial_courses", joinColumns = @JoinColumn(name = "tutorial_id"), inverseJoinColumns = @JoinColumn(name = "course_id"))
private Set<CourseDAO> courses = new HashSet<>();
@OneToMany(mappedBy = "tutorial", cascade = { CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
CascadeType.REFRESH }, orphanRemoval = true, fetch = FetchType.EAGER)
@MapKey(name = "localizedId.locale")
private Map<String, LocalizableTutorial> localizations = new HashMap<>();
public class TopicDAO implements Serializable {
private UUID id;
private String topic;
@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
private Set<TutorialDAO> tutorials = new HashSet<>();
}
public class LocalizedTutorialDAO {
private UUID id;
private LocalDateTime created;
private String createdBy;
private LocalDateTime lastModified;
private String lastModifiedBy;
private int version;
private boolean exclusive;
private String name, description;
private Set<TopicDAO> topics = new HashSet<>();
private Set<SectionDAO> sections = new HashSet<>();
public LocalizedTutorialDAO(UUID id, LocalDateTime created, String createdBy, LocalDateTime lastModified,
String lastModifiedBy, int version, boolean exclusive, String name, String description,
Set<TopicDAO> topics) {
super(id, created, createdBy, lastModified, lastModifiedBy, version);
System.out.println(topics);
System.out.println();
this.name = name;
this.description = description;
this.topics = topics;
}
}
我正试图进行一个投影查询;填充";LocalizedTutorialDAO类,这意味着我想要主题关系,例如(部分也是如此,但由于它是一个类似的不提及主题(。我有这个@Query注释:
select new LocalizedTutorialDAO(t.id, t.created, t.createdBy, t.lastModified, t.lastModifiedBy, t.version, t.exclusive, (VALUE(l)).name, (VALUE(l)).description, topics) from tutorial t join t.localizations l join t.topics as topics where (VALUE(l)).name like %:name% and (KEY(l)) = :lang
更清楚地说,TutorialDAO对象具有多语言支持,并且我的查询得到";正常的";TutorialDAO中的变量以及主题和节的关系。然后它从给定的语言中获得名称和描述,例如我想看一个名称为"的教程;烹饪鱼";在葡萄牙语中——";pt";。现在,关于名称和描述的这一部分正在工作,我在没有得到主题和部分的情况下对其进行了测试,并且实体得到了正确的填充。我在这里的问题是,我尝试了本机sql和spring数据非本机查询,但我永远无法使其工作。像这样,当前的查询,它说:
org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [com.fullstack.daos.projections.LocalizedTutorialDAO]. Expected arguments are: java.util.UUID, java.time.LocalDateTime, java.lang.String, java.time.LocalDateTime, java.lang.String, int, boolean, java.lang.String, java.lang.String, com.fullstack.daos.TopicDAO [select new com.fullstack.daos.projections.LocalizedTutorialDAO(t.id, t.created, t.createdBy, t.lastModified, t.lastModifiedBy, t.version, t.exclusive, (VALUE(l)).name, (VALUE(l)).description, topics) from com.fullstack.daos.TutorialDAO t join t.localizations l join t.topics as topics where (VALUE(l)).name like :name and (KEY(l)) = :lang]
如果我尝试本机,而不是在构造函数上放topic.id,topic.topic永远不会工作,因为它说它不能将TopicDAO转换为Set。有什么方法可以告诉hibernate如何做到这一点吗?例如,spring自动生成的findById((查询工作,生成以下sql查询:
select
tutorialda0_.id as id1_33_0_,
tutorialda0_.created as created2_33_0_,
tutorialda0_.created_by as created_3_33_0_,
tutorialda0_.last_modified as last_mod4_33_0_,
tutorialda0_.last_modified_by as last_mod5_33_0_,
tutorialda0_.version as version6_33_0_,
tutorialda0_.exclusive as exclusiv7_33_0_,
localizati1_.id as id1_8_1_,
localizati1_.locale as locale2_8_1_,
localizati1_.locale as formula413_1_,
localizati1_.id as id1_8_2_,
localizati1_.locale as locale2_8_2_,
localizati1_.description as descript3_8_2_,
localizati1_.name as name4_8_2_,
sections2_.tutorial_id as tutorial1_34_3_,
sectiondao3_.id as sections2_34_3_,
sectiondao3_.id as id1_22_4_,
sectiondao3_.parent_id as parent_i2_22_4_,
children4_.parent_id as parent_i2_22_5_,
children4_.id as id1_22_5_,
children4_.id as id1_22_6_,
children4_.parent_id as parent_i2_22_6_,
topics5_.tutorials_id as tutorial2_31_7_,
topicdao6_.id as topics_i1_31_7_,
topicdao6_.id as id1_27_8_,
topicdao6_.topic as topic2_27_8_
from
tutorials tutorialda0_
left outer join
localized_tutorial localizati1_
on tutorialda0_.id=localizati1_.id
left outer join
tutorials_sections sections2_
on tutorialda0_.id=sections2_.tutorial_id
left outer join
sections sectiondao3_
on sections2_.sections_id=sectiondao3_.id
left outer join
sections children4_
on sectiondao3_.id=children4_.parent_id
left outer join
topics_tutorials topics5_
on tutorialda0_.id=topics5_.tutorials_id
left outer join
topics topicdao6_
on topics5_.topics_id=topicdao6_.id
where
tutorialda0_.id=?
这在JPQL/HQL构造函数表达式或Spring数据投影中是不可能的,因为这些概念不支持集合。
我认为这是Blaze Persistence实体视图的一个完美用例。
我创建了这个库,以便在JPA模型和自定义接口或抽象类定义模型之间进行简单的映射,比如类固醇上的Spring Data Projections。其思想是,您可以按照自己喜欢的方式定义目标结构(域模型(,并通过JPQL表达式将属性(getter(映射到实体模型。
使用Blaze Persistence实体视图,用例的DTO模型可能如下所示:
@EntityView(Tutorial.class)
public interface LocalizedTutorialDAO {
@IdMapping
UUID getId();
LocalDateTime getCreated();
String getCreatedBy();
LocalDateTime getLastModified();
String getLastModifiedBy();
int getVersion();
boolean isExclusive();
@Mapping("localizations[:lang].name")
@AttributeFilter(ContainsFilter.class)
String getName();
@Mapping("localizations[:lang].description")
String getDescription();
Set<TopicDAO> getTopics();
@EntityView(Topic.class)
interface TopicDAO {
@IdMapping
UUID getId();
String getTopic();
}
}
查询是将实体视图应用于查询的问题,最简单的是按id进行查询。
LocalizedTutorialDAO a = entityViewManager.find(entityManager, LocalizedTutorialDAO.class, id);
Spring Data集成使您可以像使用Spring Data Projections一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-数据特征
Page<LocalizedTutorialDAO> findAll(Pageable pageable, EntityViewSettingProcessor<LocalizedTutorialDAO> processor);
并像一样使用
Page<LocalizedTutorialDAO> p = repo.findAll(pageable, setting -> setting.addAttributeFilter("name", nameParameter));
最棒的是,它只会获取实际需要的状态!