我读到,当您有一个具有大量参数的类时,使用构建器模式很有用。我想知道如何使用构建器模式来实现一个实体。如果您可以提供示例代码,那将会很棒。如何使用构造模式用于具有JPA的实体
回答
当然,这是可能的,你只需要为每个实体提供一个(可能是嵌套的)Builder。
下面是一个工作示例:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class FluentEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String someName;
private int someNumber;
private boolean someFlag;
protected FluentEntity(){}
private FluentEntity(String someName, int someNumber, boolean someFlag) {
this.someName = someName;
this.someNumber = someNumber;
this.someFlag = someFlag;
}
public long getId() {
return id;
}
public String getSomeName() {
return someName;
}
public int getSomeNumber() {
return someNumber;
}
public boolean isSomeFlag() {
return someFlag;
}
public static FluentEntityBuilder builder() {
return new FluentEntityBuilder();
}
public static class FluentEntityBuilder {
private String someName;
private int someNumber;
private boolean someFlag;
public FluentEntityBuilder setSomeName(final String someName) {
this.someName = someName;
return this;
}
public FluentEntityBuilder setSomeNumber(final int someNumber) {
this.someNumber = someNumber;
return this;
}
public FluentEntityBuilder setSomeFlag(final boolean someFlag) {
this.someFlag = someFlag;
return this;
}
public FluentEntity build() {
return new FluentEntity(someName, someNumber, someFlag);
}
}
}
使用它会是这样的代码:
FluentEntity entity = FluentEntity.builder().setSomeName(someName).setSomeNumber(someNumber)
.setSomeFlag(someFlag).build();
请记住,你必须排除像主键自动生成的字段(这个例子的案例是id
)如果你有一些。
如果你想摆脱为每个实体创建Builder类的“样板”代码,我会推荐一个类似lombok的便利库。然后,您只需注释您的Entites即可获得Builders(甚至更多),也许需要额外的工作才能排除id字段。
你应该看看Project Lombok
尽管如此,这里是一些代码来测试这个生成器(与Spring引导和Hibernate实现)。
存储库:
import org.springframework.data.repository.CrudRepository;
import com.example.model.FluentEntity;
public interface FluentEntityRepository extends CrudRepository<FluentEntity, Long> {
}
这里有一些测试:
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan;
import java.util.stream.StreamSupport;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import com.example.model.FluentEntity;
@RunWith(SpringRunner.class)
@Transactional
@SpringBootTest
public class FluentEntityRepositoryTests {
@Autowired
private FluentEntityRepository fluentEntityRepository;
@Test
public void insertAndReceiveFluentEntityCreatedWithBuilder() {
final String someName = "name";
final int someNumber = 1;
final boolean someFlag = true;
FluentEntity entity = FluentEntity.builder().setSomeName(someName).setSomeNumber(someNumber)
.setSomeFlag(someFlag).build();
entity = fluentEntityRepository.save(entity);
assertThat("Entity did not get an generated Id!", entity.getId(), greaterThan(-1L));
assertThat("Entity name did not match!", entity.getSomeName(), is(someName));
assertThat("Entity number did not match!", entity.getSomeNumber(), is(someNumber));
assertThat("Entity flag did not match!", entity.isSomeFlag(), is(someFlag));
}
@Test
public void insertSomeAndReceiveFirst() {
fluentEntityRepository.save(FluentEntity.builder().setSomeName("A").setSomeNumber(1).setSomeFlag(true).build());
fluentEntityRepository
.save(FluentEntity.builder().setSomeName("B").setSomeNumber(2).setSomeFlag(false).build());
fluentEntityRepository.save(FluentEntity.builder().setSomeName("C").setSomeNumber(3).setSomeFlag(true).build());
final Iterable<FluentEntity> findAll = fluentEntityRepository.findAll();
assertThat("Should get some iterable!", findAll, notNullValue());
final FluentEntity fluentEntity = StreamSupport.stream(findAll.spliterator(), false).findFirst().get();
assertThat("Should get some entity!", fluentEntity, notNullValue());
}
}
JPA框架能够“自动”('@ Autowire')创建只有构建器中有setter的实体的实例吗? –
我不知道我是否得到了您的问题,但通常情况下,如果使用字段访问,则不需要使用setter。然后,JPA提供程序不会调用setter,并且构建器可能足以满足您的业务代码。请参阅“2.2持久性字段和属性”:http://download.oracle.com/otn-pub/jcp/persistence-2_1-fr-eval-spec/JavaPersistence.pdf –
好的,但我想使用的主要原因一个建造者是这样,我可以使领域“最终”。如果你使用现场访问,你不能让他们最终可以吗? –
- 1. 使用具有GWT + EJB + JPA的实体
- 2. JPA实体的默认构造
- 3. 在两个模式中重用JPA实体层次结构
- 4. 使用实体框架生成实体的构造函数
- 5. 没有使用Kotlin的JPA实体的默认构造函数,即使使用noarg插件
- 6. 使用基于模板的构造函数构造std :: function
- 7. 使用JPA删除实体
- 8. 用于JPA实体的DTO生成器
- 9. 通用实现,但是构造函数的参数取决于具体的类
- 10. 创作JPA实体具有joinColumn
- 11. 具有异构构造函数约束的C++工厂模式
- 12. 如何使用CDI注入具有参数化构造函数的类的实例(仅适用于Java EE 6)
- 13. 使用JPA实体监听坚持JPA实体
- 14. 使用映射的JPA通用实体
- 15. 如何使用构造函数创建具有Root的Dojo树
- 16. 如何构建JPA实体和JSON模型?
- 17. 构造具有多个IDENTITY PK的实体?
- 18. playframework 1.2.4如何使用罐子JPA实体已有
- 19. 如何使用构造函数Django管理的模式
- 20. 实体框架DBContexts如何构造?
- 21. 如何使用正则表达式中的Spring MVC + JPA的实体应用
- 22. JPA禁用单个实体的模式创建
- 23. 如何使用JPA的标准API构造多列“WHERE ... IN”表达式?
- 24. Room Android:实体和Pojos必须具有可用的公共构造函数
- 25. NoSuchBeanDefinitionException使用具有JPA
- 26. 如何处理许多JPA实体具有外键关系
- 27. 如何使用Caliburn Micro的IOC实例化具有构造函数参数的视图模型?
- 28. 如何删除所有JPA实体?
- 29. 如何在.NET中使用位模式构造浮点数?
- 30. JPA /如何在只读模式下获取实体?
为什么它很重要的类是实体?为什么使用构建器模式来构建任何不同的实体来使用它来构建其他任何东西? –
我希望它是一个实体,以便能够将其存储在数据库中。 –