MySQL 上的 @GeneratedValue 多态抽象超类 [英] @GeneratedValue polymorphic abstract superclass over MySQL

查看:29
本文介绍了MySQL 上的 @GeneratedValue 多态抽象超类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用 Hibernate 和 MySQL 的 Spring MVC 应用程序中,我有一个抽象超类 BaseEntity,它管理模型中所有其他实体的 ID 值.id 字段使用 @GeneratedValue.每当我的代码尝试保存扩展 BaseEntity 的任何子类时,我都会遇到问题.问题在于为 @GeneratedValue 选择了 GenerationType.

In a Spring MVC application using Hibernate and MySQL, I have an abstract superclass BaseEntity that manages the values of the IDs for all the other entities in the model. The id field uses @GeneratedValue. I am encountering a problem whenever my code tries to save any of the subclasses that extend BaseEntity. The problem comes with the choice of GenerationType for the @GeneratedValue.

在我的代码中 BaseEntity 的子类尝试保存到底层 MySQL 数据库的每个地方,我收到以下错误:

At every place in my code where a subclass of BaseEntity tries to save to the underlying MySQL database, I get the following error:

ERROR SqlExceptionHelper - Table 'docbd.hibernate_sequences' doesn't exist  

我在 SO 和 google 上阅读了许多关于此的帖子,但它们要么处理其他数据库(不是 MySQL),要么不处理抽象超类.我无法通过使用 GenerationType.IDENTITY 解决问题,因为我使用抽象超类来管理模型中所有实体的 id 字段.同样,我不能使用 GenerationType.SEQUENCE 因为 MySQL 不支持序列.

I have read many postings about this on SO and on google, but they either deal with other databases (not MySQL) or they do not deal with abstract superclasses. I cannot solve the problem by using GenerationType.IDENTITY because I am using an abstract superclass to manage id fields for all entities in the model. Similarly, I cannot use GenerationType.SEQUENCE because MySQL does not support sequences.

那么我该如何解决这个问题?

So how do I solve this problem?

这是BaseEntity.java的代码:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    protected Integer id;

    public void setId(Integer id) {this.id = id;}
    public Integer getId() {return id;}

    public boolean isNew() {return (this.id == null);}

}

以下是扩展 BaseEntity 的实体之一的代码示例:

Here is an example of the code for one of the entities that extends BaseEntity:

@Entity
@Table(name = "ccd")
public class CCD extends BaseEntity{
    //other stuff
}

这是 DDL:

CREATE TABLE IF NOT EXISTS ccd(
  id int(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  #other stuff
)engine=InnoDB;SHOW WARNINGS;

这是DAO中的JPQL代码:

Here is the JPQL code in the DAO:

    @Override
    @Transactional
    public void saveCCD(CCD ccd) {
    if (ccd.getId() == null) {
        System.out.println("[[[[[[[[[[[[ about to persist CCD ]]]]]]]]]]]]]]]]]]]]");
        this.em.persist(ccd);
        this.em.flush();
    }
    else {
        System.out.println("]]]]]]]]]]]]]]]]]] about to merge CCD [[[[[[[[[[[[[[[[[[[[[");
        this.em.merge(ccd);
        this.em.flush();
    }
} 

<小时>

在这种情况下我不能使用 @MappedSuperClass 的原因是我需要有 ManyToOne 关系,允许多个子类型互换使用.以下面的 AccessLog 类为例.它有一个 actor_entity 和一个 target_entity.可以有多种类型的actor 实体和多种类型的目标实体,但它们都继承自BaseEntity.这种继承使得 MySQL 中底层的 accesslogs 数据表只有一个 actor_entity_id 字段和一个 target_entity_id 字段,而不必有多个字段用于每个.当我将 BaseEntity 上面的 @Entity 更改为 @MappedSuperClass 时,会抛出一个不同的错误,指示 AccessLog 找不到 <代码>基础实体.BaseEntity 需要 @Entity 注释以使 AccessLog 具有多态属性.


The reason I cannot use @MappedSuperClass in this situation is that I need to have ManyToOne relationships that allow for multiple subtypes to be used interchangeably. Look at the AccessLog class below as an example. It has an actor_entity and a target_entity. There can be many types of actor entities and many types of target entities, but they all inherit from BaseEntity. This inheritance enables the underlying accesslogs data table in MySQL to just have one actor_entity_id field and just one target_entity_id field instead of having to have several fields for each. When I change @Entity above BaseEntity to @MappedSuperClass, a different error gets thrown indicating that AccessLog cannot find BaseEntity. BaseEntity needs @Entity annotation in order for AccessLog to have polymorphic properties.

@Entity
@Table(name = "accesslogs")
public class AccessLog extends BaseEntity{

    @ManyToOne
    @JoinColumn(name = "actorentity_id")
    private BaseEntity actor_entity;

    @ManyToOne
    @JoinColumn(name = "targetentity_id")
    private BaseEntity target_entity;

    @Column(name="action_code")
    private String action;
    //getters, setters, & other stuff
}

<小时>

第二次

根据 JBNizet 的建议,我创建了一个 hibernate_sequences 表如下:


SECOND

As per JBNizet's suggestion, I created a hibernate_sequences table as follows:

CREATE TABLE IF NOT EXISTS hibernate_sequences(
  sequence_next_hi_value int(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
)engine=InnoDB;SHOW WARNINGS;

但现在我收到以下错误:

But now I am getting the following error:

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'sequence_name' in 'where clause'  

这是导致错误的hibernate sql,接下来是堆栈跟踪的下两行:

Here is the hibernate sql causing the error, followed by the next 2 lines of the stack trace:

Hibernate: select sequence_next_hi_value from hibernate_sequences where sequence_name = 'BaseEntity' for update
ERROR MultipleHiLoPerTableGenerator - HHH000351: Could not read or init a hi value
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'sequence_name' in 'where clause'

我该如何解决这个问题?

How do I resolve this?

推荐答案

因为您使用 TABLE 标识符生成器,​​所以您需要创建该表.如果您没有使用 增强标识符生成器,您可能会使用 MultipleHiLoPerTableGenerator.

Because you use the TABLE identifier generator you need to have that table created. If you are not using the enhanced identifier generators, chances are you are going to use the MultipleHiLoPerTableGenerator.

MultipleHiLoPerTableGenerator 可以为所有表标识符生成器使用一张表.

The MultipleHiLoPerTableGenerator can use one table for all table identifier generators.

我的建议是从集成测试中获取表 ddl,以防您使用 hbmddl 构建测试模式.如果您使用 flyway 或 liquibase 进行测试,则可以添加 maven 插件生成 ddl 架构.

My suggestion is to grab the table ddl from your integration tests, in case you use hbmddl to build the test schema. If you use flyway or liquibase for testing, you can add a maven plugin to generate the ddl schema.

获得架构后,您需要执行确切的 create table 命令并将其添加到您的 MySQL 数据库中.

Once you have the schema, you need to take the exact create table command and make add it to your MySQL database.

这篇关于MySQL 上的 @GeneratedValue 多态抽象超类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆