将结果集与实体映射并使用 Spring 数据进行计数的首选方式
Prefered way to map a result set with entity and count using Spring Data
经常有业务问题显示所有类别以及这些类别的使用频率。
这个问题很容易用一个查询来回答:
SELECT c.*, count(*) FROM category_assignment ca LEFT JOIN category c on ca.c_id = c.id group by c.id
我要的是您建议的基于以下内容映射结果集的方法:
@Entity
public class CategoryAssignment {
@Id
int id;
@ManyToOne(fetch = FetchType.EAGER)
private Category category;
@ManyToOne(fetch = FetchType.EAGER)
private Car car;
}
@Entity
public class Category {
@Id
String id;
TypeEnum type;
...
}
@Entity
public class Car {
@Id
int id;
String name;
...
}
从我的角度来看,映射的最佳结果是直接从存储库调用中获取一个自定义对象,其中包含作为实体的类别和作为附加变量的计数:
MappingResult result = repository.getCategoriesAndTheirCountOfType(TypeEnum type);
public class MappingResult {
Category category;
BigInteger count;
}
到目前为止,我能够实现它的唯一方法是手动映射结果集。但我希望有更简单的方法来映射它。
您可以使用Projections获取:
public interface CategoryAndCount {
Category getCategory();
Long getUsageCount();
}
public interface CategoryAssignmentRepository extends CrudRepository<CategoryAssignment, Integer> {
@Query("select c as category, count(*) as usageCount from CategoryAssignment ca join ca.category c where c.type = ?1 group by c")
CategoryAndCount getCategoriesAndTheirCountOfType(TypeEnum type);
}
不要忘记在查询中为字段添加别名(c 作为 category,count(*) 作为 usageCount)。
您可以通过以下两种方法之一将其作为类别的 属性。好处是 属性 始终可用,您无需调用任何特定查询。
- 创建数据库视图,比如 category_summary_data,然后使用辅助 table 或
@OneToOne
将其映射到类别
--
@Entity
@Table(name = "categories")
@SecondaryTable(name = "category_summary_data", pkJoinColumns = {...})
public class Category {
@Id
String id;
TypeEnum type;
@Column(name = "usage_count", table = "category_summary_data", insertable = false, updateable = false)
// do not use int
Integer usageCount;
}
- 或者,您可以使用一些提供商扩展。 Hibernate 提供了
@Formula
注释,您可以使用它来设置计算值。
--
@Entity
@Table(name = "categories")
public class Category {
@Id
String id;
TypeEnum type;
@Formula("some sql to count the records")
int usageCount;
}
经常有业务问题显示所有类别以及这些类别的使用频率。
这个问题很容易用一个查询来回答:
SELECT c.*, count(*) FROM category_assignment ca LEFT JOIN category c on ca.c_id = c.id group by c.id
我要的是您建议的基于以下内容映射结果集的方法:
@Entity
public class CategoryAssignment {
@Id
int id;
@ManyToOne(fetch = FetchType.EAGER)
private Category category;
@ManyToOne(fetch = FetchType.EAGER)
private Car car;
}
@Entity
public class Category {
@Id
String id;
TypeEnum type;
...
}
@Entity
public class Car {
@Id
int id;
String name;
...
}
从我的角度来看,映射的最佳结果是直接从存储库调用中获取一个自定义对象,其中包含作为实体的类别和作为附加变量的计数:
MappingResult result = repository.getCategoriesAndTheirCountOfType(TypeEnum type);
public class MappingResult {
Category category;
BigInteger count;
}
到目前为止,我能够实现它的唯一方法是手动映射结果集。但我希望有更简单的方法来映射它。
您可以使用Projections获取:
public interface CategoryAndCount {
Category getCategory();
Long getUsageCount();
}
public interface CategoryAssignmentRepository extends CrudRepository<CategoryAssignment, Integer> {
@Query("select c as category, count(*) as usageCount from CategoryAssignment ca join ca.category c where c.type = ?1 group by c")
CategoryAndCount getCategoriesAndTheirCountOfType(TypeEnum type);
}
不要忘记在查询中为字段添加别名(c 作为 category,count(*) 作为 usageCount)。
您可以通过以下两种方法之一将其作为类别的 属性。好处是 属性 始终可用,您无需调用任何特定查询。
- 创建数据库视图,比如 category_summary_data,然后使用辅助 table 或
@OneToOne
将其映射到类别
--
@Entity
@Table(name = "categories")
@SecondaryTable(name = "category_summary_data", pkJoinColumns = {...})
public class Category {
@Id
String id;
TypeEnum type;
@Column(name = "usage_count", table = "category_summary_data", insertable = false, updateable = false)
// do not use int
Integer usageCount;
}
- 或者,您可以使用一些提供商扩展。 Hibernate 提供了
@Formula
注释,您可以使用它来设置计算值。
--
@Entity
@Table(name = "categories")
public class Category {
@Id
String id;
TypeEnum type;
@Formula("some sql to count the records")
int usageCount;
}