【发布时间】:2021-04-13 19:37:01
【问题描述】:
问题
使用存储为 Long 的多个外键的贫血域对象。试图防止使用某种强类型域类型转置值。
例如给定以下产品评论类:
public class Review {
private Long id;
private Long productId;
private int rating;
private String title;
private String body;
private Long createdById;
private Date createdAt;
//...
}
我想防止自己不小心将错误的外键转移到任何 Long 的:
ReviewDto dto = // some DTO that was parsed from JSON for example
Review review = new Review();
review.productId = dto.getCreatedById(); // see transpose error here as typical type checking doesn't catch it
解决方案
继承
一个明显的解决方案是为域类型实现一个简单的类层次结构。
public class LongId {
private Long id;
//...
}
//...
public class ReviewId extends LongId {...}
public class ProductId extends LongId {...}
//...
public class Review {
private ReviewId id;
private ProductId productId;
//...
}
//...
ReviewDto dto = // some DTO that was parsed from JSON for example
Review review = new Review();
review.productId = dto.getCreatedById(); // compile error as types don't match
此解决方案的缺点是包含实际类型,因此很难将其编组到 JSON 和输入/输出数据库,需要我编写大量自定义序列化程序。
泛型
我见过的另一个解决方案是使用泛型,但增加了冗长的语法,并且仍然必须编写自定义序列化程序才能获得简单的类型。
public class LongId<T> {
private Long id;
//...
}
//...
public interface ReviewId {}
public interface ProductId {}
//...
public class Review {
private LongId<ReviewId> id;
private LongId<ProductId> productId;
//...
}
//...
ReviewDto dto = // some DTO that was parsed from JSON for example
Review review = new Review();
review.productId = dto.getCreatedById(); // compile error as types don't match
注释?
有人用 Java 注释解决了这个问题吗?涉及到什么?一旦您了解了 hello world 示例,Java 注释的文档环境就会变得稀少。我发现只提供了一个传递参考,即系统是可插拔的,我必须编写自己的 maven 插件来进行类型检查。我对此非常感兴趣,因为我不希望在其他样板文件中编写自定义序列化程序,因为这些类型只是普通的 Java 引用类型,大多数 JSON 和数据库库都大力支持。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.PARAMETER })
@TypeQualifier(applicableTo = Long.class)
public @interface ReviewId {}
//...
public class Review {
private @ReviewId Long id;
private @ProductId Long productId;
//...
}
//...
ReviewDto dto = // some DTO that was parsed from JSON for example
Review review = new Review();
review.productId = dto.getCreatedById(); // **magic** happens here so that both maven and IDE catch this at compile time
【问题讨论】:
-
注解一般用于切面编程。为什么是注释而不是强类型字段?例如,具有单个 Long 值的 ProductId 类。
-
如解决方案>问题中的继承中所述,它将需要样板文件来解析它进出 JSON 和数据库。
标签: java annotations strong-typing