【发布时间】:2020-01-20 22:22:52
【问题描述】:
我正在编写一个我希望遵循 DDD 模式的应用程序,典型的实体类如下所示:
@Entity
@Table(name = "mydomain_persons")
class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name="fullname")
private String fullName;
@OneToMany(cascade=ALL, mappedBy="item")
private Set<Item> items;
}
如您所见,由于 JPA/Hibernate 严重依赖实体类上的注释,因此我的域实体类现在受到持久性感知注释的污染。这违反了 DDD 原则,以及层的分离。它还给我带来了与 ORM 无关的属性问题,例如事件。如果我使用@Transient,它不会初始化事件列表,我必须手动执行此操作,否则会出现奇怪的错误。
我喜欢域实体是 POJO(或者我使用 Kotlin 时的 POKO),所以我不希望在实体类上有这样的注释。但是我绝对不希望使用 XML 配置,这很可怕,这也是 Spring 开发人员首先转向注解的原因。
我有哪些可用的选项?我是否应该定义一个包含此类注释的 DTO 类和一个将每个 DTO 转换为相应域实体的 Mapper 类?这是一个好习惯吗?
编辑: 我知道在 C# 中,实体框架允许使用配置类在实体类之外创建映射类,这是比 XML 地狱更好的替代方案。我不确定这种技术在 JVM 世界中是否可用,有人知道下面的代码可以用 Spring 完成吗?
public class PersonDbContext: DbContext
{
public DbSet<Person> People { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//Write Fluent API configurations here
//Property Configurations
modelBuilder.Entity<Person>().Property(p => p.id).HasColumnName("id").IsRequired();
modelBuilder.Entity<Person>().Property(p => p.name).hasColumnName("fullname").IsRequired();
modelBuilder.Entity<Person>().HasMany<Item>(p => p.items).WithOne(i => i.owner).HasForeignKey(i => i.ownerid)
}
【问题讨论】:
-
您可以查看 JDX ORM for Java。 JDX 对域模型(实体)类是非侵入性的。映射是在外部以基于简单语法的声明方式定义的。没有注释会污染您的代码。没有 XML 复杂性。免责声明:我是 JDX ORM 的架构师。
-
你找到解决办法了吗?我有完全一样的问题。我正在考虑创建一个单独的域类和单独的数据类。我认为这在我们遇到的情况下是有道理的。检查此链接:stackoverflow.com/questions/14024912/…。但是,即使我们创建了 2 个模型(域和数据模型),我仍然无法意识到如何正确连接它们。
-
@SpasojePetronijević 不幸的是,我还没有找到满意的答案。实际上,我正在考虑通过研究 Entity Framework 和 NHibernate 中的代码来自己编写这样一个库。另一种可能性是创建一个可以自动生成 XML 映射的类。令人沮丧的是,像 .NET ORM 中具有流畅 API 的映射配置类会好得多,但我们在 Spring 和 Hibernate 中没有。他们在 JVM 世界中只有注解和 XML,它的 2019 已经和 lambda 表达式从 Java 8 开始可用,来吧...
-
@LordYggdrasill 有什么消息吗?有些人说他们不应该使用 DTO,因为它很冗长......
-
@BraianSilva 不幸的是,除了使用 DTO 和编写大量样板代码或处理域实体中的注释之外,我还没有找到解决问题的方法。有一天我会写一个类似于Entity Framework的fluent mapping的库,但是在那之前……
标签: spring hibernate spring-boot orm domain-driven-design