2017-12-20 10 views
0

MySQL 데이터베이스에 새 행을 삽입하는 데 문제가 있습니다. 스프링 부트 데이터 JPA와 함께 스프링 부트를 사용하고 있습니다.삽입 후 최대 절전 모드 선택

MySQL은 시퀀스를 지원하지 않으므로 필자는 자체 시퀀스 생성기 테이블을 만들기로 결정했습니다. 이것은 기본적으로 내가 한 일입니다.

  1. 나는 자동 증가 필드 (내 테이블에 대한 내 ID로 사용)를 사용하는 sequences 테이블을 만들었습니다.
  2. sequences_nextvalue() 함수를 작성하여 sequences 테이블에 삽입하고 새 자동 증가 ID를 반환합니다.
  3. 그런 다음 삽입하기 전에 트리거 된 각 테이블에서 트리거를 생성하고 id 필드를 sequences_nextvalue() 호출 결과로 바꿉니다.

이렇게하면 새 행을 삽입 할 때 문제가 없습니다. 모든 테이블에서 고유 ID를 얻고 있습니다. JPA 엔티티에 문제가 있습니다. 내가 그 클래스 내 @Id 열을 배치하고 InheritanceType.TABLE_PER_CLASS@Entity을 사용했습니다 있도록

@Entity 
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) 
public abstract class AbstractBaseClass { 
    @Id 
    private Integer id = -1; 
    ... 
} 

@Entity 
public class ConcreteClass1 extends AbstractBaseClass { 
    ... 
} 


@Entity 
public class ConcreteClass2 extends AbstractBaseClass { 
    ... 
} 

나는 추상 기본 클래스에서 쿼리 할 수 ​​있어야합니다. id는 -을 봄철 저장소에서 호출해야하므로 -1로 초기화했습니다. 내 봄 데이터 CrudRepositorysave() 함수를 호출 한 후

, -1 id 제대로 MySQL의 트리거하지만 새로운 ID로 반환하지 않습니다 save()에 의해 반환 된 결과 개체로 대체됩니다 대신 -1을 유지합니다. SQL 로그를보고 나면 삽입 후 select 문을 호출하지 않고 새 ID를 가져 오지 만 원래 엔티티가 반환됩니다.

@GeneratedValue을 사용하지 않을 때 Hibnerate가 삽입 후 엔티티를 다시 선택하여 새 ID를 가져올 수 있습니까?

도움을 주시면 대단히 감사하겠습니다.

+0

MySQL이 Sequence..https 지원 //stackoverflow.com/questions/26578313/how-do-i-create-a-sequence-in-mysql – Yogi

+0

을 'AUTO_INCREMENT'의 문제는 각 테이블이 중복되는 id를 허용하는'AUTO_INCREMENT' 필드를 가지도록 범위가 지정되었습니다. 여러 테이블에 걸쳐 고유 한 ID를 갖고 싶습니다. 'SOME_TABLE'에 ID가 1이면'ANOTHER_TABLE '에 1의 ID가 없습니다. 그래서 기본적으로 여러 테이블을 공유하고'AUTO_INCREMENT' 필드를 원합니다. – jmw5598

+0

이미'@ GeneratedValue'를 사용하지 않았으므로 Hibernate는'INSERT' 이후에 정상적으로 수행하는'SELECT'를 수행하지 않습니다. 그래서'반환 된 엔티티에 새로 생성 된 ID를 저장하지 않습니다()'. id는 데이터베이스에 제대로 저장됩니다. – jmw5598

답변

0

이 질문에 대한 업데이트를 제공하고 싶습니다. 여기 내 해결책이있다. 대신 MySQL의 TRIGGER의이 idINSERT에 대체 만드는

, 내가 얻고 새로운 ID를 반환하는 CallableStatement을 실행하는 최대 절전 모드 IdentifierGenerator를 만들었습니다.

내 추상 기본 클래스는 다음과 같이 보입니다.

@Entity 
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) 
public abstract class AbstractBaseClass { 

    @Id 
    @GenericGenerator(name="MyIdGenerator", strategy="com.sample.model.CustomIdGenerator") 
    @GeneratedValue(generator="MyIdGenerator") 
    private Integer id; 
    ... 

} 

제 발전기는 이렇게 보입니다.

public class CustomIdGenerator implements IdentifierGenerator { 

    private Logger log = LoggerFactory.getLogger(CustomIdGenerator.class); 
    private static final String QUERY = "{? = call sequence_nextvalue()}"; 

    @Override 
    public Serializable generate(SessionImplementor session, Object object) throws HibernateException { 

     Integer id = null; 
     try { 
      Connection connection = session.connection(); 
      CallableStatement statement = connection.prepareCall(QUERY); 
      statement.registerOutParameter(1, java.sql.Types.INTEGER); 
      statement.execute(); 
      id = statement.getInt(1); 
     } catch(SQLException e) { 
      log.error("Error getting id", e); 
      throw new HibernateException(e); 
     } 
     return id; 
    } 

} 

그리고 단지

sequences 표 참조

에 대한

.

CREATE TABLE sequences (
    id INT AUTO_INCREMENT PRIMARY KEY, 
    thread_id INT NOT NULL, 
    created DATETIME DEFAULT CURRENT_TIMESTAMP 
) ^; 

sequence_nextvalue 기능

CREATE FUNCTION sequence_nextvalue() 
RETURNS INTEGER 
NOT DETERMINISTIC 
MODIFIES SQL DATA 
BEGIN 
    DECLARE nextvalue INTEGER; 
    INSERT INTO sequences (thread_id) VALUE (CONNECTION_ID()); 
    SELECT id FROM sequence_values ORDER BY created DESC LIMIT 1 INTO nextvalue; 
    RETURN nextvalue; 
END ^;