当前位置: 首页 > 知识库问答 >
问题:

具有基本类继承的JPA映射

梁英喆
2023-03-14

我有一个用JPA映射的简单类:

@Entity
@Table(name = "SPONSOR")
public class Sponsor extends PersistableBusinessObjectBase implements SponsorContract {

@PortableSequenceGenerator(name = "SEQ_SPONSOR_CODE")
@GeneratedValue(generator = "SEQ_SPONSOR_CODE")
@Id
@Column(name = "SPONSOR_CODE")
private String sponsorCode;

@Column(name = "ACRONYM")
private String acronym;

@Column(name = "AUDIT_REPORT_SENT_FOR_FY")
private String auditReportSentForFy;

@Column(name = "CAGE_NUMBER")
private String cageNumber;

@Column(name = "COUNTRY_CODE")
private String countryCode;

@Column(name = "DODAC_NUMBER")
private String dodacNumber;

@Column(name = "DUN_AND_BRADSTREET_NUMBER")
private String dunAndBradstreetNumber;

@Column(name = "DUNS_PLUS_FOUR_NUMBER")
private String dunsPlusFourNumber;

@Column(name = "OWNED_BY_UNIT")
private String ownedByUnit;

@Column(name = "POSTAL_CODE")
private String postalCode;

@Column(name = "ROLODEX_ID")
private Integer rolodexId;

@Column(name = "SPONSOR_NAME")
private String sponsorName;

@Column(name = "SPONSOR_TYPE_CODE")
private String sponsorTypeCode;

@Column(name = "STATE")
private String state;

@Column(name = "CREATE_USER")
private String createUser;

@Column(name = "ACTV_IND")
@Convert(converter = BooleanYNConverter.class)
private boolean active;

@ManyToOne(cascade = { CascadeType.REFRESH })
@JoinColumn(name = "SPONSOR_TYPE_CODE", referencedColumnName = "SPONSOR_TYPE_CODE", insertable = false, updatable = false)
private SponsorType sponsorType;

@ManyToOne(cascade = { CascadeType.REFRESH })
@JoinColumn(name = "OWNED_BY_UNIT", referencedColumnName = "UNIT_NUMBER", insertable = false, updatable = false)
private Unit unit;

@ManyToOne(cascade = { CascadeType.REFRESH })
@JoinColumn(name = "ROLODEX_ID", referencedColumnName = "ROLODEX_ID", insertable = false, updatable = false)
private Rolodex rolodex;
....

我把那门课扩展成了非常简单的课

@Entity
public class SponsorMaintainableBo extends Sponsor {
}

这正是我对SponsorDefainableBo所需要的。它是Sponsor的副本,并且从与Sponsor相同的表中读取。这是我们通过一些xml文档控制的查询框架所需要的,并且需要成为我正在做的事情的单独对象。需要SponsorDefainableBo插入查询/维护框架以进行我们不想在主父文档中进行的自定义详细信息。当我尝试使用SponsorDefainableBo时,我得到以下错误:

org.springframework.orm.jpa.JpaSystemException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: Unknown column 'DTYPE' in 'field list'
Error Code: 1054
Call: SELECT SPONSOR_CODE AS a1, DTYPE AS a2, ACRONYM AS a3, ACTV_IND AS a4, AUDIT_REPORT_SENT_FOR_FY AS a5, CAGE_NUMBER AS a6, COUNTRY_CODE AS a7, CREATE_USER AS a8, DODAC_NUMBER AS a9, DUN_AND_BRADSTREET_NUMBER AS a10, DUNS_PLUS_FOUR_NUMBER AS a11, OBJ_ID AS a12, OWNED_BY_UNIT AS a13, POSTAL_CODE AS a14, ROLODEX_ID AS a15, SPONSOR_NAME AS a16, SPONSOR_TYPE_CODE AS a17, STATE AS a18, UPDATE_TIMESTAMP AS a19, UPDATE_USER AS a20, VER_NBR AS a21 FROM SPONSOR WHERE (DTYPE = ?) LIMIT ?, ?
bind => [3 parameters bound]
Query: ReadAllQuery(referenceClass=SponsorMaintainableBo sql="SELECT SPONSOR_CODE AS a1, DTYPE AS a2, ACRONYM AS a3, ACTV_IND AS a4, AUDIT_REPORT_SENT_FOR_FY AS a5, CAGE_NUMBER AS a6, COUNTRY_CODE AS a7, CREATE_USER AS a8, DODAC_NUMBER AS a9, DUN_AND_BRADSTREET_NUMBER AS a10, DUNS_PLUS_FOUR_NUMBER AS a11, OBJ_ID AS a12, OWNED_BY_UNIT AS a13, POSTAL_CODE AS a14, ROLODEX_ID AS a15, SPONSOR_NAME AS a16, SPONSOR_TYPE_CODE AS a17, STATE AS a18, UPDATE_TIMESTAMP AS a19, UPDATE_USER AS a20, VER_NBR AS a21 FROM SPONSOR WHERE (DTYPE = ?) LIMIT ?, ?"); nested exception is javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: Unknown column 'DTYPE' in 'field list'
Error Code: 1054
Call: SELECT SPONSOR_CODE AS a1, DTYPE AS a2, ACRONYM AS a3, ACTV_IND AS a4, AUDIT_REPORT_SENT_FOR_FY AS a5, CAGE_NUMBER AS a6, COUNTRY_CODE AS a7, CREATE_USER AS a8, DODAC_NUMBER AS a9, DUN_AND_BRADSTREET_NUMBER AS a10, DUNS_PLUS_FOUR_NUMBER AS a11, OBJ_ID AS a12, OWNED_BY_UNIT AS a13, POSTAL_CODE AS a14, ROLODEX_ID AS a15, SPONSOR_NAME AS a16, SPONSOR_TYPE_CODE AS a17, STATE AS a18, UPDATE_TIMESTAMP AS a19, UPDATE_USER AS a20, VER_NBR AS a21 FROM SPONSOR WHERE (DTYPE = ?) LIMIT ?, ?
bind => [3 parameters bound]
Query: ReadAllQuery(referenceClass=SponsorMaintainableBo sql="SELECT SPONSOR_CODE AS a1, DTYPE AS a2, ACRONYM AS a3, ACTV_IND AS a4, AUDIT_REPORT_SENT_FOR_FY AS a5, CAGE_NUMBER AS a6, COUNTRY_CODE AS a7, CREATE_USER AS a8, DODAC_NUMBER AS a9, DUN_AND_BRADSTREET_NUMBER AS a10, DUNS_PLUS_FOUR_NUMBER AS a11, OBJ_ID AS a12, OWNED_BY_UNIT AS a13, POSTAL_CODE AS a14, ROLODEX_ID AS a15, SPONSOR_NAME AS a16, SPONSOR_TYPE_CODE AS a17, STATE AS a18, UPDATE_TIMESTAMP AS a19, UPDATE_USER AS a20, VER_NBR AS a21 FROM SPONSOR WHERE (DTYPE = ?) LIMIT ?, ?")
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:321)
at org.springframework.orm.jpa.DefaultJpaDialect.translateExceptionIfPossible(DefaultJpaDialect.java:120)

我不确定映射子类和继承所有JPA映射的最佳方法。请建议。

共有2个答案

阙佐
2023-03-14

您尚未指定您在ProundnerMaintainableBo中拥有的内容的详细信息,因此很难理解您在那里拥有的内容。

你还没有以正确的方式扩展你的实体。您需要给出如何扩展数据库中的原始表的提示(所有内容都集中在同一个表中,称为< code>SINGLE_TABLE?具有一对一引用的新表称为< code>JOINED?具有新字段的表的副本,称为< code>TABLE_PER_CLASS?)

您应该查看 http://en.wikibooks.org/wiki/Java_Persistence/Inheritance,以了解如何正确实现它。

更新

虽然目前还不太清楚ProunderMaintainableBO实际上在做什么,但从你添加的细节来看,我怀疑原因是你在这里使用了错误的设计模式。如果扩展 JPA 实体 Bean,系统将期望您这样做是为了添加其他字段,因此它还添加了区分数据库中两个实体(超类和子类)的机制。默认情况下,如 @Predrag 它期望表中有一个名为 DTYPE 的字段,以便可以标识行,无论它是超类的实例还是子类(继承不是标准 SQL 支持的内容)。您可以使用其他机制,例如完全独立的表,或者由外键连接在一起的 2 个表,第 2 个表仅添加子类添加的字段。

现在从你所说的,你似乎没有做(或需要)任何这些。如果我理解正确,你正在用你的框架预期的进一步行为来超载实体bean的责任。实体Bean被设计为只是Bean,即数据的载体。如果你扩展它们,JPA明白你这样做是有原因的,添加更多数据(即更多的字段)。你似乎想要的是实体的包装器,以便它也插入到你的框架中。这样,这两个问题就分开了,但仍然联系在一起。

我不知道你的框架对ProstrandMaintainableBo的期望是什么,但我的倾向是你应该使用不同的方法。与其让 SponsorMaintainableBo 扩展 Sponsor,不如将 Sponsor 的实例放在 SponsorMaintainableBo 中,从而将关系从 SponsorMaintainableBo -is-a- Sponsor 更改为 SponsorMaintainableBo -has-a- Sponsor。如果您希望两个实例都绝对耦合,则可以使 Sponsor 成为构造函数参数,并且如下所示不可变:

public class SponsorMaintainableBo 
{
   private final Sponsor sponsor;

   public SponsorMaintainableBo(Sponsor sponsor)
   {
      this.sponsor = sponsor;
   }

   public Sponsor getSponsor()
   {
      return this.sponsor;
   }

   //... rest of the methods expected by the framework
}

如果上述内容还不够,并且框架需要<code>赞助商可维护BO</code>中的一些字段,这些字段与<code>赞助者</code>相同,那么您应该使用Decorator模式。我想您在<code>赞助商合同</code>中已经有了这个,所以您最可能需要做的是:

public class SponsorMaintainableBo implements SponsorContract
{
   private final Sponsor sponsor;

   public SponsorMaintainableBo(Sponsor sponsor)
   {
      this.sponsor = sponsor;
   }

   public Sponsor getSponsor()
   {
      return this.sponsor;
   }

   //... rest of the methods specified by `SponsorContract`

   //... rest of the methods expected by the framework
}

Sponsor合约所需的方法只是将函数调用委托给底层Sponsor实例。

(请注意,完整的装饰器模式旨在将多个实例链接在一起,因此它会将 SponsorContract sponsor 而不是 Sponsor Sponsor Sponsor 添加到您的 SponsorMaintainableBo 中,这样您甚至可以将其他行为链接在实体周围,但我认为您不需要这种复杂程度)

陆畅
2023-03-14

以下是关于JPA实体继承的一些信息。

您必须在实体上配置继承,仅仅扩展类是不够的。如果希望将<code>赞助商可维护BO</code>放在一个单独的表中,则使用<code>继承(strategy=table_PER_CLASS)</code>注释<code>赞助</code>实体。在线上有很多配置不同类型继承的示例。

public enum InheritanceType {
    SINGLE_TABLE,
    JOINED,
    TABLE_PER_CLASS
};

字段列表中的未知列'DTYPE'表示SINGLE_TABLE是默认继承类型,并且您的JPA提供程序正在目标表中查找(默认命名)列DTYPE,以确定实体的确切类型。

 类似资料:
  • 我有一个关于JPA中继承的问题,是否可以使用JOINED策略来实现这个层次结构? 这是我的代码: 在上面的层次结构之后,我尝试使用JPQL进行查询,这是查询: 此代码从主代码运行 当我运行该查询时,会抛出以下错误 导致原因:com . MySQL . JDBC . exceptions . JDBC 4 . MySQL syntaxerrorexception:未知列“employee1_。“字段

  • 问题内容: 我在我的班级结构上定义了一个复合ID,如下所示。不幸的是,我总是收到一个hibernate错误,抱怨找不到的“ part2”: “在实体MoreClass中找不到@IdClass的属性:第2部分” 有人可以帮我解决问题吗?(或者至少在一个有用的jpa / hibernate文档上指向我?) 问题答案: 居然撞到了。 如: 确实可行,我认为这是一个错误。参见https://hiberna

  • 问题内容: 我的数据模型代表法人实体,例如企业或个人。两者都是纳税实体,都具有TaxID,电话号码和邮件地址的集合。 我有一个Java模型,其中有两个扩展抽象类的具体类。抽象类具有两个具体类共有的属性和集合。 我正在 MySQL* 数据库上使用 Hibernate JPA注释,其类如下: * 问题是,和对象需要参考他们的主人,这是一个。hibernate抱怨: 看来这将是一个相当普遍的Java继承

  • 我有一个BaseEntity,当我像这样制作mapper时,它有一个名为Customer的子级: Mapstruct不会自动映射BaseEntity字段。你能告诉我怎么做吗?

  • 我在JPA实体映射方面有问题。我有一些课: A级 类别b Classc *如何解决这个问题?*我还能使用类继承吗?还是另一个解决这个的方法? 谢了。

  • 问题内容: 我有一个实体类和一个基于该实体的子类: 和 我需要发出仅在基类(A)上使用存储过程的本机查询。如果我尝试如下: 我收到有关“在ResultSet中未找到clazz_列”的错误。我假设JPA提供程序添加了此列,以便区分基类和扩展类。我可以通过显式添加clazz列和子类中的所有字段来解决此问题: 其中“ prop1”和“ prop2”是子类B的属性。但是,这似乎是不必要的修改,并且如果子类