2017-02-14 23 views
-1

2つの自動インクリメントフィールドを持つテーブル(PostgreSQL)があり、最初のフィールドには@Idと@GeneratedValueというアノテーションが付けられています。私が意図的にそれを設定するまで、インクリメントして保存してください。自動インクリメント用のHibernateアノテーションですが、保存前に値を保存する必要があります

これを行う方法はありますか?

@Entity 
@Table(name = "route") 
public class Route extends BaseEntity { 

private Integer id; 
private Integer routeNumberId; 

@Id 
@GeneratedValue(strategy = GenerationType.IDENTITY) 
@Column(name = "id") 
public Integer getId() { 
    return id; 
} 
... 
@XmlAttribute 
@Id 
@Basic(optional = false) 
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="route_number_seq") 
@GenericGenerator(name="route_number_seq", 
        strategy="com.tripms.models.master.UseIdOrGenerate") 
@Column(name = "route_number_id", nullable = false) 
public Integer getRouteNumberId() { 
    return routeNumberId; 
} 

} 

@Idに2回注釈を付けることはできません。複合pkは必要ありません。

+1

何かをコードしようとしましたか? – msagala25

+1

StackOverflowへようこそ達成しようとしていることに向かって努力を示すために、いくつかのコードを投稿する必要があります。これは、他のユーザーがあなたの質問に答えるのにも役立ちます。 –

+0

私はそれを更新しました.. @SouravGhosh –

答えて

1

自動増分値と手動値を混ぜることはお勧めできません。あなたの現在のシーケンスポイントが11になるように指示しても、データベースはどのように振舞うべきですか?値20のエントリを挿入しますか?シーケンスが20に達すると、ユニークな制約違反が発生します。これを防ぐには、生成されたシーケンス値が既存のエントリと競合していないことを確認する必要があります。再試行やロックなどの問題が発生する可能性があります。

あなたのモデルや要件を再考するために、なぜあなたは2番目の擬似IDですか?手動と自動の両方で記入することがなぜ可能なのでしょうか? この機能を主張する場合は、手動入力が自動生成されたものと衝突しないことを保証することができます。次に、実際のID列(Integer id)のカスタムIDジェネレータを作成し、generateメソッドをオーバーライドすることで、IDの生成とは別に、擬似ID "(routeNumberId)の値もチェックできます。 nullの場合、DBに次の値を与えるように依頼することができます。ダミー実装怒鳴る:

@Override 
public synchronized Serializable generate(SessionImplementor session, Object object) throws HibernateException { 
    Serializable result; 
    if (object instanceof Route) { 
     Route reoute= ((Route) object); 
     if (route.getid() != null) { 
      result = (Serializable) route.getId(); 
     } else { 
      result = <GENERATE new ID(e.g. call super, etc)> ; 
     } 
     if (route.getRouteNumberId() == null) { 
      long autoIncrRouteId = <GENERATE new routeID,> 
      route.setRouteNumberId(autoIncrRouteId); 
     } 
     return result; 
    } else { 
     result = super.generate(session, object); 
    } 

    return result; 
} 

別のオプションは、エンティティ・リスナーを@PrePersist使用し、チェックおよび/またはそこシーケンスの呼び出しを行うことです。しかし、ほとんどのJPAプロバイダはエンティティリスナへの注入を完全にサポートしていないため、リスナーからEntity ManagerまたはJPAコンテキストにアクセスするのは難しい場合があります。手動のjndiルックアップを実行することもできますが、問題の価値がある場合は、まず達成しようとしていることを再考してください。

編集:機能IDジェネレータコード(ポストグル)。

@Override 
public Serializable generate(SessionImplementor session, Object obj) throws HibernateException { 
    Connection connection = session.connection(); 
    try { 
     Route route= ((Route) obj); 
     String seqName = "you_db_id_sequence"; 
     PreparedStatement ps = connection.prepareStatement("SELECT nextval ('" + seqName + "') as nextval"); 
     ResultSet rs = ps.executeQuery(); 
     if (rs.next()) { 
      int id = rs.getInt("nextval"); 
      log.info("Generated order id {} ", id); 
      if (route.getRouteNumberId() == null) { 
       route.setrouteNumberid(id); //or call another sequence to get a different id 
      } 
      return Long.parseLong(code); 
     } else { 
      throw new IllegalStateException("could not generate new id"); 
     } 
    } catch (SQLException e) { 
     log.error("Could not generate id!", e); 
     throw new HibernateException("Unable to generate id from Sequence"); 
    } 
    return null; 
} 
+0

routeNumberIdを手動で追加できるようにする理由は - >ルートのレコードを保存している間に自動増分する必要があります。同じrouteNumberIdで記録する(これは他のテーブルにFkである)。また、監査のために前回のレコードが必要であり、古いレコードを別の列に格納する。すでに生成されているrouteNumberIdを使用しています.. –

+0

コードuはIDのためだけに働いています....私はrouteNumberIdのためにそれを必要とします..それはrouteNumberId coz上で動作しません。このコードは、@ Idだけが注釈されている場合に機能します –

+0

routeNumberIdが別のテーブルへのFKである場合、自動増分された整数ではなく、 '@ OneToOne'または' @ ManyToOne'の関連でなければなりません。 。ジェネレータが 'Integer Id'フィールドだけであっても、提供されたコードはIdとrouteNumberIdの両方を満たすでしょう。もちろん、複合PKを必要としない限り、 '@ Id'でアノテーションされた2つのカラムを持つことはできません。いずれにしても、routeNumberIdが別のエンティティへのFKである場合、モデルにはそれが反映されます。 – yntelectual

関連する問題