Ho letto che è utile usare il modello di builder quando si ha una classe con molti parametri. Mi chiedo come sia possibile implementare un'entità utilizzando il modello di builder. Sarebbe bello poter fornire un codice di esempio.Come si può usare il modello di generatore per le entità con JPA
risposta
Ovviamente è possibile, devi solo fornire un Builder (possibilmente annidato) per ogni Entity.
Ecco un esempio di lavoro:
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);
}
}
}
Il codice da utilizzare sarebbe questo:
FluentEntity entity = FluentEntity.builder().setSomeName(someName).setSomeNumber(someNumber)
.setSomeFlag(someFlag).build();
Basta tenere a mente che si deve escludere i campi generati automaticamente, come la chiave primaria (in in questo esempio il id
) se ne hai.
Se si desidera eliminare il codice "boilerplate" per la creazione di classi Builder per ogni Entity, consiglierei una libreria di convenienza, qualcosa come lombok. Quindi otterrai i tuoi Costruttori (e anche di più) semplicemente annotando le tue Entità, forse costa un po 'di lavoro in più per escludere i campi ID.
Si dovrebbe dare un'occhiata a Project Lombok
Tuttavia, qui è un codice per testare questo Builder (realizzato con la Primavera Boot e Hibernate).
Il repository:
import org.springframework.data.repository.CrudRepository;
import com.example.model.FluentEntity;
public interface FluentEntityRepository extends CrudRepository<FluentEntity, Long> {
}
e qui ci sono alcune prove:
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());
}
}
Il framework JPA sarà in grado di "automaticamente" ('@ Autowire'?) Creare istanze di entità che hanno setter solo nel builder? –
Non so se ho ricevuto la tua domanda, ma in generale i setter non sono necessari se si utilizza l'accesso al campo. Quindi il provider JPA non invoca i setter ei builder potrebbero essere sufficienti per il tuo codice aziendale. Vedi "2.2 Campi e proprietà persistenti" in: http://download.oracle.com/otn-pub/jcp/persistence-2_1-fr-eval-spec/JavaPersistence.pdf –
Ok, ma il motivo principale che voglio usare un costruttore è così che posso rendere i campi 'finali'. Se usi l'accesso al campo, non puoi renderli definitivi, vero? –
- 1. Esposizione di entità JPA tramite il servizio
- 2. Che gestore delle transazioni devo usare per il modello JBDC Quando si usa JPA?
- 3. Come si può usare XCTAssertNil con le strutture opzionali?
- 4. JPA cascata persistenza con entità chiavi ElementCollection
- 5. Errore Bypass "Entità non trovata" con JPA
- 6. JPA con JTA: persist entità e unire entità figlio cascata
- 7. JPA entità senza id
- 8. Conversione entità a DTO con JPA
- 9. Come rilevare automaticamente le entità in JPA 2.0
- 10. JPA nativo di query per entità con l'ereditarietà
- 11. C'è un modo per usare il middleware Mongoose con il generatore di query?
- 12. JPA Mappa w/Entità chiave e valore di entità
- 13. Si può usare Clutter con Python 3?
- 14. JBoss6 JPA: entità con @Lob genera GenericJDBCException
- 15. Come lavorare con le interfacce e JPA
- 16. Come implementare entità polimorfiche JPA con relazioni generiche
- 17. JPA @Version: come si usa?
- 18. Entità JPA con un attributo di interfaccia, è possibile?
- 19. Monitoraggio cronologia con JPA
- 20. Problema con il programma di caricamento di massa di Google App Engine quando si utilizza la configurazione con generatore automatico yaml e le entità con ID numerico
- 21. JPA e visualizzazioni tabella. Può essere fatto?
- 22. non può persistere entità JPA in App Engine
- 23. JPA entità per una tabella senza chiave primaria
- 24. Entità JPA: specificare l'unità di persistenza?
- 25. JPA - Problema di progettazione di entità
- 26. approccio migliore per il collegamento di diversi tipi di entità in JPA
- 27. Come usare generatore di query con colonna e groupBy
- 28. Come si può usare il modulo di registrazione in python con il modulo unittest?
- 29. Come ottenere la chiave primaria di qualsiasi entità JPA?
- 30. come salvare entità chiave esterna in JPA
Perché è importante che la classe è un'entità? Perché utilizzare il modello di builder per creare entità diverse per utilizzarlo per costruire qualcos'altro? –
Voglio che sia un'entità, per poterla archiviare in db. –