- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想构建一个 JPQL 查询来将该结构的数据映射到这个 DTO:
@AllArgsConstructor
class UserDTO {
long userId;
long countOfContacts;
Map<String,Long> countOfActions; // by type
}
我不知道如何在 JPQL 中提取每个 Action 类型的计数,这就是我被困的地方(看到我的名字?:)):
public interface UserRepository extends CrudRepository<User, Long> {
@Query("SELECT new example.UserDTO( "
+ " u.id, "
+ " COUNT(contacts), "
--> + " ???group by actions.type to map<type,count>??? " <---
+ " ) "
+ " FROM User u "
+ " LEFT JOIN u.actions actions "
+ " LEFT JOIN u.contacts contacts "
+ " GROUP BY u.id")
List<UserDTO> getAll();
}
我使用 postgres,如果这在 JPQL 中不可能,也可以使用 native 查询。
实际上,我可以通过 native 查询并在 Java 中映射操作数据来解决它,但感觉很糟糕:
SELECT
u.id,
COALESCE(MIN(countOfContacts.count), 0) as countOfContacts,
ARRAY_TO_STRING(ARRAY_REMOVE(ARRAY_AGG(actions.type || ':' || actions.count), null),',') AS countOfActions
FROM user u
LEFT JOIN (
SELECT
user_id, COUNT(*) as count
FROM contact
GROUP BY user_id
) countOfContacts
ON countOfContacts.user_id = u.id
LEFT JOIN (
SELECT
user_id, type, COUNT(*)
FROM action
GROUP BY user_id, type
) actions
ON actions.user_id = u.id
GROUP BY u.id
;
产生这样的结果数据:
id | countOfContacts | countOfActions
--------+-----------------+-------------------------
11728 | 0 | {RESTART:2}
9550 | 0 | {}
9520 | 0 | {CLEAR:1}
12513 | 0 | {RESTART:2}
10238 | 3 | {CLEAR:2,RESTART:5}
16531 | 0 | {CLEAR:1,RESTART:7}
9542 | 0 | {}
...
由于在 native 查询中我们无法映射到 POJO,因此我返回 List<String[]>
并自己将所有列转换为 UserDTO
的构造函数:
@Query(/*...*/)
/** use getAllAsDTO for a typed result set */
List<String[]> getAll();
default List<UserDTO> getAllAsDTO() {
List<String[]> result = getAll();
List<UserDTO> transformed = new ArrayList<>(result.size());
for (String[] row : result) {
long userId = Long.parseLong(row[0]);
long countOfContacts = Long.parseLong(row[1]);
String countOfActions = row[2];
transformed.add(
new UserDTO(userId, countOfContacts, countOfActions)
);
}
return transformed;
}
然后我映射countOfActions
到 Java Map<String, Long>
在 DTO 的构造函数中:
class UserDTO {
long userId;
long countOfContacts;
Map<String,Long> countOfActions; // by type
/**
* @param user
* @param countOfContacts
* @param countOfActions {A:1,B:4,C:2,..} will not include keys for 0
*/
public UserDTO(long userId, long countOfContacts, String countOfActionsStr) {
this.userId = userId;
this.countOfContacts = countOfContacts;
this.countOfActions = new HashMap<>();
// remove curly braces
String s = countOfActionsStr.replaceAll("^\\{|\\}$", "");
if (s.length() > 0) { // exclude empty "arrays"
for (String item : s.split(",")) {
String[] tmp = item.split(":");
String action = tmp[0];
long count = Long.parseLong(tmp[1]);
countOfActions.put(action, count);
}
}
}
}
我可以在 DB 层解决它吗?
最佳答案
不幸的是JPQL没有像 string_agg 这样的聚合函数或 group_concat .所以你应该自己转换查询结果。首先,您应该像这样创建一个“普通”查询,例如:
@Query("select new example.UserPlainDto( " +
" a.user.id, " +
" count(distinct c.id), " +
" a.type, " +
" count(distinct a.id) " +
") " +
"from " +
" Action a " +
" join Contact c on c.user.id = a.user.id " +
"group by " +
" a.user.id, a.type")
List<UserPlainDto> getUserPlainDtos();
(它是 HQL - JPQL 的 Hibernate 扩展)
此查询的结果将是一个普通表,例如:
|--------|---------------|-------------|-------------|
|user_id |countact_count |action_type |action_count |
|--------|---------------|-------------|-------------|
|1 |3 |ONE |1 |
|1 |3 |TWO |2 |
|1 |3 |THREE |3 |
|2 |2 |ONE |1 |
|2 |2 |TWO |2 |
|3 |1 |ONE |1 |
|--------|---------------|-------------|-------------|
然后您应该将该结果分组到 UserDto
的集合中,像这样:
default Collection<UserDto> getReport() {
Map<Long, UserDto> result = new HashMap<>();
getUserPlainDtos().forEach(dto -> {
long userId = dto.getUserId();
long actionCount = dto.getActionCount();
UserDto userDto = result.getOrDefault(userId, new UserDto());
userDto.setUserId(userId);
userDto.setContactCount(dto.getContactCount());
userDto.getActions().compute(dto.getActionType(), (type, count) -> count != null ? count + actionCount : actionCount);
result.put(userId, userDto);
});
return result.values();
}
然后瞧,你会在Collection<UserDto>
中得到这样的结果:
[
{
"userId": 1,
"contactCount": 3,
"actions": {
"ONE": 1,
"TWO": 2,
"THREE": 3
}
},
{
"userId": 2,
"contactCount": 2,
"actions": {
"ONE": 1,
"TWO": 2
}
},
{
"userId": 3,
"contactCount": 1,
"actions": {
"ONE": 1
}
}
]
上面使用了DTO:
@Value
class UserPlainDto {
long userId;
long contactCount;
ActionType actionType;
long actionCount;
}
@Data
class UserDto {
long userId;
long contactCount;
Map<ActionType, Long> actions = new HashMap<>();
}
关于java - JPQL 按子列计算多个多对一和组计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59654606/
我有一个 ProductDescription ViewController,它从我放置在许多 ViewController 中的 ProductTable UITableView 调用。 对于 St
首先,是的,我使用的是 DistinctRootEntityResultTransformer。 我有以下(Fluent NHibernate)映射: public FirstObjectMap()
我有两个模型:Book 和 Author。每个Author有很多本书,每本书有很多作者,所以我在Author和Book之间建立了ManyToMany关系,如下所示: class Author(mode
我正在尝试映射两个具有一对一关系的类之间的关系。在互联网上查找后,似乎人们更喜欢使用多对一来映射它。 例如,有一个 Order 类和 Bill 类。比尔持有发票的 FK。 这是我为比尔绘制的 map
假设有以下实体类: public class Player { public virtual int ID { get; set; } public virtual string Name { g
我想尝试一下 dynamodb 我能够保存单个对象。现在我想尝试创建一个多对一的关联。 许多任务应附加到单个用户。 @DynamoDBTable(tableName = "User") public
所以,情况如下: 表ComputerInventory,其中包含{computerInventoryID(主键)、TagID(唯一)、名称等} 表reviewStatus,其中包含{reviewSta
我在使用 hibernate 进行多对一映射时遇到问题。我有两个表,表 A 和表 B。我在这些表之间映射了多对一关系。两个表可以一起使用,也可以单独使用。 用 Java 中的类来表示表,例如: cla
我的实体: @Entity public class Film { @Id @GeneratedValue(strategy = IDENTITY) private long film
我必须制作拼贴项目的域层。我们的标准很少,比如我们必须使用 Hibernate,而且数据库也是固定的。 数据库的相关部分看起来几乎像这样: BusEntity(表 1) 总线 ID 公交车具体信息 总
如果有这两个实体: @Entity @Table(name = "CUSTOMER") public class Customer { @Id @GeneratedValue(stra
我正在尝试找出在多对一关系中检索单个最新结果的最有效方法。 示例: 实体 A - 团队(名称)实体 B - 员工(姓名,已创建) 团队>员工 我想在 Employee 上创建一个获取请求,返回每个团队
假设我有一个MySQL表read,记录了一个userid和一个articleid,记录了用户阅读了哪些文章。我现在想列出已阅读文章 1、2 和 3 的用户。 我知道以下是不可能的,但它说明了这个想法:
我的两个实体之间存在多对一关系。现在我希望当没有更多的 child 时将 parent 移除。 我的情况: 类(class)联系人 类(class)组织 一个组织有几个联系人,每个联系人都有一个组织。
我有下表: A 和 B A 有一个复合 PK:id int,类型 string。 B 只有 A 的 PK 之一:id int。 如何使用 B 的 id 和常量 type='typeB' 定义从 A 到
我正在为我的项目使用 Hibernate 3 映射一些实体,并简单地解释说我有这样的东西: Student 实体(tstudent 表) UniversityStudent 实体(tuniversit
我有一个成员表:成员(id, name, gender, head_id) 我想要的是建立以户主(家庭成员)为基础的家庭关系。就像这样:一个成员属于一个家庭(由成员定义) 也许我可以将其拆分为 2 个
示例 父类 @OneToMany(mappedBy = "parent") private List childs; 子类 @ManyToOne(cascade = CascadeType.ALL)
我有以下化学过程数据集,由 5 个连续输入向量组成,产生 1 个输出。每个输入每分钟采样一次,而输出操作系统每 5 采样一次。 虽然我相信输出取决于之前的 5 个输入向量,但我决定为我的设计寻找 LS
我正在将我的应用程序从原则 1 转换为原则 2.4我确实从数据库自动映射,但缺少一些关系: 表:产品产品 ID、标题、价格 表:位置产品id , 产品id , 位置id , 数量 因此每个 Locat
我是一名优秀的程序员,十分优秀!