Czytałem, że przydatne jest używanie wzorca budowania, gdy masz klasę z wieloma parametrami. Zastanawiam się, w jaki sposób można zaimplementować jednostkę przy użyciu wzorca budowania. Byłoby wspaniale, gdybyś mógł podać przykładowy kod.Jak używać Wzorca Builder dla podmiotów z JPA
Odpowiedz
Oczywiście jest to możliwe, wystarczy podać (prawdopodobnie zagnieżdżony) Builder dla każdej Jednostki.
Oto przykład praca:
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);
}
}
}
Kod użycie byłoby to:
FluentEntity entity = FluentEntity.builder().setSomeName(someName).setSomeNumber(someNumber)
.setSomeFlag(someFlag).build();
Wystarczy pamiętać, że trzeba wykluczyć generowanych automatycznie pól jak klucz podstawowy (w ten przykład przypadku id
), jeśli masz.
Jeśli chcesz pozbyć się kodu "boilerplate" do tworzenia klas Builder dla każdej Entity, poleciłbym bibliotekę wygody, coś w stylu lombok. Wtedy dostaniesz swoich budowniczych (a nawet więcej), po prostu dodając adnotacje do swoich Entit, może to trochę zająć dodatkową pracę, aby wykluczyć pola id.
Należy przyjrzeć Project Lombok
Niemniej jednak, jest tu jakiś kod, aby przetestować ten Builder (realizowany z wiosennym Boot i hibernacji).
Repozytorium:
import org.springframework.data.repository.CrudRepository;
import com.example.model.FluentEntity;
public interface FluentEntityRepository extends CrudRepository<FluentEntity, Long> {
}
A oto kilka testów:
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());
}
}
Czy środowisko JPA będzie w stanie "automatycznie" ('@ Autowire'?) Utworzyć wystąpienia Jednostek, które mają ustawniki tylko w programie budującym? –
Nie wiem, czy mam twoje pytanie, ale generalnie setery nie są potrzebne, jeśli używany jest dostęp do pola. Następnie dostawca JPA nie powołuje się na ustawiaczy, a budowniczowie mogą wystarczyć dla twojego kodu biznesowego. Zobacz "2.2 Trwałe pola i właściwości" w: http://download.oracle.com/otn-pub/jcp/persistence-2_1-fr-eval-spec/JavaPersistence.pdf –
OK, ale główny powód, dla którego chcę skorzystać budowniczy jest taki, że mogę tworzyć pola "ostateczne". Jeśli korzystasz z dostępu do pola, nie możesz ich ukończyć, prawda? –
- 1. Łączenie niepowiązanych podmiotów z kryteriami jpa api
- 2. Dlaczego warto używać wzorca konstruktora?
- 3. JPA: Pomysły do śledzenia ewolucji/zmian podmiotów
- 4. Jak używać czasu joda z JPA (eclipselink)?
- 5. JPA CriteriaBuilder - Jak używać operatora porównania "IN"
- 6. Jak używać wzorca strategii za pomocą C#?
- 7. Wdrożenie konwerterów dla podmiotów z Java rodzajowych
- 8. Najlepszy sposób używać LINQ do podmiotów z kolekcją własności
- 9. Czy dobrą praktyką jest wykorzystywanie podmiotów JPA jako modeli domen?
- 10. Jak używać interfejsu API JPA w JOIN
- 11. Bufory protokołów z JPA
- 12. GUI Builder dla Pythona
- 13. Jak używać JPA Enum w klauzuli WH?
- 14. Jak używać pamięci podręcznej drugiego poziomu Hibernate z JPA?
- 15. Jak używać niestandardowego typu w kolumnie JPA?
- 16. Jak używać Postgres JSONB typu danych z JPA?
- 17. Jak używać StatelessSession z wiosennymi danymi JPA i Hibernate?
- 18. GUI Builder dla Eclipse Juno
- 19. JPA EntityManager, jak to działa?
- 20. NHibernate HiLo - jedna tabela dla wszystkich podmiotów
- 21. Kiedy należy używać JCR i kiedy należy używać JPA/RDBMS?
- 22. JPA Język zapytań dla jednostki z dziedziczenia
- 23. Zbyt wiele argumentów Konstruktora dla Wzorca Wzorca Dependency Injection/Dziedziczenia
- 24. Jak kwerendy dla podmiotów przez ich wartości zbiórki
- 25. Wyraźne rok-miesiące z Linq (do podmiotów)
- 26. Kiedy używać narzędzia Eloquent (ORM) over Fluent (Query Builder)?
- 27. W ElasticSearch, czy powinienem używać wielu indeksów dla osobnych, ale powiązanych podmiotów?
- 28. Co to jest dobra strategia przekształcania podmiotów jpa w zasoby restrykcyjne
- 29. Jak korzystać z audytu w JPA/Spring-Data JPA?
- 30. Jak używać generycznych w wzorzec konstruktora
Dlaczego jest tak ważne, że klasa jest podmiotem? Dlaczego używanie wzorca budowania do budowania elementów różni się od tego, aby używać go do budowania czegokolwiek innego? –
Chcę, żeby to był byt, aby móc go przechowywać w db. –