Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 不公开域对象属性的持久化模型到域模型映射_Java_Oop_Domain Driven Design_Persistence_Ddd Repositories - Fatal编程技术网

Java 不公开域对象属性的持久化模型到域模型映射

Java 不公开域对象属性的持久化模型到域模型映射,java,oop,domain-driven-design,persistence,ddd-repositories,Java,Oop,Domain Driven Design,Persistence,Ddd Repositories,我知道这是一个常见的问题,但我还没有找到另一个可以解决我的疑问的问题 通常,如果项目很小,我会在表示域对象的同一个对象中添加持久性注释。这允许从数据库加载实体并保持所有setter私有,确保任何实例始终处于有效状态。比如: @Entity class SomeEntity { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String attribute1;

我知道这是一个常见的问题,但我还没有找到另一个可以解决我的疑问的问题

通常,如果项目很小,我会在表示域对象的同一个对象中添加持久性注释。这允许从数据库加载实体并保持所有setter私有,确保任何实例始终处于有效状态。比如:

@Entity
class SomeEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String attribute1;
    private String attribute2;
    private String attribute3;
    // ... other attributes

    protected SomeEntity() {}

    /* Public getters */
    public Long getId() { ... }

    public String getAttribute1() { ... }

    public String getAttribute2() {  ... }

    /* Expose some behaviour */
    public void updateAttributes(String attribute1, String attribute2) { 
       /* do some validations before updating */
    }
}
/* SomeEntity without persistent info */
class SomeEntity {
    private Long id;
    private String attribute1;
    private String attribute2;
    private String attribute3;
    // ... other attributes

    protected SomeEntity() {}

    /* Public getters */
    public Long getId() { ... }

    public String getAttribute1() { ... }

    public String getAttribute2() {  ... }

    /* Expose some behaviour */
    public void updateAttributes(String attribute1, String attribute2) { 
       /* do some validations before updating */
    }
}
如果我想要一个不同的持久化模型,我的问题就会出现。然后我会有这样的想法:

@Entity
class SomeEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String attribute1;
    private String attribute2;
    private String attribute3;
    // ... other attributes

    protected SomeEntity() {}

    /* Public getters */
    public Long getId() { ... }

    public String getAttribute1() { ... }

    public String getAttribute2() {  ... }

    /* Expose some behaviour */
    public void updateAttributes(String attribute1, String attribute2) { 
       /* do some validations before updating */
    }
}
/* SomeEntity without persistent info */
class SomeEntity {
    private Long id;
    private String attribute1;
    private String attribute2;
    private String attribute3;
    // ... other attributes

    protected SomeEntity() {}

    /* Public getters */
    public Long getId() { ... }

    public String getAttribute1() { ... }

    public String getAttribute2() {  ... }

    /* Expose some behaviour */
    public void updateAttributes(String attribute1, String attribute2) { 
       /* do some validations before updating */
    }
}
和道:

@Entity
class SomeEntityDAO {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String attribute1;
    private String attribute2;
    private String attribute3;

    public SomeEntityDAO() {}

    /* All getters and setters */
}
我的问题是,如何将SomeEntityDAO映射到SomeEntity而不公开SomeEntity的属性

如果我创建一个构造函数,比如:
publicsomeentity(stringattribute1,stringattribute2,…){}
,那么任何人都可以创建一个无效的SomeEntity实例。如果我在某个实体中公开所有setter,也会发生同样的情况

我也不认为使用
updateAttributes()
构建对象是一个有效的解决方案,因为这将执行一些验证,我现在不想执行这些验证(我们信任数据库中持久化的数据)

我想保护所有的setter,这样DAO就可以扩展实体并访问setter。。。但我不确定这是否是一个好的选择


解决此问题的最佳或常用方法是什么?

域实体应该是自验证的,这意味着它应该仅根据其内部值验证自身。如果更新需要依赖于外部依赖项的验证,那么我将创建一个负责更新的更新程序类。从updater类中,可以使用规范模式(作为可注入依赖项)来实现验证

修改时使用域实体,对只读投影使用DTO。在只读模式下使用直接DTO可以提高性能和简化。这在CQRS模式中使用

class SomeEntity {
    private Long id;
    private String attribute1;
    private String attribute2;
    private String attribute3;
    // ... other attributes

    public SomeEntity() {}

    /* Public getters/setter */
    public Long getId() { ... }

    public String getAttribute1() { ... }

    public String getAttribute2() {  ... }

    public Long setId() { ... }

    public String setAttribute1() { ... }

    public String setAttribute2() {  ... }
}

//classes/interfaces named for clarity
class EntityUpdater implements IEntityUpdater {
  public EntityUpdater (ISpecification spec){
  }

  public updateEntity(SomeEntity entity){
    //assert/execute validation
  }
}

我也有同样的问题。环顾四周,我没有找到解决办法。相信我,如果它存在的话,它就藏在某个地方。当你不得不处理一个旧项目,其中ORM实体无处不在,并且域和ORM模型之间有一大步的时候,这些都没有建议你该怎么做

考虑到这一点,我推断,如果你真的想保持你的域实体的纯净(所以非get和set——后者我永远不会接受!),你必须做一些交易。因为如果不给实体一些额外的知识,就无法共享内部结构。注意,这并不意味着您必须让域实体知道ORM层,也不意味着您必须使用getter。我的结论是,域实体应该有办法将它们公开为不同的模型

总之,在你的情况下,我要做的是建立一个访问者模式。域实体EntityA将实现EntityAVisitable接口以接受EntityAVisitor或类似的内容

interface EntityAVisitable {
   accepts(EntityAVisitor visitor);
}
构建器实现访问者EntityAVisitor所需的界面

interface EntityAVisitor<T>{
    setCombinedValue1_2(String attribute1_attribute2_combinedInEntity);
    <T> build();
}
interface EntityAVisitor{
setCombinedValue1_2(字符串属性1_属性2_CombinedEntity);
build();
}
接口EntityAVisitorbuild()函数使用泛型类型T。这样,域实体就不知道EntityAVisitor的具体实现的返回类型

interface EntityAVisitor<T>{
    setCombinedValue1_2(String attribute1_attribute2_combinedInEntity);
    <T> build();
}
它完美吗?没有

完美的解决方案是摆脱ORM(实际上我会说我讨厌它们,因为使用的方式在大多数情况下都是错误的——但这是我个人的想法)

好吗?没有

由于语言限制,不允许使用好的解决方案(我想您使用Java)

它在封装域实体的真实内容方面是否很好?对


不仅如此,通过这种方式,你还可以准确地决定什么可以被曝光以及如何曝光。因此,在我看来,在保持实体的纯净和必须在座位下使用ORM之间是一个很好的选择

一些ORM允许通过字段访问设置实体值(与setter方法相反)

JPA使用@Access注释。看


我创建了一个可以使用字段访问的ORM。请参阅和测试用例org.sormula.tests.fieldaccess。

您想要一个ORM,它允许实体类没有setter或有私有setter?我是说域模型类没有公开公共setter。只暴露行为方法。吸气剂很好。ORM类可以有getter和getter。