2011-11-13 26 views
12

Tôi đọc rằng nó hữu ích khi sử dụng mẫu trình xây dựng khi bạn có một lớp với nhiều tham số. Tôi tự hỏi làm thế nào bạn có thể thực hiện một thực thể bằng cách sử dụng mô hình xây dựng. Nó sẽ là tuyệt vời nếu bạn có thể cung cấp mã mẫu.Làm thế nào để bạn có thể sử dụng Pattern Builder cho các đối tượng có JPA

+2

Tại sao nó quan trọng rằng lớp là một tổ chức? Tại sao lại sử dụng mẫu builder để xây dựng các thực thể khác nhau để sử dụng nó để xây dựng bất cứ thứ gì khác? –

+0

Tôi muốn nó là một thực thể, để có thể lưu trữ nó trong db. –

Trả lời

5

Tất nhiên là có thể, bạn chỉ cần cung cấp Trình tạo (có thể lồng nhau) cho mọi Thực thể.

Dưới đây là một ví dụ làm việc:

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); 
     } 

    } 

} 

Các mã để sử dụng nó sẽ là thế này:

FluentEntity entity = FluentEntity.builder().setSomeName(someName).setSomeNumber(someNumber) 
       .setSomeFlag(someFlag).build(); 

Chỉ cần ghi nhớ rằng bạn phải loại trừ lĩnh vực autogenerated như khóa chính (trong ví dụ này là id) nếu bạn có.

Nếu bạn muốn loại bỏ mã "bản mẫu" để tạo lớp Trình tạo cho mỗi Thực thể, tôi khuyên bạn nên sử dụng thư viện tiện lợi, chẳng hạn như lombok. Sau đó, bạn sẽ nhận được các nhà xây dựng của bạn (và thậm chí nhiều hơn) bằng cách chỉ chú thích các Entites của bạn, có lẽ nó chi phí thêm một chút công việc để loại trừ các lĩnh vực id.

Bạn nên có một cái nhìn tại Project Lombok

Tuy nhiên, đây là một số mã để kiểm tra Builder này (thực hiện với mùa xuân Boot và Hibernate).

Các kho:

import org.springframework.data.repository.CrudRepository; 

import com.example.model.FluentEntity; 

public interface FluentEntityRepository extends CrudRepository<FluentEntity, Long> { 

} 

Và đây là một số xét nghiệm:

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()); 
    } 

} 
+0

Khung công tác JPA sẽ có thể "tự động" ('@ Autowire'?) Tạo ra các cá thể của các thực thể có các bộ định cư chỉ trong trình xây dựng không? –

+1

Tôi không biết nếu tôi có câu hỏi của bạn, nhưng nói chung những người định cư không cần thiết nếu truy cập trường được sử dụng. Sau đó, nhà cung cấp JPA không gọi những người định cư và các nhà xây dựng có thể đủ cho mã doanh nghiệp của bạn. Xem "2.2 Trường liên tục và thuộc tính" trong: http://download.oracle.com/otn-pub/jcp/persistence-2_1-fr-eval-spec/JavaPersistence.pdf –

+0

Ok, nhưng lý do chính tôi muốn sử dụng người xây dựng là để tôi có thể tạo trường 'final'. Nếu bạn sử dụng truy cập trường, bạn không thể làm cho họ cuối cùng có thể bạn? –

Các vấn đề liên quan