我正在使用liquibase作爲我當前項目的遷移工具。爲什麼liquibase總是使用自己的序列?
問題是,我試圖使用自定義序列爲實體的自動生成ids但發生了錯誤。
我定義一個實體表和定製序列如下類似:
<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
);
首先不可預知的對我來說這裏的事情是爲什麼liquibase寫了自己的orders_id_seq
而不是我的SEQ_ORDERS
?
接下來,我寫了一個典型的JPA代碼和它的測試中使用Spring:
@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
我第一次以爲orders_id_seq
每次增加值50。 我很surpised,當我測試後看到未修改orders_id_seq
(當前值= 1),但我SEQ_ORDERS被遞增1
當我再次運行測試我得到了未來三年的訂單與IDS 100101102
莫非有人向我解釋這到底是怎麼回事? 和如何使液化石蠟& postgresql做正確的事情?
我使用:在PostgreSQL 9.6(org.postgresql.9.4.1212 JDBC驅動程序),Liquibase 3.5.3,春天引導1.5.2
春季啓動測試配置:
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
是啊,這樣的changelog讓PostgreSQL的用我的序列,但我得到了50,51,52 IDS反正。 – rvit34
@ rvit34:可能是你的模糊層中的映射有問題 - 我不使用Hibernate,所以我無法幫助你)。你可能想爲此提出一個單獨的問題(關於SO的問題應該只包含一個問題)。但這聽起來像是Hibernate中的某種緩存。或者你可能用'cache =「50」'創建序列? –
正如我在PgAdmin看到的,我的SEQ_ORDERS緩存是1 – rvit34