使用 JPA 的域对象中的注释违反了数据库是一个细节
Annotations in domain objects with JPA violates Database is a detail
您如何看待持久性模型和领域模型的分离?我读过,您不必将持久性问题与您的业务问题混为一谈(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) 等典型方法可能在 mapper/tranformer 可能在存储库 class) 中,当你想与数据存储交互时,反之亦然,当你想从数据库中检索数据时。
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));
}
}
那么 discussion/question 是否从域模型中拆分了持久性模型?什么时候分,什么时候不分?在大多数项目中,更不用说在我见过的所有项目中,我已经看到他们在“专家总是叫卖”DataStore 是一个细节时,在领域模型中耦合了持久性模型的注释。
非常感谢。
请查看这个非常类似的问题:Are persistence annotations in domain objects a bad practice?
我认为作为工程师我们应该务实。任何最佳实践、原则或“专家建议”都应该有所帮助。他们不应该让事情变得更糟。所以我建议将它们作为指导,而不是严格的规则。例如,我通常同意“数据库是一个细节”。但我们很少更改该细节。
另一方面,注释不执行任何代码。而且耦合还不错。你的域对象可以同时是一个JPA实体,而且会很干净,很有用。顺便说一下,这 并没有违反单一职责原则 (SPR)。如果您认为可以,请查看 SOLID explanation by its author Uncle Bob
是的,这些注释是细节,应该远离干净架构的实体。
不要混淆干净架构中的名称实体和持久性框架中的 @Entity
注释。它们是不同的东西。
Bob 叔叔 a video 关于干净的架构,最后他说得很清楚,因为他说:
the entities are not instances of database tables. They are usually constructions from many database tables.
在 another video 中,他谈到了依赖注入和这些框架使用的注解。好吧,依赖注入与您要求的持久性无关,但该视频清楚地表明了 Bob 大叔对干净架构的用例或实体层中的框架注释的看法。
并且在 this video 中,他非常清楚地表明实体不应具有持久性细节。是hibernate还是JPA都无所谓
您如何看待持久性模型和领域模型的分离?我读过,您不必将持久性问题与您的业务问题混为一谈(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) 等典型方法可能在 mapper/tranformer 可能在存储库 class) 中,当你想与数据存储交互时,反之亦然,当你想从数据库中检索数据时。
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));
}
}
那么 discussion/question 是否从域模型中拆分了持久性模型?什么时候分,什么时候不分?在大多数项目中,更不用说在我见过的所有项目中,我已经看到他们在“专家总是叫卖”DataStore 是一个细节时,在领域模型中耦合了持久性模型的注释。
非常感谢。
请查看这个非常类似的问题:Are persistence annotations in domain objects a bad practice?
我认为作为工程师我们应该务实。任何最佳实践、原则或“专家建议”都应该有所帮助。他们不应该让事情变得更糟。所以我建议将它们作为指导,而不是严格的规则。例如,我通常同意“数据库是一个细节”。但我们很少更改该细节。
另一方面,注释不执行任何代码。而且耦合还不错。你的域对象可以同时是一个JPA实体,而且会很干净,很有用。顺便说一下,这 并没有违反单一职责原则 (SPR)。如果您认为可以,请查看 SOLID explanation by its author Uncle Bob
是的,这些注释是细节,应该远离干净架构的实体。
不要混淆干净架构中的名称实体和持久性框架中的 @Entity
注释。它们是不同的东西。
Bob 叔叔 a video 关于干净的架构,最后他说得很清楚,因为他说:
the entities are not instances of database tables. They are usually constructions from many database tables.
在 another video 中,他谈到了依赖注入和这些框架使用的注解。好吧,依赖注入与您要求的持久性无关,但该视频清楚地表明了 Bob 大叔对干净架构的用例或实体层中的框架注释的看法。
并且在 this video 中,他非常清楚地表明实体不应具有持久性细节。是hibernate还是JPA都无所谓