Spring 数据 JPA,hql 查询在 select 请求中加入 @ManyToMany 关系
Spring data JPA, hql query joining @ManyToMany relation in select request
收入明细:
帐号 table
@Entity
@Table(name = "account_table")
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "account_seq_gen")
@SequenceGenerator(name = "account_seq_gen", sequenceName = "ACCOUNT_SEQ")
private Long id;
@ManyToMany(cascade = CascadeType.REMOVE)
@JoinTable(name = "account_calendar_relation",
joinColumns = @JoinColumn(name = "account_id"),
inverseJoinColumns = @JoinColumn(name = "calendar_id")
)
private List<Calendar> calendars = new ArrayList<>();
@ManyToOne
@JoinColumn(columnDefinition = "user_id")
private User user;
//...
}
与日历有关
@Entity
@Table(name = "calendar")
public class Calendar {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "calendar_seq_gen")
@SequenceGenerator(name = "calendar_seq_gen", sequenceName = "CALENDAR_SEQ")
private Long id;
@ManyToMany(mappedBy = "calendars")
private List<Account> accounts;
//...
}
as manyToMany.
我需要通过 userId 使用 spring 数据 JPA 存储库实现从数据库加载轻型日历集合的请求(userId帐户字段)。
我试过了:
@Query(value = "SELECT new com.nextiva.calendar.model.CalendarsCoreInfo(c.id, c.email, c.originalCalendar.id," +
" c.readOnly, c.deleted)" +
" FROM Calendar c " +
" JOIN Account a ON c.accounts IN (a)" +
" WHERE a.user.id = :userId")
Set<CalendarsCoreInfo> findCalendarsCoreInfoByUserId(@Param("userId") Long usedId);
但应用程序没有启动,出现异常:
Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.Set com.nextiva.calendar.dao.jpa.CalendarRepository.findCalendarsCoreInfoByUserId(java.lang.Long)!
我尝试应用本机查询:
@Query(value = "SELECT new com.nextiva.calendar.model.CalendarsCoreInfo(c.id, c.email, c.originalCalendar.id," +
" c.readOnly, c.deleted)" +
" FROM {h-schema}.calendar c" +
" JOIN {h-schema}.account_calendar_relation atr ON atr.calendar_id = c.id" +
" JOIN {h-schema}.account_table account ON account.id = atr.account_id" +
" WHERE account.user_id = :userId", nativeQuery = true)
Set<CalendarsCoreInfo> findCalendarsCoreInfoByUserId(@Param("userId") Long usedId);
但本机查询不支持自定义结果(CalendarsCoreInfo 在我的例子中)。
问题
据我所知,我可以使用 jdbcTemplate 或将 ManyToMany 实体映射替换为 OneToMany[=50] 来解决此问题=] 和 ManyToOne。但我希望有人知道当前结构修复的优雅解决方案 HQL only.
我的查询部分:
@NamedNativeQueries( {
@NamedNativeQuery(name = "findCalendarsCoreInfoById",
query = "SELECT c.id, c.email, c.original_id, c.read_only, c.deleted" +
" FROM {h-schema}calendar c" +
" JOIN {h-schema}account_calendar_relation atr ON atr.calendar_id = c.id" +
" JOIN {h-schema}account_table a ON a.id = atr.account_id" +
" WHERE a.user_id = ? ",
resultSetMapping = "calendarsCoreInfoMapping"
),
})
与查询的目标对象对应的映射器:
@SqlResultSetMappings( {
@SqlResultSetMapping(
name = "calendarsCoreInfoMapping",
classes = {
@ConstructorResult(
targetClass = CalendarsCoreInfo.class,
columns = {
@ColumnResult(name = "id", type = Long.class),
@ColumnResult(name = "email", type = String.class),
@ColumnResult(name = "original_id", type = String.class),
@ColumnResult(name = "read_only"),
@ColumnResult(name = "deleted")
}
)
}
),
})
我已将其放入 Calendar 实体(一些建议是因为不同 JPA 供应商的行为不同)。
为了使我的存储库正常工作,我声明了 Query 指定准备好的查询:
@Query(name = "findCalendarsCoreInfoById", nativeQuery = true)
Set<CalendarsCoreInfo> findCalendarsCoreInfoByUserId(Long userId);
请关注@Query。如果方法名称与查询名称相同,并且它被标记为 nativeQuery = true,那么在查询上映射方法是不够的(这种方式对我不起作用)。如果我也将 name = "findCalendarsCoreInfoById" 添加到 @Query 中,它是固定的。
收入明细:
帐号 table
@Entity
@Table(name = "account_table")
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "account_seq_gen")
@SequenceGenerator(name = "account_seq_gen", sequenceName = "ACCOUNT_SEQ")
private Long id;
@ManyToMany(cascade = CascadeType.REMOVE)
@JoinTable(name = "account_calendar_relation",
joinColumns = @JoinColumn(name = "account_id"),
inverseJoinColumns = @JoinColumn(name = "calendar_id")
)
private List<Calendar> calendars = new ArrayList<>();
@ManyToOne
@JoinColumn(columnDefinition = "user_id")
private User user;
//...
}
与日历有关
@Entity
@Table(name = "calendar")
public class Calendar {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "calendar_seq_gen")
@SequenceGenerator(name = "calendar_seq_gen", sequenceName = "CALENDAR_SEQ")
private Long id;
@ManyToMany(mappedBy = "calendars")
private List<Account> accounts;
//...
}
as manyToMany.
我需要通过 userId 使用 spring 数据 JPA 存储库实现从数据库加载轻型日历集合的请求(userId帐户字段)。
我试过了:
@Query(value = "SELECT new com.nextiva.calendar.model.CalendarsCoreInfo(c.id, c.email, c.originalCalendar.id," +
" c.readOnly, c.deleted)" +
" FROM Calendar c " +
" JOIN Account a ON c.accounts IN (a)" +
" WHERE a.user.id = :userId")
Set<CalendarsCoreInfo> findCalendarsCoreInfoByUserId(@Param("userId") Long usedId);
但应用程序没有启动,出现异常:
Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.Set com.nextiva.calendar.dao.jpa.CalendarRepository.findCalendarsCoreInfoByUserId(java.lang.Long)!
我尝试应用本机查询:
@Query(value = "SELECT new com.nextiva.calendar.model.CalendarsCoreInfo(c.id, c.email, c.originalCalendar.id," +
" c.readOnly, c.deleted)" +
" FROM {h-schema}.calendar c" +
" JOIN {h-schema}.account_calendar_relation atr ON atr.calendar_id = c.id" +
" JOIN {h-schema}.account_table account ON account.id = atr.account_id" +
" WHERE account.user_id = :userId", nativeQuery = true)
Set<CalendarsCoreInfo> findCalendarsCoreInfoByUserId(@Param("userId") Long usedId);
但本机查询不支持自定义结果(CalendarsCoreInfo 在我的例子中)。
问题
据我所知,我可以使用 jdbcTemplate 或将 ManyToMany 实体映射替换为 OneToMany[=50] 来解决此问题=] 和 ManyToOne。但我希望有人知道当前结构修复的优雅解决方案 HQL only.
我的查询部分:
@NamedNativeQueries( {
@NamedNativeQuery(name = "findCalendarsCoreInfoById",
query = "SELECT c.id, c.email, c.original_id, c.read_only, c.deleted" +
" FROM {h-schema}calendar c" +
" JOIN {h-schema}account_calendar_relation atr ON atr.calendar_id = c.id" +
" JOIN {h-schema}account_table a ON a.id = atr.account_id" +
" WHERE a.user_id = ? ",
resultSetMapping = "calendarsCoreInfoMapping"
),
})
与查询的目标对象对应的映射器:
@SqlResultSetMappings( {
@SqlResultSetMapping(
name = "calendarsCoreInfoMapping",
classes = {
@ConstructorResult(
targetClass = CalendarsCoreInfo.class,
columns = {
@ColumnResult(name = "id", type = Long.class),
@ColumnResult(name = "email", type = String.class),
@ColumnResult(name = "original_id", type = String.class),
@ColumnResult(name = "read_only"),
@ColumnResult(name = "deleted")
}
)
}
),
})
我已将其放入 Calendar 实体(一些建议是因为不同 JPA 供应商的行为不同)。
为了使我的存储库正常工作,我声明了 Query 指定准备好的查询:
@Query(name = "findCalendarsCoreInfoById", nativeQuery = true)
Set<CalendarsCoreInfo> findCalendarsCoreInfoByUserId(Long userId);
请关注@Query。如果方法名称与查询名称相同,并且它被标记为 nativeQuery = true,那么在查询上映射方法是不够的(这种方式对我不起作用)。如果我也将 name = "findCalendarsCoreInfoById" 添加到 @Query 中,它是固定的。