J'utilise liquibase comme outil de migration pour mon projet actuel. Le problème est que j'essaie d'utiliser une séquence personnalisée pour les identifiants de génération automatique pour les entités, mais quelque chose ne va pas.Pourquoi la liquibase utilise-t-elle toujours sa propre séquence?
J'ai défini une table d'entité et séquence personnalisée comme similaire ci-dessous:
<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>
Mais quand cette migration est appliquée, je vois la structure de tableau suivant dans 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
);
Première imprévisible chose pour moi ici est pourquoi liquibase a écrit son propre orders_id_seq
au lieu de mon SEQ_ORDERS
?
Ensuite, j'écrit un code JPA typique et il est test à l'aide du printemps:
@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> {}
test
@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));
}
}
Dans les journaux de test, je vois:
Hibernate: select nextval ('seq_orders')
...
java.lang.AssertionError:
Expected: is <Order(id=50, number=order-n-01, ...>
but: was null
Après test est terminé en DB J'ai vu trois commandes avec id = 50,51,52
Première fois que je pensais que orders_id_seq
incrémente la valeur sur 50 à chaque fois. j'étais très surpised quand j'ai vu non modifié orders_id_seq
après le test (valeur actuelle = 1), mais mon SEQ_ORDERS a été augmentée sur 1.
Quand je lance le test encore une fois je suis arrivé trois commandes avec ids 100.101.102
pourrait Quelqu'un m'explique ce qui se passe ici? Et comment faire liquibase & postgresql faire les bonnes choses?
J'utilise: PostgreSQL 9.6 (org.postgresql.9.4.1212 pilote JDBC), Liquibase 3.5.3, Spring Boot 1.5.2
Spring Boot test Config:
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
Ouais, ce changelog fait postgreSQL utiliser ma séquence mais je m'y suis 50,51,52 ids de toute façon. – rvit34
@ rvit34: probablement quelque chose qui ne va pas avec le mapping dans votre couche d'obfuscation - je n'utilise pas Hibernate donc je ne peux pas vous aider avec ça). Vous voudrez peut-être poser une question distincte pour cela (une question sur l'OS ne devrait contenir qu'une seule question). Mais cela ressemble à une sorte de mise en cache dans Hibernate. Ou avez-vous créé la séquence avec 'cache =" 50 "'? –
Comme je le vois dans PgAdmin, cache de mon SEQ_ORDERS est 1 – rvit34