2017-12-20 16 views
0

MySQLデータベースに新しい行を挿入する際に問題があります。私はSpring Boot Data JPAでSpring Bootを使用しています。挿入後にハイバーネーションを選択

MySQLはシーケンスをサポートしていないので、独自のシーケンスジェネレータテーブルを作成することにしました。これは基本的に私がやったことです。

  1. 自動増分フィールド(自分のテーブルのIDとして使用)を使用するsequencesテーブルを作成しました。
  2. 関数sequences_nextvalue()が作成され、sequencesテーブルに挿入され、新しい自動インクリメントIDが返されます。
  3. それから、挿入前にトリガーされた各テーブルでトリガーを作成し、idフィールドをsequences_nextvalue()の呼び出しの結果に置き換えました。

これは新しい行を挿入するときに問題なく動作します。すべてのテーブルでユニークなIDを取得しています。私が抱えている問題はJPAエンティティにあります。

@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列を配置し、InheritanceType.TABLE_PER_CLASS@Entityを使用しましたので、抽象基本クラスから照会できるようにしたいです。また、私はIDを-1に初期化しました。なぜなら、IDはsave()を私のspring crudリポジトリから呼び出す必要があるからです。私の春のデータCrudRepositorysave()関数を呼び出した後

、-1 idに対して適切にMySQLのトリガーが、新しいIDで返さないsave()によって返されたエンティティによって置き換えられますが、代わりに-1を保持します。 SQLログを調べた後、新しいIDを取得するために挿入後にselectステートメントが呼び出されず、代わりに元のエンティティが返されます。

@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'にはidが1つもありません。だから基本的に私は複数のテーブルと 'AUTO_INCREMENT'フィールドを共有したい。 – jmw5598

+0

私はすでにこれを動作させていますが、 '@ GeneratedValue'を使用していないので、Hibernateは通常' INSERT'の後に 'SELECT'を実行しませんので、' save () 'を返します。 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 ^; 
関連する問題