部署后,休眠元模型字段引用无效

时间:2018-11-30 14:13:35

标签: java hibernate metamodel

我在使用Hibernate / JPA元模型时遇到了一个奇怪的情况。我们成熟的Wicket 7 Web应用程序可以正常部署,但是一段时间后,某些元模型字段值将变为空。总是相同的罪魁祸首(该应用程序有数百个实体,并且始终是这个实体)。元模型生成器为ProductGroup类创建此代码:

@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(ProductGroup.class)
public abstract class ProductGroup_ extends com.sw.generic.data.AbstractBusinessEntity_ {

    public static volatile SingularAttribute<ProductGroup, String> serviceLevelDescription;
    public static volatile SingularAttribute<ProductGroup, String> supportDescription;
    public static volatile SingularAttribute<ProductGroup, String> code;
    public static volatile SingularAttribute<ProductGroup, Boolean> useProductSubgroupL2;
    public static volatile SingularAttribute<ProductGroup, String> description;
    public static volatile SingularAttribute<ProductGroup, Boolean> useSupportSubgroupL2;
    public static volatile SingularAttribute<ProductGroup, String> productSubgroupLevel1Description;
    public static volatile SingularAttribute<ProductGroup, String> serviceLevelGroupDescription;
    public static volatile SingularAttribute<ProductGroup, String> productSubgroupLevel2Description;
    public static volatile SingularAttribute<ProductGroup, String> supportSubgroupLevel1Description;
    public static volatile SingularAttribute<ProductGroup, String> supportSubgroupLevel2Description;

}

获取空指针的地方是一个将属性保留为字段的枚举:

public class DefaultProductGroupEntityDescriptionLabel extends OptionalLabel {

  private static final long serialVersionUID = 1L;

  public static enum ProductGroupEntityType {
    SUPPORT_SERVICE( "product.group.label.support.default", ProductGroup_.supportDescription ),
    SUPPORT_SUBGROUP_L1( "product.group.label.support.subgroup.l1.default", ProductGroup_.supportSubgroupLevel1Description ),
    SUPPORT_SUBGROUP_L2( "product.group.label.support.subgroup.l2.default", ProductGroup_.supportSubgroupLevel2Description ),
    PRODUCT_SUBGROUP_L1( "product.group.label.product.subgroup.l1.default", ProductGroup_.productSubgroupLevel1Description ),
    PRODUCT_SUBGROUP_L2( "product.group.label.product.subgroup.l2.default", ProductGroup_.productSubgroupLevel2Description ),
    SERVICE_LEVEL( "product.group.label.servicelevel.default", ProductGroup_.serviceLevelDescription ),
    SERVICE_LEVEL_TYPE( "product.group.label.serviceleveltype.default", ProductGroup_.serviceLevelGroupDescription );

    private String m_singularKey;
    private String m_pluralKey;

    private Attribute<ProductGroup,String> m_attribute;

    private ProductGroupEntityType( String p_key, Attribute<ProductGroup,String> p_attribute ) {
      this( p_key, p_key, p_attribute );
    }

    private ProductGroupEntityType( String p_singularKey, String p_pluralKey, Attribute<ProductGroup,String> p_attribute ) {
      m_singularKey = p_singularKey;
      m_pluralKey = p_pluralKey;
      m_attribute = p_attribute;
    }

    public String getSingularKey() {
      return m_singularKey;
    }
    public String getPluralKey() {
      return m_pluralKey;
    }

    public Attribute<ProductGroup,String> getAttribute() {
      return m_attribute;
    }

    public String getDescription( ProductGroup p_group ) {
      try {
        return BeanUtils.getSimpleProperty( p_group, getAttribute().getName() ); // <-- This is where the NPE occurs!
      } catch( Exception e_e ) {
        throw new IllegalStateException( name() + " has a bad property setting - cannot get Vendor property " + getAttribute().getName(), e_e );
      }
    }
  }

  protected IModel<ProductGroupEntityType> m_typeModel;

  protected IModel<String> m_baseModel;

  /**
   * @param p_id
   */
  public DefaultProductGroupEntityDescriptionLabel( String p_id, ProductGroupEntityType p_type ) {
    this( p_id, Model.of( p_type ) );
  }

  /**
   * @param p_id
   */
  public DefaultProductGroupEntityDescriptionLabel( String p_id, IModel<ProductGroupEntityType> p_typeModel ) {
    super( p_id );
    m_typeModel = p_typeModel;
  }

  @Override
  public void detachModels() {
    super.detachModels();
    m_typeModel.detach();
    m_baseModel.detach();
  }

  protected void onInitialize() {
    super.onInitialize();

    m_baseModel = createBaseModel();

    setDefaultModel( createDescriptionModel( m_baseModel ) );

    add( new MultilineTooltipBehavior( new LoadableDetachableModel<String>() {

      private static final long serialVersionUID = 1L;

      @Override
      protected String load() {
        return getString( m_typeModel.getObject().getSingularKey() );
      }
    } ) );
  }

  @Override
  protected void onDetach() {
    super.onDetach();
    if( m_baseModel != null ) {
      m_baseModel.detach();
    }
  }

  /**
   * Creates the base model for getting the description
   * @return a model for getting the description.  This version gets the default description from the property settings.
   */
  protected IModel<String> createBaseModel() {
    return new LoadableDetachableModel<String>() {

      private static final long serialVersionUID = 1L;

      @Override
      protected String load() {
        return getString( isPlural() ? m_typeModel.getObject().getPluralKey() : m_typeModel.getObject().getSingularKey() );
      }
    };
  }

  /**
   * Allows subclasses to return a modified version of the model, so the base description can be part of a more complex description.
   * @param p_baseDescriptionModel
   * @return the base model unchanged by default
   */
  protected IModel<String> createDescriptionModel( IModel<String> p_baseDescriptionModel ) {
    return p_baseDescriptionModel;
  }

  /**
   * If true, plural versions of the key will be used.
   * @return false by default.
   */
  public boolean isPlural() {
    return false;
  }
}

调用ProductGroupEntityType :: getDescription会导致错误,但不是在初始部署时发生,而是在几个小时后:

Caused by: java.lang.NullPointerException
    at com.sw.system4.ui.product.group.DefaultProductGroupEntityDescriptionLabel$ProductGroupEntityType.getDescription(DefaultProductGroupEntityDescriptionLabel.java:64)
    at com.sw.system4.ui.product.group.ProductGroupEntityDescriptionModel.load(ProductGroupEntityDescriptionModel.java:57)
    at com.sw.system4.ui.product.group.ProductGroupEntityDescriptionModel.load(ProductGroupEntityDescriptionModel.java:17)
    at org.apache.wicket.model.LoadableDetachableModel.getObject(LoadableDetachableModel.java:135)
    at org.apache.wicket.model.StringResourceModel.getString(StringResourceModel.java:454)
    at org.apache.wicket.model.StringResourceModel$AssignmentWrapper.load(StringResourceModel.java:271)

该代码一直使用,并且基本上不会导致此问题。

停止并重新启动它所在的tomcat服务器可以使其再次工作。

我怀疑如果我将ProductGroupEntityType属性字段从Attribute更改为String,然后传入attribute.getName(),那么它最终并不会保留可以解决问题的引用,但是有人可以告诉我这是为什么首先发生?预先感谢。

Hibernate 5.1.14,Java 8

0 个答案:

没有答案