2012-01-03 2 views
1

多くの検索と試行の後、私は立ち往生しています...私は2つのクラス、1つはExpectedSecurityReturn、もう1つはForecastReturnTypeです。 ForecastReturnTypeはExpectedSecurityReturnのメンバーですが、データを永続化するときは挿入しないでください。私は "不十分な特権"を取得し続けますが、JDBCとJPAの削除で正常に動作するので、ユーザがテーブルexpected_security_returnに対する削除/挿入権限を持っていることがわかります。したがって、私はそれが私のクラスと関係していると思います。トランザクションから挿入を実行するときのJPA 2.0の不十分な特権

@Table(name = "EXPECTED_SECURITY_RETURNS") 
@Entity 
@IdClass(ExpectedSecurityReturn.ExpectedSecurityReturnPK.class) 
public class ExpectedSecurityReturn { 

@Id 
@Column(name = "REP_SEC_ID") 
private Integer repSecId; 

@Id 
@Column(name = "AS_OF_DATE") 
private Date date; 

@Id 
@ManyToOne(optional = false) 
@JoinColumn(name = "RETURN_TYPE_ID", referencedColumnName = "RETURN_TYPE_ID", insertable=false) 
private ForecastReturnType returnType; 

@Column(name="CURR_TOUSD_RET") // local currency to usd 
private Double currencyToUsdReturn; 
} 

ForecastReturnTypeを含んで主キークラス、:

// ------------------------------ 
// PK 
// ------------------------------ 
public static class ExpectedSecurityReturnPK implements Serializable { 

    private static final long serialVersionUID = 1325372032981567439L; 

    public ExpectedSecurityReturnPK() { 
    } 

    public ExpectedSecurityReturnPK(final Integer repSecId, 
      final Date asOfDate, ForecastReturnType returnType) { 
     if (repSecId == null) 
      throw new IllegalArgumentException("null rep sec id"); 
     if (asOfDate == null) 
      throw new IllegalArgumentException("null asOfDate"); 
     if (returnType == null) 
      throw new IllegalArgumentException("null returnType"); 

     this.repSecId = repSecId; 
     this.date = new Date(asOfDate.getTime()); 
    } 

    @Override 
    public boolean equals(final Object o) { 
     if (this == o) 
      return true; 
     if (o == null || getClass() != o.getClass()) 
      return false; 

     final ExpectedSecurityReturnPK that = (ExpectedSecurityReturnPK) o; 

     if (repSecId != that.repSecId) 
      return false; 
     if (!date.equals(that.date)) 
      return false; 
     if (!returnType.equals(that.returnType)) 
      return false; 

     return true; 
    } 

    @Override 
    public int hashCode() { 
     int result = repSecId; 
     result = 31 * result + date.hashCode(); 
     result = 31 * result + returnType.getForecastTypeId(); 
     return result; 
    } 

    private int repSecId; 
    private Date date; 
    private ForecastReturnType returnType; 
} 

とForecastReturnType:

@Table(name="EXPECTED_SEC_RET_TYPE_DECODE") 
@Entity 
public class ForecastReturnType { 

@Id 
@Column(name="RETURN_TYPE_ID") 
private int forecastTypeId; 

@Column(name="SHORT_NAME") 
private String shortName; 

@Column(name="LONG_NAME") 
private String longName; 

@OneToMany(fetch=FetchType.LAZY, mappedBy="returnType") 
Collection<ExpectedSecurityReturn> expectedSecurityReturns; 
} 

は、誰も私が私が間違っているのかを把握助けてもらえますか?私は成功せずに多くのことを試みた...私は、ユーザーが特権を持っていないことを知っているので、犯人はExpectedSecurityReturn.returnTypeだと思う。

基本的には、ExpectedSecurityReturnインスタンスを挿入/保持する必要があります。

+0

JPA実装のログを調べて、どのSQLが呼び出されているのか、そして例外の詳細(およびそのスタックトレース) – DataNucleus

+0

Seconds、PostgreSQLを使用している場合、postgresql.confを頻繁に変更できます/ var/pgsqlにあります)、サーバでのロギングを有効にし、ロギングセクションを探します。 MySQLを使用している場合は、my.cnf(多くの場合/ etc)にログを追加してすべてのクエリを記録することができます.Oracleを使用している場合は、V $ SQLで参照する必要があります。私はあなたがすべてのクエリをログに記録できるかどうかを知るためにMSSQLをよく知っていませんが、SQL Studioを通してデータベースロックの履歴を取得できると思います。 – PlexQ

+0

結果のSQLは – user899757

答えて

0

さて、いくつかのことがあります。

私はこれをやろうとしても大したことは勧めません。あなたはJPAの注釈やこのような奇妙な問題を決める人生を無駄にすることはできません。また、異なるJPAプロバイダは、このようなより複雑な構造については多少異なる動作をし、継承については二重になります。

あなたはEXPECTED_SECURITY_RETURNSにユニークなキーを作成することが本当にずっと良かったです。それだけで暮らしていれば、Javaの生活をはるかに簡単にすることができます。

にこのようなことを行うためにがある場合、JPAが主キーコンポーネントを別のエンティティオブジェクトにするのをやめているのは驚きではありません。これはRDBMSではもちろん可能ですが、JPAを飛び越えるようなことはほとんどないようです。

JPA implが出すクエリログもチェックします(ほとんどのJPAプロバイダの永続性定義、もちろんEcpliselinkとHibernateではかなり簡単に設定可能です)。私はそれがEXPECTED_SEC_RET_TYPE_DECODEの更新を実行しようとしていると思いますが、そうでなければ、あなたのDBMSに応じてロック(テーブル、行またはその他)を取得しようとしている可能性があります。ユーザーがそのテーブルでロックまたは更新を実行する権限を持っていない場合、正確な実装によっては、アクセス許可の問題でクエリが失敗する可能性があります。

JPAは、トランザクション中にEXPECTED_SEC_RET_TYPE_DECODEで参照されているエントリが変更される可能性があるため、そのテーブルをロックすることが妥当です。したがって、他のテーブルの更新/挿入。最後に、JPAにこのテーブルが基本的に静的であることを伝える方法はありません。 Hibernateを使用している場合は、@ ReadOnlyアノテーションを試してみることもできますが、これまで試みてきたことはあまりありません。

あなたがより良い解決策を見つけたら、私たちの残りの人が学ぶことができるように投稿してください!

+0

ありがとうあなたの投稿。私は見て、次に何をするかを考え出すでしょう。私はこの紛争を解決したときに再び投稿します。コンポジットPKはテーブルデザインでは非常に一般的な場所なので、JPAが機能すると思うでしょう。 EXPECTED_SEC_RET_TYPE_DECODEに関する問題が正しいと思います。それも私の考えです。 ExpectedSecurityReturn.returnTypeをint(ForecastReturnTypeのPKはintなので)に置き換え、オブジェクト自体(ForecastReturnType)を忘れてしまいます。 – user899757

+0

彼らはかなり一般的です、私は同意します。リンクテーブルは最も一般的な変種であり、JPAは@JoinTableアノテーションを持つ人たちとうまくやっています。一般的に、メタデータを持つ結合表であるものに新しい主キー列を追加することによって行われる犠牲は大きくありません。両方の外部キー(またはそれ以上)が外部キー制約でマッピングされているため、制約の影響は小さく、主キーの動作をシミュレートするためにSQLで一意のインデックスを作成できます。 PostgreSQLはこのように一意のインデックスを使用しています。したがって、関係する限り、内部ローIDがあるので違いはありません。 – PlexQ

+0

遅延負荷と熱負荷の1つの問題が発生します。複合主キーを持つテーブルが多すぎると、ORMにとって非常に危険になります。整合性を検証するために、特にコンポジット主キーが外部キーで構成されている場合は、非常に大量の表情報をフェッチする必要があります。同様の状況が一対多の関連付けで発生します。いずれかでオブジェクトグラフをトラバースすると、悪いORMは文字通りそのデータに対するあなたの意図を知ることができないので、フェッチプロセスを合理的なクエリに最適化してネットワークリンクをスラッシングさせることはできません。 – PlexQ

0

派生IDと複合キーは、JPAのかなり複雑な部分です。

ただし、JPA 2。0仕様には、これらのトピックを説明するための良い例が含まれています。これらの例は、主にさまざまなJPA実装で機能します。あなたのケースの仕様については

@ManyToOneフィールドの名前と参照先エンティティの@Idフィールドの型と@IdClassにフィールドを置くためにあなたを示唆:

@Entity 
public class Employee { 
    @Id long empId; 
    String empName; 
    ... 
} 

public class DependentId { 
    String name; // matches name of @Id attribute 
    long emp; // matches name of @Id attribute and type of Employee PK 
} 

@Entity 
@IdClass(DependentId.class) 
public class Dependent { 
    @Id String name; 
    // id attribute mapped by join column default 
    @Id @ManyToOne Employee emp; 
    ... 

}

も参照してください:

0

多くの試行錯誤の末、私は最終的にエラーが正当であると判断し、実際に十分な(つまり挿入)特権を持っていませんでした。

関連する問題