2017-05-04 6 views
0

現在のプロジェクトの移行ツールとしてliquibaseを使用しています。なぜliquibaseは常に独自のシーケンスを使用していますか?

問題は、エンティティの自動生成IDにカスタムシーケンスを使用しようとしていますが、何か問題が発生していることです。

私は下記の似たようエンティティテーブルとカスタムシーケンスを定義しました:

<databaseChangeLog> 
<changeSet id="create_orders_table" author="I am"> 
    <createTable tableName="ORDERS"> 
     <column name="id" type="SERIAL" valueComputed="SEQ_ORDERS.NEXTVAL" valueSequenceCurrent="SEQ_ORDERS.CURRENT" valueSequenceNext="SEQ_ORDERS.NEXTVAL" defaultValueSequenceNext="SEQ_ORDERS.NEXTVAL"> 
      <constraints primaryKey="true" unique="true"/> 
     </column> 
     <column name="number" type="VARCHAR(64)"/> 
     ... 
    </createTable> 
</changeSet> 
<changeSet id="add_sequence" author="I am"> 
    <createSequence sequenceName="SEQ_ORDERS" cycle="false" minValue="1" maxValue="9223372036854775807" startValue="1" incrementBy="1"/> 
</changeSet> 
</databaseChangeLog> 

しかし、この移行が印加されたとき、私は、PostgreSQLで、次のテーブル構造を参照してください。

CREATE TABLE public.orders 
(
id integer NOT NULL DEFAULT nextval('orders_id_seq'::regclass), 
"number" character varying(64), 
... 
CONSTRAINT pk_orders PRIMARY KEY (id) 
) 
WITH (
OIDS=FALSE 
); 

まず、予測できません私のためのものはここに私のSEQ_ORDERSの代わりに自分自身orders_id_seqを書いた理由は何ですか?

次の私は、一般的なJPAコードを書いて、それが春を使用してテストだ:私が見るテストログで

@Entity(name = "ORDERS") 
public class Order { 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ORDERS_ID_GEN") 
    @SequenceGenerator(name = "ORDERS_ID_GEN", sequenceName = "SEQ_ORDERS") 
    private long id; 

    private String number; 
    //... getters,setters and other stuff 
} 

public interface OrderRepository extends JpaRepository<Order,Long> {} 

テスト

@RunWith(SpringRunner.class) 
@DataJpaTest 
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) 
@Rollback(value = false) 
public class OrderRepositoryTest { 

    @Autowired 
    private TestEntityManager testEntityManager; 

    @Autowired 
    private OrderRepository orderRepository; 


    @Test 
    public void testThatIdsOfOrdersGenerateCorrectly(){ 


     Order orderOne = new Order(); 
     orderOne.setNumber("order-n-01"); 

     Order orderTwo = new Order(); 
     orderTwo.setNumber("order-n-02"); 

     Order orderThree = new Order(); 
     orderThree.setNumber("order-n-03"); 

     testEntityManager.persist(orderOne); 
     testEntityManager.persist(orderTwo); 
     testEntityManager.persist(orderThree); 

     Assert.assertThat(orderRepository.findOne(new Long(1)),is(orderOne)); 
     Assert.assertThat(orderRepository.findOne(new Long(2)),is(orderTwo)); 
     Assert.assertThat(orderRepository.findOne(new Long(3)),is(orderThree)); 

    } 

} 

Hibernate: select nextval ('seq_orders') 
... 
java.lang.AssertionError: 
Expected: is <Order(id=50, number=order-n-01, ...> 
    but: was null 

テストがで終了した後DB私はid = 50,51,52の3つの注文を見た。

初めて、私はorders_id_seqが毎回50ずつ増分すると思った。 私がテストした後、そのままorders_id_seqを見たときに非常にあわてた(現在値= 1)が、私のSEQ_ORDERSが、私はもう一度テストを実行すると、私は、IDS 100101102

でして次の3つの注文を得た。1.

に増分されました誰かがここで何が起こっているのか教えてください。 そして、liquibaseを作る方法& postgresqlは正しいことをしていますか?

私が使用しています:PostgreSQLの9.6(org.postgresql.9.4.1212 JDBCドライバ)、LiquiBaseを3.5.3、春ブーツ1.5.2

春Bootテスト設定:

spring.jpa.hibernate.ddl-auto=none 
spring.jpa.generate-ddl=false 
spring.jpa.database=postgresql 

spring.datasource.initialize=false 
spring.datasource.username=postgres 
spring.datasource.password=******** 
spring.datasource.url=jdbc:postgresql://localhost:5432/ORDERS_TEST 
spring.datasource.driver-class-name=org.postgresql.Driver 

liquibase.change-log=classpath:/db/changelog/changelog-master.xml 

答えて

1

をあなたの場合データ型としてserialを指定してください。デフォルト値は指定しないでください。Postgres will already do that for youです。シーケンスorders_id_seqとデフォルト値はPostgresによって自動的に作成されます。serialを使用すると、ではなく、がLiquibaseによって作成されます。

したがって、何らかの理由で独自のシーケンスを使用する場合は、integerという列を指定し、nextval()を使用してdefaultValueComputedと指定します。また、テーブルを作成する前にシーケンスを作成する必要があります。

また次の値を取得するための構文は、Postgresのではなくsequence.nextvalnextval('sequence')ではありません。

<databaseChangeLog> 
<changeSet id="add_sequence" author="I am"> 
    <createSequence sequenceName="SEQ_ORDERS" cycle="false" minValue="1" maxValue="9223372036854775807" startValue="1" incrementBy="1"/> 
</changeSet> 

<changeSet id="create_orders_table" author="I am"> 
    <createTable tableName="ORDERS"> 
     <column name="id" type="integer" defaultValueComputed="nextval('seq_orders')> 
      <constraints primaryKey="true" unique="true"/> 
     </column> 
     <column name="number" type="VARCHAR(64)"/> 
     ... 
    </createTable> 
</changeSet> 
</databaseChangeLog> 
+0

うん、そのような変更履歴はPostgreSQLが私のシーケンスを使用しますが、私はとにかく50,51,52のIDを得ました。 – rvit34

+0

@ rvit34:難読化レイヤのマッピングにおそらく何か問題があります - 私はHibernateを使用しないので、それを手伝ってはいけません)。別の質問をすることもできます(SOに関する質問には、1つの質問のみを含める必要があります)。しかし、Hibernateでは何らかのキャッシュのように思えます。あるいは、 'cache =" 50 "'でシーケンスを作成したでしょうか? –

+0

PgAdminでわかるように、私のSEQ_ORDERSのキャッシュは1 – rvit34

関連する問題