Java 有什么实践或设计模式可以用来减少硬编码?

2020-05-15 10:48:09 +08:00
 LoremIpSum

C#:

_userEventData.Collection().Aggregate()
                .Match(p => p.CreateTime >= dateTimePeriod.StartTime && p.CreateTime < dateTimePeriod.EndTime)
                .SortByDescending(p => p.CreateTime)
                .Group(p => p.UserId, group => new UserDto()
                {
                    UserId = group.Key,
                    Total = group.Sum(g => g.Value)
                })
                .ToListAsync();

Java:

Aggregation agg = newAggregation(UserEvent.class,
                match(where("createTime").gte(period.getStartTime()).lte(period.getEndTime())),
                group("userId").addToSet("userId").as("userId").sum("value").as("total"),
                sort(Sort.Direction.DESC, "createTime"));
        Flux<UserDto> items = reactiveMongoTemplate.aggregate(agg, "UserEvent",
        UserDto.class);

上面两端代码,实现一模一样的功能,一段是用 c#写的,一段是用 java 写的,用 java 对象的字段名需要硬编码,用 c#则不需要,如果工程中有大量类似于上面这种查询代码,后续很难重构,java 中有没有什么方法,当字段名写错的时候就能够在编译器发现?

2524 次点击
所在节点    程序员
14 条回复
Jrue0011
2020-05-15 10:56:35 +08:00
这个得你用的 Aggregation 支持,然后使用 java8 方法引用

比如 group("userId"),如果它提供了 group(Function<? super T, ? extends K> func)这样的接口,你就可以写成 group(User::getUserId)或者 group(u -> u.userId)这样的形式
wysnylc
2020-05-15 11:31:03 +08:00
@Jrue0011 #1 完美回答
xizismile
2020-05-15 11:39:38 +08:00
java 也能写出 c#那样子啊,用流式 api 配合 lambda 表达式
yalin
2020-05-15 11:41:31 +08:00
传说中的微服务配置中心
aguesuka
2020-05-15 12:01:46 +08:00
java.util.Collectors.groupingBy
aguesuka
2020-05-15 12:24:51 +08:00
public interface UserEvent {
LocalDateTime getCreateTime();

BigDecimal getValue();

String getUserId();

static Map<String, BigDecimal> sumValue(Collection<? extends UserEvent> userEvents, LocalDateTime stateDate, LocalDateTime endDate) {
return userEvents.stream()
.filter(userEvent -> !userEvent.getCreateTime().isBefore(stateDate) &&
!userEvent.getCreateTime().isAfter(endDate))
.sorted(Comparator.comparing(UserEvent::getCreateTime).reversed())
.collect(Collectors.toMap(UserEvent::getUserId, UserEvent::getValue, BigDecimal::add));
}
}
用 stream 是这么写。
不过如果是用这样的形式生成 sql 是做不到的,因为::表达式拿不到方法的元信息
LoremIpSum
2020-05-15 16:21:26 +08:00
@Jrue0011 这个是 mongodb 的库,mongodb 貌似没有提供基于 stream api 的聚合查询接口
kaedea
2020-05-15 16:23:13 +08:00
CAP 模式了解一下
LoremIpSum
2020-05-15 16:23:25 +08:00
想请问下大佬,mongodb 有没有基于 stream api 的聚合查询接口?
Jrue0011
2020-05-15 17:18:17 +08:00
@LoremIpSum 用的应该是 Spring Data Mongodb Reactive ?看官方文档里与 QueryDSL 集成后貌似能实现 IDE 级别的检查,不过需要引入 QueryDSL 的库,需要评估下使用和维护的成本。。。

spring data mongodb#type-safe query methods
https://docs.spring.io/spring-data/mongodb/docs/3.0.0.RELEASE/reference/html/#mongodb.reactive.repositories.queries.type-safe

querydsl#quering mongodb
http://www.querydsl.com/static/querydsl/latest/reference/html/ch02s07.html
CoderGeek
2020-05-15 17:22:47 +08:00
有些新的 Query 方法类都可以的
ai277014717
2020-05-15 17:23:18 +08:00
万能 xml
Jrue0011
2020-05-15 17:35:44 +08:00
@Jrue0011 #10 没用过 mongodb 和 querydsl,不知道 querydsl 支持不支持 mongodb 的聚合。。
aguesuka
2020-06-03 12:44:09 +08:00
@aguesuka 我错了,先定义一个函数接口,继承 Serializlable 接口。然后 wirte 成 SerializedLambda 。这样就能拿到元信息了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/671923

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX