如何连接多个 queryDSL 表
How to join multiple queryDSL tables
我有一些 tables,我想使用 queryDSL 连接获得结果,但没有找到任何关于使用 queryDSL 的多重连接的例子。
我有这些 table:
账户table: accountId (PK) |电邮 |密码
account_profile table: accountId (PK)(fk to account) |昵称
社区table:articleId (PK) | accountId(fk 到帐户)|标题 |内容
现在我希望JPQL下面是queryDSL代码
select r from community r join r.account.profile a where a.nickname = :nickname
我有实体元模型 - QAccount、QAccountProfile、QCommunity
此外,我必须通过分页获得结果,因此应使用 pageable
object.
调用查询
这是我尚未完成的工作。
JPAQuery</*What generic type expected?*/> query = new JPAQuery</*???*/>(entityManager);
Predicate predicate = query.from(QCommunity.community).join(/*join directly accountProfile? or account? is it QEntity or real entity?*/);
// where should I place nickname matching condition ?
...
list = (repository.findAll(predicate, pageable)).getContent();
昵称匹配条件应该放在哪里?
编辑:附加实体信息
Account.java
@Entity
@Table(name="account", uniqueConstraints={
@UniqueConstraint(columnNames="account_seq"),
@UniqueConstraint(columnNames="email")
})
@DynamicInsert
@DynamicUpdate
@Data
@EqualsAndHashCode
@ToString(includeFieldNames=true)
@RequiredArgsConstructor(staticName="of")
@NoArgsConstructor
public class Account implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="account_seq", nullable=false, unique=true)
private Integer accountId;
@Column(name="email", nullable=false, unique=true)
@NonNull
private String email;
@NonNull
private String password;
@OneToOne(cascade=CascadeType.ALL, mappedBy="account")
private AccountProfile profile;
@OneToOne(cascade=CascadeType.ALL, mappedBy="account")
private AccountSecurity security;
}
AccountProfile.java
@Entity
@Table(name="account_profile", uniqueConstraints={
@UniqueConstraint(columnNames={"account_seq"}),
@UniqueConstraint(columnNames={"nickname"})
})
@DynamicInsert
@DynamicUpdate
@Data
@EqualsAndHashCode
@ToString(includeFieldNames=true)
@RequiredArgsConstructor(staticName="of")
@NoArgsConstructor
public class AccountProfile implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="account_seq", referencedColumnName="account_seq")
private Account account;
@Column(name="nickname", nullable=false)
@NonNull
private String nickname;
}
Community.java
@Entity
@Table(name="community", uniqueConstraints = {
@UniqueConstraint(columnNames="article_seq")
})
@DynamicInsert
@DynamicUpdate
@Data
@NoArgsConstructor
@EqualsAndHashCode
@ToString(includeFieldNames=true)
public class Community {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="article_seq", nullable=false, unique=true)
private Long articleId;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="account_seq", referencedColumnName="account_seq")
private Account account;
@Column(name="title", nullable=false)
private String title;
@Column(name="content", nullable=false)
private String content;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="reg_dt")
private Date date;
@Column(name="read_cnt", nullable=false)
private int readCount;
@Column(name="attach_url")
private String attachUrl;
@Column(name="attach_filename")
private String attachFileName;
@OneToMany(cascade=CascadeType.ALL, mappedBy="article")
private Set<CommunityReply> replies;
}
编辑:问题已解决
为了帮助像我一样面临问题的其他人,我将 post 我的工作代码。该代码正在搜索具有匹配特定昵称的任何社区文章。
@PersistenceContext
private EntityManager entityManager;
private List<Community> getList(int pageNo, String keyword, int rowsOnPage){
int offset = (pageNo -1) * rowsOnPage;
int limit = rowsOnPage;
JPAQuery<Community> query = new JPAQuery<Community>(entityManager);
QCommunity qCommunity = QCommunity.community;
QAccount qAccount = QAccount.account;
QAccountProfile qAccountProfile = QAccountProfile.accountProfile;
return query
.from(qCommunity)
.innerJoin(qCommunity.account ,qAccount)
.innerJoin(qAccount.profile, qAccountProfile)
.where(qAccountProfile.nickname.like("%"+keyword+"%"))
.orderBy(qCommunity.articleId.desc())
.offset(offset)
.limit(limit)
.fetch();
}
首先,为 QueryDSL 查询声明一个自定义扩展基础存储库class。
首先是界面:
@NoRepositoryBean
public interface ExtendedQueryDslJpaRepository<T, ID extends Serializable>
extends JpaRepository<T, ID>, QueryDslPredicateExecutor<T> {
<T1> Page<T1> findAll(JPQLQuery jpqlQuery, Pageable pageable);
}
然后执行:
public class ExtendedQueryDslJpaRepositoryImpl<T, ID extends Serializable>
extends QueryDslJpaRepository<T, ID> implements ExtendedQueryDslJpaRepository<T, ID> {
private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE;
private final EntityPath<T> path;
private final PathBuilder<T> builder;
private final Querydsl querydsl;
private EntityManager entityManager;
public ExtendedQueryDslJpaRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) {
this(entityInformation, entityManager, DEFAULT_ENTITY_PATH_RESOLVER);
}
public ExtendedQueryDslJpaRepositoryImpl(JpaEntityInformation<T, ID> entityInformation,
EntityManager entityManager, EntityPathResolver resolver) {
super(entityInformation, entityManager);
this.path = resolver.createPath(entityInformation.getJavaType());
this.builder = new PathBuilder(this.path.getType(), this.path.getMetadata());
this.querydsl = new Querydsl(entityManager, this.builder);
this.entityManager = entityManager;
}
@Override
public <T1> Page<T1> findAll(JPQLQuery jpqlQuery, Pageable pageable) {
// Count query
final JPQLQuery<?> countQuery = jpqlQuery;
// Apply pagination
JPQLQuery<T1> query = querydsl.applyPagination(pageable, jpqlQuery);
// Run query
return PageableExecutionUtils.getPage(query.fetch(), pageable, countQuery::fetchCount);
}
}
将新的 class 定义为 @Configuration
class 中的基础和存储库的基础。
@Configuration
@EnableJpaRepositories(basePackageClasses = ..., repositoryBaseClass = ExtendedQueryDslJpaRepositoryImpl.class)
然后你的存储库应该从新接口扩展(当然扩展 JpaRepository):
@Repository
public interface CommunityRepository extends ExtendedQueryDslJpaRepository<Community, Long> {
}
那么,您可以试试下面的代码:
String nickname = "nick";
QAccount account = QAccount.account;
QAccountProfile accountProfile = QAccountProfile.accountProfile;
QCommunity community = QCommunity.community;
JPQLQuery query = new JPAQuery(entityManager);
BooleanBuilder predicate = new BooleanBuilder();
predicate.and(accountProfile.nickname.eq(nickname));
// select r from community r join r.account.profile a where a.nickname = :nickname
query.from(community)
.join(community.account, account)
.join(account.accountProfile, accountProfile)
.where(predicate);
repository.findAll(query, pageable);
希望对您有所帮助。
我找到了一种解决方案
QEntity qEntity1 = new QEntity("qEntity1");
QEntity qEntity2 = new QEntity("qEntity2");
所以在查询时你可以使用
new JPAQueryFactory(entityManager).from(qSampleBO)
.innerJoin(qEntity1).on(qEntity1.id.eq(qSampleBO.address.id))
.innerJoin(qEntity2).on(qEntity2.id.eq(qSampleBO.secondary_address.id))
...
我有一些 tables,我想使用 queryDSL 连接获得结果,但没有找到任何关于使用 queryDSL 的多重连接的例子。
我有这些 table:
账户table: accountId (PK) |电邮 |密码
account_profile table: accountId (PK)(fk to account) |昵称
社区table:articleId (PK) | accountId(fk 到帐户)|标题 |内容
现在我希望JPQL下面是queryDSL代码
select r from community r join r.account.profile a where a.nickname = :nickname
我有实体元模型 - QAccount、QAccountProfile、QCommunity
此外,我必须通过分页获得结果,因此应使用 pageable
object.
这是我尚未完成的工作。
JPAQuery</*What generic type expected?*/> query = new JPAQuery</*???*/>(entityManager);
Predicate predicate = query.from(QCommunity.community).join(/*join directly accountProfile? or account? is it QEntity or real entity?*/);
// where should I place nickname matching condition ?
...
list = (repository.findAll(predicate, pageable)).getContent();
昵称匹配条件应该放在哪里?
编辑:附加实体信息
Account.java
@Entity
@Table(name="account", uniqueConstraints={
@UniqueConstraint(columnNames="account_seq"),
@UniqueConstraint(columnNames="email")
})
@DynamicInsert
@DynamicUpdate
@Data
@EqualsAndHashCode
@ToString(includeFieldNames=true)
@RequiredArgsConstructor(staticName="of")
@NoArgsConstructor
public class Account implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="account_seq", nullable=false, unique=true)
private Integer accountId;
@Column(name="email", nullable=false, unique=true)
@NonNull
private String email;
@NonNull
private String password;
@OneToOne(cascade=CascadeType.ALL, mappedBy="account")
private AccountProfile profile;
@OneToOne(cascade=CascadeType.ALL, mappedBy="account")
private AccountSecurity security;
}
AccountProfile.java
@Entity
@Table(name="account_profile", uniqueConstraints={
@UniqueConstraint(columnNames={"account_seq"}),
@UniqueConstraint(columnNames={"nickname"})
})
@DynamicInsert
@DynamicUpdate
@Data
@EqualsAndHashCode
@ToString(includeFieldNames=true)
@RequiredArgsConstructor(staticName="of")
@NoArgsConstructor
public class AccountProfile implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="account_seq", referencedColumnName="account_seq")
private Account account;
@Column(name="nickname", nullable=false)
@NonNull
private String nickname;
}
Community.java
@Entity
@Table(name="community", uniqueConstraints = {
@UniqueConstraint(columnNames="article_seq")
})
@DynamicInsert
@DynamicUpdate
@Data
@NoArgsConstructor
@EqualsAndHashCode
@ToString(includeFieldNames=true)
public class Community {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="article_seq", nullable=false, unique=true)
private Long articleId;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="account_seq", referencedColumnName="account_seq")
private Account account;
@Column(name="title", nullable=false)
private String title;
@Column(name="content", nullable=false)
private String content;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="reg_dt")
private Date date;
@Column(name="read_cnt", nullable=false)
private int readCount;
@Column(name="attach_url")
private String attachUrl;
@Column(name="attach_filename")
private String attachFileName;
@OneToMany(cascade=CascadeType.ALL, mappedBy="article")
private Set<CommunityReply> replies;
}
编辑:问题已解决
为了帮助像我一样面临问题的其他人,我将 post 我的工作代码。该代码正在搜索具有匹配特定昵称的任何社区文章。
@PersistenceContext
private EntityManager entityManager;
private List<Community> getList(int pageNo, String keyword, int rowsOnPage){
int offset = (pageNo -1) * rowsOnPage;
int limit = rowsOnPage;
JPAQuery<Community> query = new JPAQuery<Community>(entityManager);
QCommunity qCommunity = QCommunity.community;
QAccount qAccount = QAccount.account;
QAccountProfile qAccountProfile = QAccountProfile.accountProfile;
return query
.from(qCommunity)
.innerJoin(qCommunity.account ,qAccount)
.innerJoin(qAccount.profile, qAccountProfile)
.where(qAccountProfile.nickname.like("%"+keyword+"%"))
.orderBy(qCommunity.articleId.desc())
.offset(offset)
.limit(limit)
.fetch();
}
首先,为 QueryDSL 查询声明一个自定义扩展基础存储库class。
首先是界面:
@NoRepositoryBean
public interface ExtendedQueryDslJpaRepository<T, ID extends Serializable>
extends JpaRepository<T, ID>, QueryDslPredicateExecutor<T> {
<T1> Page<T1> findAll(JPQLQuery jpqlQuery, Pageable pageable);
}
然后执行:
public class ExtendedQueryDslJpaRepositoryImpl<T, ID extends Serializable>
extends QueryDslJpaRepository<T, ID> implements ExtendedQueryDslJpaRepository<T, ID> {
private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE;
private final EntityPath<T> path;
private final PathBuilder<T> builder;
private final Querydsl querydsl;
private EntityManager entityManager;
public ExtendedQueryDslJpaRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) {
this(entityInformation, entityManager, DEFAULT_ENTITY_PATH_RESOLVER);
}
public ExtendedQueryDslJpaRepositoryImpl(JpaEntityInformation<T, ID> entityInformation,
EntityManager entityManager, EntityPathResolver resolver) {
super(entityInformation, entityManager);
this.path = resolver.createPath(entityInformation.getJavaType());
this.builder = new PathBuilder(this.path.getType(), this.path.getMetadata());
this.querydsl = new Querydsl(entityManager, this.builder);
this.entityManager = entityManager;
}
@Override
public <T1> Page<T1> findAll(JPQLQuery jpqlQuery, Pageable pageable) {
// Count query
final JPQLQuery<?> countQuery = jpqlQuery;
// Apply pagination
JPQLQuery<T1> query = querydsl.applyPagination(pageable, jpqlQuery);
// Run query
return PageableExecutionUtils.getPage(query.fetch(), pageable, countQuery::fetchCount);
}
}
将新的 class 定义为 @Configuration
class 中的基础和存储库的基础。
@Configuration
@EnableJpaRepositories(basePackageClasses = ..., repositoryBaseClass = ExtendedQueryDslJpaRepositoryImpl.class)
然后你的存储库应该从新接口扩展(当然扩展 JpaRepository):
@Repository
public interface CommunityRepository extends ExtendedQueryDslJpaRepository<Community, Long> {
}
那么,您可以试试下面的代码:
String nickname = "nick";
QAccount account = QAccount.account;
QAccountProfile accountProfile = QAccountProfile.accountProfile;
QCommunity community = QCommunity.community;
JPQLQuery query = new JPAQuery(entityManager);
BooleanBuilder predicate = new BooleanBuilder();
predicate.and(accountProfile.nickname.eq(nickname));
// select r from community r join r.account.profile a where a.nickname = :nickname
query.from(community)
.join(community.account, account)
.join(account.accountProfile, accountProfile)
.where(predicate);
repository.findAll(query, pageable);
希望对您有所帮助。
我找到了一种解决方案
QEntity qEntity1 = new QEntity("qEntity1");
QEntity qEntity2 = new QEntity("qEntity2");
所以在查询时你可以使用
new JPAQueryFactory(entityManager).from(qSampleBO)
.innerJoin(qEntity1).on(qEntity1.id.eq(qSampleBO.address.id))
.innerJoin(qEntity2).on(qEntity2.id.eq(qSampleBO.secondary_address.id))
...