2017-02-14 70 views
0

我在建模实体时有点矛盾。@瞬间vs装饰者

我们有一个具有6-8个实例变量的实体。其中两个实际上并没有保存在数据库中,但仅用于做一些验证或在UI中显示。因此,当我们获取实体时,我们用一些外部查找来填充。

现在,根据我的同事之一,其更好的做法是使用装饰器代替使用@Transient。我在某种程度上同意。因为它阐明了DB代表的实际模型。

但它会增加对一些案件的补充样板(如业务我可以命名实体MyEntityBO,但如果我用它的UI ......再次名称将是有点混乱。

我的问题是,什么场景它更好地使用@Transient而不是装饰器,反之亦然

+1

无论其他字段或方法。出于这个原因,您不应该直接从UI中使用实体。您应该有一个特定于视图的模型,它是专门为该视图设计的模型的表示。该视图模型属于用户界面。视图模型可以通过合成封装原始模型,但这本身不是装饰器。这是除非你的应用程序是简单的CRUD,在这种情况下只需要使用@Transient。 – plalx

+0

你可以显示示例代码来给出一个想法如何在这里添加装饰模式? –

+0

@plalx在我的情况下,它并不总是用户界面。对象也用于其他验证。组合似乎更好地处理这种情况。创建2个对象。 ObjectUI,ObjectBO。所以只有用户界面需要的吸气剂才会在那里。所以不小心,这些东西不应该被用户界面看到,但应该存在于主要实体中,例如ID /密码可以隐藏。 (再次,这里的反指向是“@IgnoreJson”:)我试图理解“@Transient”在哪些情况下仍然可行。如果像你说的应用程序只是CRUD,那么只需要“@Transient” –

回答

0

对于两者都使用实体,这不是一个好的做法:数据库映射和UI映射平。始终考虑单一责任原则。实体应该只负责数据库映射,不要再做。您应该为UI表示创建DTO图层。但在这种情况下,您应该创建转换器,这很无聊,我建议使用Mapstruct - http://mapstruct.org。 如果您必须使用@Transient,这是第一个出现错误的迹象,请记住它。祝你好运:)

@Entity 
public class User { 
    @Id 
    Long id; 
    String name; 
} 

public class UserDto{ 
    Long id; 
    String name; 
} 

public class UserConverter{ 
    public UserDto toDto(User user) { 
     if (user == null) return null; 
     UserDto dto = new UserDto(); 
     dto.setId(user.getId()); 
     dto.setName(user.getName()); 
     return dto; 
    } 

    public User toEntity(UserDto dto){...} 
} 

而且在DTO对象,你可以创建你需要某种目的

+0

问题是维护这个DTO。它创建了不必要的冗长代码。但如果我将其组合起来,它会使它更易于维护。我的疑问是关于“@Transient”,他们为什么创建一个实体只是应该映射DB结构?它有什么动机。在哪里更加可行......但我现在明白......单一责任原则。 –

+0

我不推荐使用这个包装器,你应该分离你的dao层,服务层和UI层。理想情况下,您应该从数据库获取对象,执行业务逻辑,在UI端构建需要的对象并发送它。如果你发送包装,它意味着实体是在包装对象内,这是错误的,因为你发送你的域对象到UI。它也可能导致LazyInitException,因为您的分离实体已发送到UI。您应该将完全构建的DTO对象发送到UI。其实DTO模式是如何处理LazyInitException的最好方法之一。 – idmitriev

+0

想想你的架构,你的图层应该是糟糕的耦合,并使用他们自己的数据。如果你的DTO没有任何方法,这将是完美的,它只是一个愚蠢的数据。用户界面负责处理这些数据 – idmitriev

-1

使用装饰模式的主要缺点是代码维护可能是一个问题(从我的经验) 我强烈建议你去@Transient

+0

您可以详细说明一下“代码维护”吗?你看到了哪些问题或不雅情绪在哪里产生问题? –

+0

在我们的项目中,Decarator模式有许多类似于similer的对象,因此在维护过程中它变得令人头疼。另外,如果您计划迁移(在将来),它比暂时模式更不方便。但是,如果您拥有很少的对象,不是一个问题。我自己面临的问题,所以建议。干杯 – Akshay