0

createPerImplementationColumnsForReferenceField に null データストア クラスを返す getDatastoreClass までたどり着きました。

私は 3.1.1 と現在 3.2.0-m4 リリースの両方を試しましたが、これで問題が解決することを期待しています。

RDBMSStoreManager#getDatastoreClass(String className, ClassLoaderResolver clr);

null データストア クラスを

ReferenceMapping#createPerImplementationColumnsForReferenceField(boolean pk, boolean nullable, boolean serialised, boolean embedded, int fieldRole, ColumnMetaData[] columnMetaData, ClassLoaderResolver clr)

orm を使用してマップされたスーパークラスに注釈を付けていますが、このマップされたスーパークラスにはテーブル定義がなく、両方のマップされたスーパークラスがこの例外をスローしています。

499170 [http-bio-8080-exec-8] DEBUG DataNucleus.Datastore.Schema  - Field [com.hp.vf.server.domain.AlertDefinition.isPublic] -> Column(s) ["ALERTDEFINITION"."ISPUBLIC"] using mapping of type "org.datanucleus.store.rdbms.mapping.java.BooleanMapping" (org.datanucleus.store.rdbms.mapping.datastore.SmallIntRDBMSMapping)
551964 [http-bio-8080-exec-8] DEBUG DataNucleus.Persistence  - Managing Persistence of Class : com.hp.vf.analytics.shared.metric.Metric [Table : (none), InheritanceStrategy : subclass-table]
561964 [http-bio-8080-exec-8] ERROR DataNucleus.Datastore.Schema  - An exception was thrown while adding/validating class(es) : null
java.lang.NullPointerException
    at org.datanucleus.store.rdbms.mapping.java.ReferenceMapping.createPerImplementationColumnsForReferenceField(ReferenceMapping.java:452)
    at org.datanucleus.store.rdbms.mapping.java.ReferenceMapping.prepareDatastoreMapping(ReferenceMapping.java:214)
    at org.datanucleus.store.rdbms.mapping.java.ReferenceMapping.initialize(ReferenceMapping.java:110)
    at org.datanucleus.store.rdbms.mapping.java.InterfaceMapping.initialize(InterfaceMapping.java:54)

参照マッピングでは、getIdMapping() を実行しようとすると dc が null になります。デバッガで確認しました。

           try
            {
                DatastoreClass dc = storeMgr.getDatastoreClass(implClass.getName(), clr);
                m = dc.getIdMapping(); // DC is null 
            }
            catch (NoTableManagedException ex)
            {
                // TODO Localise this message
                throw new NucleusUserException("Cannot define columns for " + mmd.getFullFieldName() + 
                    " due to " + ex.getMessage(), ex);
            }

問題のあるクラス ファイルは次のとおりです。

public abstract class Metric implements IMetric {

    /**
     * Serialization ID
     */
    private static final long serialVersionUID = 3806479436166940035L;

    private Long id;

    /**
     * The name of the metric, this is not mandatory we have some metrics that
     * may come back without names.
     */
    protected String name;

    /**
     * This is an optional metric value that can be set by the script in order
     * to add context to the execution of the metric.
     */
    protected String context;

    /**
     * The list of violations associated with this metric.
     */
    protected List<Violation> violations = null;

    public Metric() {
        violations = new ArrayList<Violation>();
    }

    /**
     * Constructor that takes the name of the object and the value that it
     * represents.
     * 
     * @param name
     * @param value
     */
    public Metric(String name) {
        this();
        this.name = name;
    }

    /* (non-Javadoc)
     * @see com.hp.vf.taskengine.shared.metric.IMetric#getName()
     */
    @Override
    public String getName() {
        return name;
    }

    /* (non-Javadoc)
     * @see com.hp.vf.taskengine.shared.metric.IMetric#setName(java.lang.String)
     */
    @Override
    public void setName(String name) {
        this.name = name;
    }

    /**
     * This is the context that represents the metric. This could have come from
     * R and would be a Key:Value; pair of values used to calculate the value.
     * For example if a metric was calculated for a product in houston for ISS
     * the context may look like "ProdNum:1234;Factory:Houston;BUnit:ISS". This
     * context is useful when chaining together tasks.
     * 
     * @return String context used when chaining tasks together.
     */
    public String getContext() {
        return context;
    }

    /* (non-Javadoc)
     * @see com.hp.vf.taskengine.shared.metric.IMetric#toString()
     */
    public String toString() {
        String debugString = "";
        debugString += "Metric: " + name;

        return debugString;
    }

    /* (non-Javadoc)
     * @see com.hp.vf.taskengine.shared.metric.IMetric#hasMetricViolations()
     */
    @Override
    public boolean hasMetricViolations() {
        return (violations != null && violations.size() > 0) ? true : false;
    }


    /* (non-Javadoc)
     * @see com.hp.vf.taskengine.shared.metric.IMetric#getViolations()
     */
    @Override
    public List<IViolation> getViolations() {
        return violations;
    }

    /* (non-Javadoc)
     * @see com.hp.vf.taskengine.shared.metric.IMetric#setViolations(java.util.List)
     */
    @Override
    public void setViolations(List<IViolation> violations) {
        this.violations = violations;
    }

    @Override
    public Long getId() {
        return id;
    }
}

ここに私のorm.xmlファイルからの抜粋があります

<access>FIELD</access>

<mapped-superclass class="com.hp.vf.analytics.shared.metric.Metric" access="FIELD">
    <attributes>
        <basic name="name" />
        <basic name="context" />
        <one-to-many name="violations">
            <cascade>
                <cascade-all />
            </cascade>
        </one-to-many>
    </attributes>
</mapped-superclass>

私は何か間違ったことをしていますか、それともこれはバグですか?

4

1 に答える 1

0

Datanucleus からのヒントを使用して問題を解決できました。複数の問題がありました

問題
私にとって最も明白でばかげている問題

インターフェイスを使用する 1 対多または 1 対 1 がある場合は、ターゲット エンティティを指定する必要があります。

    /**
     * The list of violations associated with this metric.
     */
    protected List<IViolation> violations = null;
...
    <one-to-many name="violations"
      target-entity="com.vf.analytics.shared.metric.Violation">
       <cascade>
          <cascade-all />
       </cascade>
    </one-to-many>

ジェネリックを使用しないでください。JPA仕様はそれらをサポートしていません.datanucleus
がジェネリックをサポートしているかどうかはわかりませんが、おそらく推奨されていません.

public MetricNumber< T extends Number> extends Metric implements IMetric {
  T value;
}

注釈が付けられていないエンティティを拡張する場合は、必ず orm.xml に追加してください。

一部のオブジェクトをテストしていなかったので、datanucleus がそれらを無視すると想定しましたが、そうではないようです。注釈が付けられていないが、まだ orm.xml に追加していないサード パーティ クラスを拡張しました。これにより、取得していた null ポインター例外が null になっていました。

于 2013-02-27T14:31:36.823 に答える