【问题标题】:Insert of subclass inserts into superclass table将子类插入到超类表中
【发布时间】:2018-10-21 13:56:43
【问题描述】:

我是一个初学者,我在 hibernate 中做一些继承练习。我有两个类,一个超类和一个子类,它们都是通过继承 SINGLE_TABLE 连接的。

问题是,当我想将子类的对象持久化到数据库时,hibernate 会尝试在超类的表中创建一个“INSERT”。这会产生错误“'字段列表'中的未知列“颜色””,因为超类的表中不存在“颜色”列。

我没有映射两个表之间的关联。我应该这样做吗?我的教科书没有具体说明。不然怎么办?

超类: --------------------------------------------------------- ----------------------

  @Entity
    @Table(name="autos")
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(
            name = "pe_discriminador",
            discriminatorType = DiscriminatorType.STRING)
    @DiscriminatorValue(value = "a1")

    public class auto implements Serializable{

    @Id  
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private int id;
    @Column(name="marca")
    private String marca;
    @Column(name="modelo")
    private String modelo;

    public auto(){

    }

        public auto(int id, String marca, String modelo) {
            this.id = id;
            this.marca = marca;
            this.modelo = modelo;
        }



        public long getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getMarca() {
            return marca;
        }

        public void setMarca(String marca) {
            this.marca = marca;
        }

        public String getModelo() {
            return modelo;
        }

        public void setModelo(String modelo) {
            this.modelo = modelo;
        }

        @Override
        public String toString() {
            return "auto{" + "id=" + id + ", marca=" + marca + ", modelo=" + modelo + '}';
        }





    }

SUBCLASS ----------------------------------------------------------------------

@Entity
@Table(name="autos")
@DiscriminatorValue("a2")
public class auto2 extends auto{

    int id2;
    public auto2() {
    }


    public auto2(int id2, String color, double motor, int id, String marca, String modelo) {
     this.id2=id2; 
     this.color=color; 
     this.motor=motor; 
     setMarca(marca); 
     setModelo(modelo);
    }



@Column(name="color")
private String color;
@Column(name="motor")
private double motor;



    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public double getMotor() {
        return motor;
    }

    public void setMotor(double motor) {
        this.motor = motor;
    }

    @Override
    public String toString() {
        return "auto2{"  + ", color=" + color + ", motor=" + motor + '}';
    }
    }

休眠错误日志:------------------------------------------- ---------------

INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
oct 21, 2018 10:22:51 AM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
oct 21, 2018 10:22:52 AM org.hibernate.cfg.AnnotationBinder bindClass
WARN: HHH000139: Illegal use of @Table in a subclass of a SINGLE_TABLE hierarchy: entidades.auto2
Hibernate: insert into autos (marca, modelo, color, id2, motor, pe_discriminador) values (?, ?, ?, ?, ?, 'a2')
oct 21, 2018 10:22:54 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 1054, SQLState: 42S22
oct 21, 2018 10:22:54 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Unknown column 'color' in 'field list'
Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not execute statement
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:178)
    at org.hibernate.dialect.identity.GetGeneratedKeysDelegate.executeAndExtract(GetGeneratedKeysDelegate.java:57)
    at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:42)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3072)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3663)
    at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:645)
    at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:282)
    at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:263)
    at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:317)
    at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:359)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:292)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:200)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:131)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
    at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
    at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
    at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:709)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:701)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:696)
    at testeo.TestAuto.main(TestAuto.java:225)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'color' in 'field list'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
    at com.mysql.jdbc.Util.getInstance(Util.java:408)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:944)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3978)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3914)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2530)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2683)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2495)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1903)
    at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2124)
    at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2058)
    at com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5158)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2043)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175)
    ... 22 more

【问题讨论】:

    标签: java sql hibernate jpa


    【解决方案1】:

    0) 答案前传

    在我们开始回答之前,我想指出一点:示例代码看起来有点乱。例如,缩进可能更直观,并且通常以PascalCase 命名类(即camelCase,首字母大写)。许多风格指南可以帮助你(例如Google)。相信我:它让编码更有趣!

    1) 实际答案

    使用 hibernate 保存类层次结构有多种策略:

    • 单表:层次结构中的所有类都保存在一个表中(可能包含许多列)
    • 每个类的表:每个具体类都保存在自己的表中
    • Joined:每个具体类和超类都被持久化到一个表中

    您选择了SINGLE_TABLE 继承策略。这意味着,属于此层次结构的所有类和子类都将保存在一个表中 (table per class hierarchy)。

    根据您对错误的描述,您的数据库架构似乎适合不同的策略。

    a) 每类策略表

    如果你有,每个具体子类一个表(这意味着:抽象超类没有表),尝试:

    @Entity
    @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
    public class Auto {
    

    b) 加入策略

    如果抽象超类和您的具体子类各有一个表,则使用:

    @Entity
    @Inheritance(strategy = InheritanceType.JOINED)
    public class Auto{
        @Id
        private int id;
    
        // getters, setters, ...
    }
    
    @Entity
    @PrimaryKeyJoinColumn(name = "id")
    public class RaceAuto extends Auto {
        // ...
    }
    

    在这两种情况下,您都不需要鉴别器列。如果您想使用注释,Hibernate documentation 可能会产生误导。我发现这个blog post 很有帮助。

    【讨论】:

    • 那言过其实了 :) 但是@DiegoCaballero,如果你喜欢这篇文章,你介意点赞吗?多谢! :)
    • 我尝试为您的帖子投票,但收到以下消息:“声望低于 15 人的投票已被记录”
    • 我稍后再试。
    • 哦,当然,对不起。在这种情况下也是如此:欢迎使用 Stack Overflow! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多