我讀到,當您有一個具有大量參數的類時,使用構建器模式很有用。我想知道如何使用構建器模式來實現一個實體。如果您可以提供示例代碼,那將會很棒。如何使用構造模式用於具有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. 在兩個模式中重用JPA實體層次結構
- 5. Builder模式,具有公共構造vaild
- 6. 使實體的構造函數私有
- 7. 如何使用JPA映射實體?
- 8. 顯式模板特用於構造
- 9. 使用實體框架生成實體的構造函數
- 10. 沒有使用Kotlin的JPA實體的默認構造函數,即使使用noarg插件
- 11. 具有模式的Arquillian實體
- 12. JPA:使用現有ID合併實體
- 13. 使用基於模板的構造函數構造std :: function
- 14. JPA實體訪問不同的模式
- 15. 使用JPA刪除實體
- 16. deveoping實體類使用JPA
- 17. 用於JPA實體的DTO生成器
- 18. 通用實現,但是構造函數的參數取決於具體的類
- 19. 創作JPA實體具有joinColumn
- 20. 如何使用約束構造Applicative實例(類似於使用ContT構造Monad實例)
- 21. 如何在具有構造函數的類上使用Unity實現DI - mvc?
- 22. 如何使用CDI注入具有參數化構造函數的類的實例(僅適用於Java EE 6)
- 23. 具有異構構造函數約束的C++工廠模式
- 24. 使用JPA實體監聽堅持JPA實體
- 25. 使用映射的JPA通用實體
- 26. 如何使用構造函數創建具有Root的Dojo樹
- 27. 如何構建JPA實體和JSON模型?
- 28. 構造具有多個IDENTITY PK的實體?
- 29. 如何使用JPA setMaxResults()(LIMIT 20)沒有實體管理器?
- 30. playframework 1.2.4如何使用罐子JPA實體已有
爲什麼它很重要的類是實體?爲什麼使用構建器模式來構建任何不同的實體來使用它來構建其他任何東西? –
我希望它是一個實體,以便能夠將其存儲在數據庫中。 –