【问题标题】:Hibernate generate wrong sql query for inserting child entityHibernate为插入子实体生成错误的sql查询
【发布时间】:2021-11-24 19:31:41
【问题描述】:

我以这种方式有一个一对多的实体关联模型:


@Entity
@Table(name = "father")
public class Father {

    @Id
    @GeneratedValue
    @Column(columnDefinition = "BINARY(16)", updatable = false)
    @Type(type="org.hibernate.type.UUIDBinaryType")
    private UUID id;

    ...

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "father", orphanRemoval = true)
    private List<AbstractChild> children = new ArrayList<>();

    ...
    

}




@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
        name="type",
        discriminatorType = DiscriminatorType.INTEGER,
        columnDefinition = "TINYINT(1) NOT NULL")
@Table(
    name = "child",
    uniqueConstraints = @UniqueConstraint(columnNames = {"type", "name", "father_id"})
)
@IdClass(Child.class)
public abstract class AbstractChild implements Serializable {

    @Id
    @Column(nullable = false)
    protected Locale locale;

    @Id
    @ManyToOne(fetch = FetchType.LAZY)
    protected Father father;

    @Id
    @Column(name = "type", insertable = false, updatable = false)
    protected short mediaType;

    ...

}



@Entity
@DiscriminatorValue("1")
public class ConcreteChildOne extends AbstractChild {

    @Lob
    private String content;

    ...

}



@Entity
@DiscriminatorValue("2")
public class ConcreteChildTwo extends AbstractChild {

    @Column(name = "path")
    private String path;

    ...

}

一切似乎都很好,但是当我保存一个有孩子的父亲实体时,生成的 sql 中的值顺序是错误的。

父亲的插入查询没问题

insert 
    into
        father
        (description, name, id) 
    values
        (?, ?, ?)

有那些绑定参数

  • 绑定参数 [1] 作为 [VARCHAR] - [描述]
  • 绑定参数 [2] 作为 [VARCHAR] - [name]
  • 绑定参数 [3] 为 [BINARY] - [3bfac6e0-08ec-4f6b-a62a-5626ee6ab0e5]

但是对孩子的插入查询是错误的

    insert 
    into
        tourist_informations
        (content, type, father_id, locale) 
    values
        (?, ?, ?, ?)
  • 绑定参数 [1] 为 [CLOB] - [这是我的内容]
  • 绑定参数 [2] 为 [BINARY] - [3bfac6e0-08ec-4f6b-a62a-5626ee6ab0e5]
  • 绑定参数 [3] 为 [SMALLINT] - [1]
  • 绑定参数 [4] 作为 [VARCHAR] - [en_EN]

创建数据库的sql是

    create table father (
        id BINARY(16) not null,
        description varchar(255),
        name varchar(150) not null,
        primary key (id)
    ) engine=InnoDB
    
    create table child (
        type TINYINT(1) NOT NULL ,
        locale varchar(255) not null,
        path varchar(255),
        content longtext,
        father_id BINARY(16) not null,
        primary key (father_id, type, locale)
    ) engine=InnoDB
    
    alter table tourist_informations 
       add constraint FKpem984v0clq1bsvubkkynoq7x 
       foreign key (father_id) 
       references father (id)

有人知道为什么顺序错误? 谢谢你的建议。

【问题讨论】:

  • 你能发布用于创建表的 SQL 吗?
  • 刚刚用创建的 sql 脚本编辑了问题
  • 好的,Child 类的代码?另外,name="media_type" 中是否定义了不连贯性而不是 name="type"
  • 这是一个错字,代码是正确的。子类只有 equals 和 hashCode 方法。我正在使用 mariadb 作为数据库;这可能是mariadb jdbc客户端的错误吗?版本是 2.7.3
  • 请发布 Child 类以便更好地理解。

标签: hibernate jpa spring-data-jpa mariadb hibernate-mapping


【解决方案1】:

我认为你的映射是错误的。应该是:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "father", orphanRemoval = true)
private List<AbstractChild> children = new ArrayList<>();

【讨论】:

    【解决方案2】:

    我找到了一张有效的地图:

    
    @Entity
    @Table(name = "father")
    public class Father {
    
        @Id
        @GeneratedValue
        @Column(columnDefinition = "BINARY(16)", updatable = false)
        @Type(type="org.hibernate.type.UUIDBinaryType")
        private UUID id;
    
        ...
    
        @OneToMany(cascade = CascadeType.ALL, mappedBy = "father", orphanRemoval = true)
        private List<AbstractChild> children = new ArrayList<>();
    
        ...
        
    
    }
    
    
    @Embeddable
    public class ChildID implements Serializable {
    
        @Column(name = "type")
        protected short type;
    
        @Column(nullable = false)
        protected String name;
    
        @Column(columnDefinition = "BINARY(16)", name = "father_id")
        @Type(type="org.hibernate.type.UUIDBinaryType")
        private UUID fatherId;
    
        ...
    
    }
    
    
    
    @Entity
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(
            name="type",
            discriminatorType = DiscriminatorType.INTEGER,
            columnDefinition = "TINYINT(1) NOT NULL")
    @DiscriminatorOptions(force = true, insert = false)
    @Table(
        name = "child",
        uniqueConstraints = @UniqueConstraint(columnNames = {"type", "name", "father_id"})
    )
    @IdClass(Child.class)
    public abstract class AbstractChild implements Serializable {
    
        @EmbeddedId
        private ChildID id;
    
        public AbstractChild() {
            this.id = new ChildID();
        }
    
        @ManyToOne(fetch = FetchType.LAZY)
        @MapsId("fatherId")
        protected Father father;
    
        ...
    
    }
    
    
    
    @Entity
    @DiscriminatorValue("1")
    public class ConcreteChildOne extends AbstractChild {
    
        @Lob
        private String content;
    
        public ConcreteChildOne() {
            super();
            this.getId().type = 1;
        }
    
        ...
    
    }
    
    
    
    @Entity
    @DiscriminatorValue("2")
    public class ConcreteChildTwo extends AbstractChild {
    
        @Column(name = "path")
        private String path;
    
        public ConcreteChildTwo() {
            super();
            this.getId().type = 2;
        }
    
        ...
    
    }
    
    

    当然,您可以使用委托方法改进代码,在嵌入的 id 上设置类型,或者使用 super() 将其传递给构造函数,但这些都是细节。

    希望答案能有所帮助 谢谢大家的回答

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-28
      • 2011-04-13
      • 1970-01-01
      • 2017-12-25
      • 2021-01-31
      • 1970-01-01
      相关资源
      最近更新 更多