1

次のような名前付きクエリがあります。

UPDATE Foo f SET f.x = 0 WHERE f.x = :invoiceId

Fooこの場合は、クラスごとのテーブル継承戦略を使用するスーパークラスを持つエンティティです。

EclipseLinkが生成するSQLは次のとおりです。

UPDATE foo_subclass SET x = ?
 WHERE EXISTS(SELECT t0.id
                FROM foo_superclass t0, foo_subclass t1
               WHERE ((t1.x = ?) AND ((t1.id = t0.id) AND (t0.DTYPE = ?)))

?スロットは正しく埋められています。)

Informix 11.70では、サブクエリが変更中のテーブルにアクセスできないというエラーが発生します。

Informixのサブクエリ制限について見つけたドキュメントは次のとおりです。http: //publib.boulder.ibm.com/infocenter/idshelp/v115/index.jsp? topic =%2Fcom.ibm.sqls.doc%2Fids_sqs_2005 .htm

他のデータベースにもこのようなサブクエリに対する制限があります。したがって、これはInformixの問題として現れていますが、たとえばMySQLに対してこれを実行すると、同様のエラーが発生することは間違いありません。

EclipseLinkにこれらの制限を尊重させるにはどうすればよいですか?使用すべきより良いクエリはありますか?

4

2 に答える 2

1

それ以外の:

UPDATE foo_subclass SET x = ?
 WHERE EXISTS(SELECT t0.id
                FROM foo_superclass t0, foo_subclass t1
               WHERE ((t1.x = ?) AND ((t1.id = t0.id) AND (t0.DTYPE = ?)))

これを行う:

UPDATE
  foo_subclass SET x = ?
WHERE
  foo_subclass.x = ? AND
  EXISTS(SELECT t0.id
         FROM foo_superclass t0
         WHERE ((foo_subclass.id = t0.id) AND (t0.DTYPE = ?))

11.50では、foo_subclassのエイリアスを使用できないことに注意してください。11.70で許可されています。「id」は主キー(または少なくとも一意の識別子)であると想定しています。

于 2013-02-27T22:33:20.557 に答える
1

答えが見つかりました。EclipseLinkがMySQLのこのケースを処理する必要があったようですが、これにも同様の問題があります。

答えは、InformixPlatformサブクラスで、この問題を解決するために次のメソッドをオーバーライドする必要があるということです。

  1. supportsLocalTemporaryTables():これは戻る必要がありますtrue
  2. shouldAlwaysUseTempStorageForModifyAll():これは戻る必要がありますtrue
  3. dontBindUpdateAllQueryUsingTempTables戻る必要がありますtrue
  4. getCreateTempTableSqlPrefix():これは戻る必要がありますCREATE TEMP TABLE 
  5. getCreateTempTableSqlSuffix():これは戻る必要があります WITH NO LOG
  6. isInformixOuterJoin():戻る必要がありますfalse
  7. getTempTableForTable(DatabaseTable):これはこれを行う必要があります:

    return new DatabaseTable("TL_" + table.getName(), "" /* no table qualifier */, table.shouldUseDelimiters(), this.getStartDelimiter(), this.getEndDelimiter());
    

さらに、適切なInformixPlatform動作を実現するには、次のメソッドもオーバーライドする必要があります。

  1. appendBoolean(Boolean, Writer):ストックのInformixプラットフォームは、ブールリテラルを適切に書き出せません。あなたはこれをする必要があります:

    if (Boolean.TRUE.equals(booleanValue)) {
      writer.write("'t'");
    } else {
      writer.write("'f'");
    }
    
  2. 'のオーバーライドwriteUpdateOriginalFromTempTableSqlと同じコードが含まれるようにオーバーライドする必要があります。H2Platform

    @Override
    public void writeUpdateOriginalFromTempTableSql(final Writer writer, final DatabaseTable table, final Collection pkFields, final Collection assignedFields) throws IOException {
      writer.write("UPDATE ");
      final String tableName = table.getQualifiedNameDelimited(this);    
      writer.write(tableName);
      writer.write(" SET ");
      final int size = assignedFields.size();
      if (size > 1) {
        writer.write("(");            
      }
      writeFieldsList(writer, assignedFields, this);
      if (size > 1) {
        writer.write(")");            
      }
      writer.write(" = (SELECT ");        
      writeFieldsList(writer, assignedFields, this);
      writer.write(" FROM ");
      final String tempTableName = this.getTempTableForTable(table).getQualifiedNameDelimited(this);
      writer.write(tempTableName);
      writeAutoJoinWhereClause(writer, null, tableName, pkFields, this);
      writer.write(") WHERE EXISTS(SELECT ");
      writer.write(((DatabaseField)pkFields.iterator().next()).getNameDelimited(this));
      writer.write(" FROM ");
      writer.write(tempTableName);
      writeAutoJoinWhereClause(writer, null, tableName, pkFields, this);
      writer.write(")");
    }
    

最後に、コンストラクターはを呼び出す必要がありますthis.setShouldBindLiterals(false)

これらの変更により、Informixは満足しているようです。

于 2013-03-01T04:34:02.460 に答える