解决方法
当然这是可能的,你只需要为每个实体提供一个(可能是嵌套的)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
不过,这里有一些代码来测试这个Builder(使用Spring Boot和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()); } }