之前按提到过Jimmer在复杂统计上的问题。这里提供一些“邪修”思路:关闭数据库合法性校验,使用视图解决

案例

现在有一个data表,里面记录了部分设备的运转记录。这个表的结构如下:

create table public.data
(
    id                  bigserial
        constraint data_pk
            primary key,
    datetime            timestamp not null,
    device_id           text      not null,
    value               numeric,
    constraint data_pk_2
        unique (datetime, device_id)
);

alter table public.data
    owner to postgres;

接下来,编写一下对应视图,查询每天每个设备的value的平均值。

 SELECT row_number() OVER (ORDER BY date) AS id, -- 这里用rowNumber作为id,在下面的实体类映射中用到
    value_avg,
    device_id,
    date
   FROM ( SELECT avg(data.value) AS value_avg,
            data.device_id,
            to_char(data.datetime, 'YYYY-MM-DD'::text) AS date
           FROM data
          GROUP BY (to_char(data.datetime, 'YYYY-MM-DD'::text)), data.device_id) unnamed_subquery

然后给这个视图命名为 data_daily_value

然后,编写对应的实体类

Entity
interface DataDailyAvg {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long

    @IdView
    val deviceId: String?

    @ManyToOne
    val device: Device?

    val date: LocalDate?

    val value: BigDecimal?
}

然后编写一个查询接口(这里接口仅仅作为示范作用):

@GetMapping("/dailyData")
    fun getData(): ApiResponse<List<DataDailyAvg>> {
        val data = sql.createQuery(DataDailyAvg::class) {
            where(table.date le LocalDate.now())
            select(table.fetchBy {
                allScalarFields()
                device {
                    allScalarFields()
                }
            })
        }.execute()
        return ApiResponse.success(data)
    }

此时如果运行,可能现下面的报错:

报错的原因是:jimmer发现,DataDailyAvg实体类的id在数据库是可为空的。但是实际上,这个视图的id实际上不会为空。因此,我们需要降低Jimmer的database-validation-mode 等级,使得其不至于妨碍项目的运行,同时也能给我们输出检查的对应结果。

解决办法是在配置文件中,设置 database-validation-mode 为WARNING。这样既能输出对应的检查结果,也能不妨碍项目运行。