JPA와 Oracle Sequence

CREATE SEQUENCE SEQ_NO START WITH 1 INCREMENT BY 1 NOMAXVALUE; JPA의 EntityBean은 아래와 같이 작성한다. [crayon] @Entity @Table(name=”테이블이름”, schema=”스키마”) public class MyEntity implements Serializable { private static final long serialVersionUID = 1L; private long seqNo; @Id @Column(name=”SEQ_NO”) @GeneratedValue(strategy=GenerationType.SEQUENCE, generator=”S_MY_SEQ”) @SequenceGenerator(name=”S_MY_SEQ”, sequenceName=”SEQ_NO”) public long getSeqNo() { return seqNo; } public void setSeqNo(long seqNo) { this.seqNo = seqNo; } } [/crayon] 그렇다면 아래 테스트 코드를 살펴보자.. [crayon] public class JPATest { EntityManagerFactory emf; EntityManager em; public JPATest() { emf = Persistence.createEntityManagerFactory(“test”); em = emf.createEntityManager(); em.getTransaction().begin(); for (int i=0; i<11; i++) { MyEntity myEntity = insertSeq(); System.err.println( "SEQ=" + myEntity .getSeqNo() ); } em.getTransaction().commit(); em.close(); emf.close(); } public MyEntity insertSeq() { MyEntity myEntity = new MyEntity (); em.persist(myEntity ); return myEntity ; } public static void main(String[] args) throws Exception { new JPATest(); } } [/crayon] [tip] 물론 별도로 persistence.xml을 작성해야 한다.

<?xml version=”1.0″ encoding=”UTF-8″?> <!– Persistence deployment descriptor for dev profile –> <persistence xmlns=”http://java.sun.com/xml/ns/persistence” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd” version=”1.0″> <persistence-unit name=”test”> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>mypackage.MyEntity </class> <properties> <property name=”hibernate.dialect” value=”org.hibernate.dialect.OracleDialect”/> <property name=”hibernate.connection.driver_class” value=”oracle.jdbc.OracleDriver” /> <property name=”hibernate.connection.url” value=”jdbc:oracle:thin:@localhost:1521:myschema” /> <property name=”hibernate.connection.username” value=”myid” /> <property name=”hibernate.connection.password” value=”password” /> <property name=”hibernate.connection.autocommit” value=”false” /> <property name=”hibernate.hbm2ddl.auto” value=”none” /> <property name=”hibernate.show_sql” value=”true” /> <property name=”hibernate.format_sql” value=”true” /> <property name=”hibernate.use_sql_comments” value=”false” /> </properties> </persistence-unit> </persistence>
[/tip] 테스트코드에서 보듯이 for문을 11번 실행했다. 그렇다면 시퀀스를 가져오는 처리도 11번, INSERT문도 11번 실행되야 하는데, 사실은 그렇지 않다. [tip] select SEQ_NO.nextval from dual [/tip] 아래 로그를 보자.
Hibernate: select SEQ_NO.nextval from dual Hibernate: insert into schema.MyTable (SEQ_NO) values (?) Hibernate: insert into schema.MyTable (SEQ_NO) values (?) Hibernate: insert into schema.MyTable (SEQ_NO) values (?) Hibernate: insert into schema.MyTable (SEQ_NO) values (?) Hibernate: insert into schema.MyTable (SEQ_NO) values (?) Hibernate: insert into schema.MyTable (SEQ_NO) values (?) Hibernate: insert into schema.MyTable (SEQ_NO) values (?) Hibernate: insert into schema.MyTable (SEQ_NO) values (?) Hibernate: insert into schema.MyTable (SEQ_NO) values (?) Hibernate: insert into schema.MyTable (SEQ_NO) values (?) Hibernate: insert into schema.MyTable (SEQ_NO) values (?)
위에서 보듯이 시퀀스를 가져오는 처리는 단 1번 실행된다. 아마 100을 가져왔을테고, 그 다음에는 JPA 내부에서 +1 씩 더한다. 실행결과는 아래참조.
SEQ=100 SEQ=101 SEQ=102 SEQ=103 SEQ=104 SEQ=105 SEQ=106 SEQ=107 SEQ=108 SEQ=109 SEQ=110
그리고 그 다음 실행은 150부터 표시된다. 이것은 @SequenceGenerator 에서 설정하는 allocationSize속성을 생략할 경우 기본적으로 50 이 설정되며, 이 값은 자동으로 다음 시퀀스에 적용된다. [tip] 아! 그리고 한가지 더! 오라클의 시퀀스는 기본적으로 +1 씩 증가하는데라는 의문을 가질것이다. 물론 오라클 자체의 시퀀스는 +1씩 증가한다. JPA는 그 값을 가져와서 50을 곱한다음 사용하고 있을뿐.. 즉, 오라클자체의 시퀀스 값이 1, 2, 3… 으로 증가한다면 JPA에서 내부적으로 설정되는 값은 50, 100, 150…으로 설정된다. (allocationSize속성값에 따라서 적용됨) [/tip] ]]>

Related Posts