Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在hibernate中使用复合键扩展实体类_Java_Hibernate - Fatal编程技术网

Java 在hibernate中使用复合键扩展实体类

Java 在hibernate中使用复合键扩展实体类,java,hibernate,Java,Hibernate,在我们公司,我们有一个奇怪的数据库模型,无法修改,因为很多系统都使用它。据我们所知,我们有一个直接的java应用程序,它与hibernate连接到数据库并加载数据。每个表都有一个xml映射文件 数据库的奇怪之处在于我们没有任何主键。大多数表都有一个包含多个列的唯一索引 现在我们想要使用应用服务器(jboss)和ejb模型。所以我创建了一个这样的类: @Entity @Table (name = "eakopf_t") public class Eakopf implements

在我们公司,我们有一个奇怪的数据库模型,无法修改,因为很多系统都使用它。据我们所知,我们有一个直接的java应用程序,它与hibernate连接到数据库并加载数据。每个表都有一个xml映射文件

数据库的奇怪之处在于我们没有任何主键。大多数表都有一个包含多个列的唯一索引

现在我们想要使用应用服务器(jboss)和ejb模型。所以我创建了一个这样的类:

   @Entity
   @Table (name = "eakopf_t")
   public class Eakopf implements Serializable {

       @Embeddable
       public static class EakopfId implements Serializable { 

            private String mandant;

            private String fk_eakopf_posnr;

            // I removed here the getters and setters to shorten it up

       }

       @Id
       private EakopfId id;

       private String login;

       // I removed the getters and setters here as well    
   }
这很好用

因为我们的客户有不同版本的数据库模式,所以我考虑在每次数据库版本更改时扩展这个类。因此,我们用java创建的每个接口都可以决定使用哪个版本的表

这是扩展表类

   @Entity
   @Table (name = "eakopf_t")
   public class Eakopf6001 extends Eakopf implements Serializable {

        private String newField;

        // getters and setters
   }
如果我使用Eakopf(基本版本),如果我这样做,它是有效的:

EakopfId id = new EakopfId();
id.setMandant("001");
id.setFk_eakopf_posnr("ABC");
Eakopf kopf = (Eakopf) em.find(Eakopf.class, id);
但如果我这样做:

EakopfId id = new EakopfId();
id.setMandant("001");
id.setFk_eakopf_posnr("ABC");
Eakopf6001 kopf = (Eakopf6001) em.find(Eakopf6001.class, id);
出现了这种例外情况

javax.ejb.EJBException: javax.persistence.PersistenceException: 
org.hibernate.WrongClassException: Object with id: 
de.entity.Eakopf$EakopfId@291bfe83 was not of the specified subclass:  
de.entity.Eakopf (Discriminator: null)
有人有主意吗

许多问候,
Hauke

这样做意味着休眠,即在一个表中存储两种不同类型的实体。如果使用鉴别器列,这是可能的。但如果我理解正确,您只需要表中的一种实体:Eakopf6001。在这种情况下,它的基类应该用
@MappedSuperClass
注释,而不是用
@Entity
注释

我建议创建一个用
@mappedenty
注释的类(我们称之为BaseEakopf)和两个实体:EaKopf和EaKopf6001,每个实体都有一组附加字段。根据要使用的实体,在映射类列表中包含另一个实体


我个人的观点是,如果你有多个版本的应用程序,它们应该使用相同的实体,但字段不同。您的版本控制系统将负责这些多个版本,而不是您的源代码(即,每个版本的应用程序都有一组源文件,而不是所有可能的版本都有一组源文件)。

我们有一个包含三个部分的eakopf\t表。现在我为客户开发了一个接口,我知道只需要这三个字段,所以我可以使用Eakopf.java。几周后,我们向表中添加了一个新字段,我为不同的客户创建了另一个接口,对于该接口,我需要所有四个字段。我的想法是扩展eakopf.java类,并将新字段放在扩展类(eakopf6001.java)上。一个是第二个接口(对于具有此附加字段的客户),我使用eakopf6001.java。最好的方法是将这个新字段添加到eakopf.java中。但是如果我为数据库模式没有第四个字段的“第一个”客户进行更新,我会遇到麻烦,因为hibernate找不到该字段。这是一个好的做法吗?是否适合声明所有基本实体并创建扩展这些实体的模型?