【发布时间】:2017-12-01 03:17:44
【问题描述】:
我有一个项目有很多相互依赖的部分:
myProject
- core
- core_web (depends on core)
- app1_core (depends on core)
- app1_web (depends on app1_core and core_web)
- app2_core (depends on core)
- app2_web (depends on app2_core and core_web)
我在 core 和 core_web 中定义了典型的 MVC 部分:服务、控制器、存储库、JPA 实体等。
app1 项目按原样使用所有这些核心内容——除了一些使用 application.properties 的特定配置外,我将能够使用一些 @Configuration 魔法来解决。
但是,app2 项目将Date 字段和List 字段添加到实体。加法的影响无处不在:DTO、工厂、控制器、服务等变成了混乱的继承混乱,从设计的角度来看只是感觉很恶心。有没有更好、更干、更符合最佳实践的方法来处理这个问题,还是我只需要从我的核心代码中继承几乎每个类,只是为了向一个实体添加几个字段?
作为一个简单的例子(这里使用Lombok 是为了简洁和令人敬畏),这是来自core 的@Entity:
package com.example.core;
@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "ACCOUNT")
@ToString(of = {"id", "emailAddress", "name"})
@EqualsAndHashCode
public class Account implements Serializable {
private static final long serialVersionUID = 1L;
@Embedded
private Address address;
@Id
@GenericGenerator(
name = "SEQ_ACCOUNT_ID",
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
@Parameter(name = "sequence_name", value = "SEQ_ACCOUNT_ID"),
@Parameter(name = "initial_value", value = "1"),
@Parameter(name = "increment_size", value = "1")
}
)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ACCOUNT_ID")
@Column(name = "ACCOUNT_ID", updatable = false, nullable = false, unique = true)
private Long id;
@Column(name = "EMAIL", nullable = false, length = 200, unique = true)
private String emailAddress;
public void setEmailAddress(String emailAddress) {
this.emailAddress = StringUtils.lowerCase(emailAddress);
}
@JsonIgnore
@Column(name = "PASSWORD_HASH", nullable = false, length = 256)
private String passwordHash;
@Column(name = "NAME", nullable = false, length = 200)
private String name;
@Column(name = "PHONE", nullable = false, length = 30)
private String phoneNumber;
@Column(name = "URL")
private String url;
}
现在我在app2 中添加额外的字段
package com.example.app2;
@Data
@NoArgsConstructor
@Table(name = "ACCOUNT")
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class Bride extends Account {
@Column(name = "WEDDING_DATE")
private Date weddingDate;
}
我预计会有这么多的工作。它体面、优雅、不重复,只要我告诉 Spring 不要扫描两个类中的实体,一切都很好。当我开始添加服务代码时,它开始变得乏味,例如:
package com.example.core;
@Service
public class AccountService {
private AccountRepository accountRepository;
@Autowired
public AccountService(AccountRepository accountRepository) {
this.accountRepository = accountRepository;
}
/* the command object here would mirror Account, but contain some code
* to handle input validation and the like. I know I could just use the
* entity class, but I've been bitten by using entity classes as DTOs or
* command objects before, so I'd like to keep them separate.
*/
public Account createAccount(CreateAccountCommand createAccountCommand) {
Account account = new Account();
account.setEmailAddress(createAccountCommand.getEmailAddress());
account.setPasswordHash(createPasswordHash(createAccountCommand.getPassword()));
account.setName(createAccountCommand.getName());
account.setPhoneNumber(createAccountCommand.getPhoneNumber());
account.setUrl(createAccountCommand.getUrl());
}
}
现在的主要问题是:(阅读:应该)我如何处理Bride 中的额外字段?创建一个名为BrideService 的新类,它扩展AccountService 并调用super.createAccount()?那么我现在也需要一个包含额外字段的命令对象吗?然后验证器需要处理额外的字段,所以我继承自AccountValidator 类?正如你所看到的,我得到了这种混乱的、继承的类的滑坡,这些类只用于将一个或两个字段的逻辑添加到所有应该能够在某些时候通用处理它们的类的目的。我的意思是,这就是多态性的目的,对吧?这样我就可以在所有地方和服务等地方使用Account。“只是工作?”在这个纠结的混乱中,适配器模式是否可以工作?提前感谢您的任何建议。
【问题讨论】:
标签: java spring spring-mvc inheritance spring-boot