Java JPA数据库的域对象中的注释是一个细节

Java JPA数据库的域对象中的注释是一个细节,java,hibernate,jpa,domain-driven-design,clean-architecture,Java,Hibernate,Jpa,Domain Driven Design,Clean Architecture,将持久性模型和域模型分开,您认为如何?我已经读到,您不必将持久性关注点与业务关注点(DDD、Clean Architecture、MartinFowler、Eric Evans等等)混为一谈。即使如此,我仍然在所有项目中看到直接用ORM注释注释的域模型,像这样的域模型与持久性机制耦合,达到了贫血模型,并且违反了其他原则 //PersistenceJPA entity @Entity @Table(name="training_cycle") class TrainingCyc

将持久性模型和域模型分开,您认为如何?我已经读到,您不必将持久性关注点与业务关注点(DDD、Clean Architecture、MartinFowler、Eric Evans等等)混为一谈。即使如此,我仍然在所有项目中看到直接用ORM注释注释的域模型,像这样的域模型与持久性机制耦合,达到了贫血模型,并且违反了其他原则

//PersistenceJPA entity
@Entity
@Table(name="training_cycle")
class TrainingCycle {
    @Id
    private Long id;
    private String name;

    @Column(name="discipline_id")
    @JoinColumn(name="discipline_id")
    private Long disciplineId; //Referencing by Id because Discipline is another Aggregate ROOT

    //EmptyConstructor, getters and setters avoided
}

//PersistenceJPA entity
@Entity
@Table(name="training_cycle")
class Discipline {
    @Id
    private Long disciplineId;
    private String name;
    //EmptyConstructor, getters and setters avoided
} 
因此,如果您想遵循干净的原则,您需要拆分域和持久性模型(如下所示),以使域模型具有业务行为(这避免了贫血模型并遵循SRP),因此您需要将域模型映射到持久性模型(使用mapToEntity(DomainModel DM)和mapToDomain等典型方法)(PersistenceModel PM)可能在映射器/转换器中(可能在repository类中),当您希望与数据存储交互时;反之亦然,当您希望从数据库检索数据时

class Discipline {
    private DisciplineId disciplineId;
    private String name;

    public Discipline(DisciplineId disciplineId, String name) {
        this.disciplineId = disciplineId;
        this.name = name
    }
}

public class TrainingCycle{
    private TrainingCycleId trainingCycleId;
    private String name;
    private DisciplineId disciplineId;

    public TrainingCycle(TrainingCyleId trainingCycleId, String name, DisciplineId disciplineId) {
        this.trainingCycleId = trainingCycleId;
        this.name = name;
        assignDiscipline(disciplineId);
    }

    public void assignDiscipline(DisciplineId aDisicplineId) {
        if(aDisicplineId == null) {
            throw new IllegalArgumenException("Discipline cannot be null")
        }
        this.disciplineId = aDisicplineId;
    }
}


@Entity
@Table(name="training_cycle")
class TrainingCycleJpa {
    @Id
    private Long id;
    private String name;

    @Column(name="discipline_id")
    @JoinColumn(name="discipline_id")
    private Long disciplineId; //Referencing by Id because Discipline is another Aggregate ROOT

    //EmptyConstructor, getters and setters avoided
}


@Entity
@Table(name="training_cycle")
class DisciplineJpa {

    @Id
    private Long disciplineId;
    private String name;
   //EmptyConstructor, getters and setters avoided
}

class TrainingCyleJpaRepository implements TrainigCycleRepository {

    public void create(TrainingCycle trainingCycle) {
        entityManager.persist(this.mapToEntity(trainingCycle)
    }

    public TrainingCycle create(TrainingCycleId trainingCycleId) {
        return this.mapToDomain(entityManager.find(TrainingCycleId));
    }
}
因此,讨论/问题是是否将持久性模型从域模型中拆分?何时拆分?在大多数项目中,更不用说在我所看到的所有项目中,作为一个例子,我看到他们在域模型中结合了持久性模型的注释,而“大师总是在叫卖”数据存储是一个细节


非常感谢。

请查看这个非常类似的问题:

我认为作为工程师,我们应该务实。任何最佳实践、原则或“大师建议”都应该有所帮助。它们不应该让事情变得更糟。因此我建议将它们视为指导,而不是严格的规则。例如,我普遍同意“数据库是一个细节”。但我们很少改变这个细节


另一方面,注释不执行任何代码。而且耦合也不是那么糟糕。您的域对象可以同时是一个JPA实体,它将非常干净和有用。顺便说一句,这不会违反单一责任原则(SPR)。如果您认为是这样,请查看

是的,这些注释是详细信息,应该远离干净体系结构的实体

不要混淆clean体系结构中的名称实体和持久性框架中的
@entity
注释。它们是不同的东西

关于清洁建筑,Bob叔叔有很多想法,最后他说得很清楚,因为他说:

实体不是数据库表的实例,它们通常是从许多数据库表中构造出来的

在中,他谈到了依赖注入和这些框架使用的注释。嗯,依赖注入与您要求的持久性无关,但这段视频清楚地说明了Bob叔叔对clean Architecture的用例或实体层中的框架注释的看法


在中,他明确指出实体不应该有持久性细节。无论是hibernate还是JPA。

注释不执行任何代码,但有一些代码可以扫描注释并执行其他代码。因此注释有效地执行代码。