Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.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 @MySQL上GeneratedValue多态抽象超类_Java_Mysql_Database_Hibernate_Jpa - Fatal编程技术网

Java @MySQL上GeneratedValue多态抽象超类

Java @MySQL上GeneratedValue多态抽象超类,java,mysql,database,hibernate,jpa,Java,Mysql,Database,Hibernate,Jpa,在使用Hibernate和MySQL的Spring MVC应用程序中,我有一个抽象超类BaseEntity,它管理模型中所有其他实体的ID值。id字段使用@GeneratedValue。每当我的代码试图保存扩展BaseEntity的任何子类时,我都会遇到问题。问题在于为@GeneratedValue选择GenerationType 在代码中,BaseEntity的子类试图保存到底层MySQL数据库的每个地方,我都会遇到以下错误: ERROR SqlExceptionHelper - Table

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

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

ERROR SqlExceptionHelper - Table 'docbd.hibernate_sequences' doesn't exist  
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'sequence_name' in 'where clause'  
我在某某和谷歌上读过很多关于这方面的帖子,但它们要么处理其他数据库(不是MySQL),要么不处理抽象超类。使用
GenerationType.IDENTITY
无法解决此问题,因为我使用的是抽象超类来管理模型中所有实体的
id
字段。类似地,我不能使用
GenerationType.SEQUENCE
,因为MySQL不支持序列

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

下面是
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
的一个实体的代码示例:

@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代码:

    @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
的原因是我需要有
manytone
关系,允许多个子类型互换使用。以下面的
AccessLog
类为例。它有一个
actor\u实体
和一个
target\u实体
。可以有多种类型的参与者实体和多种类型的目标实体,但它们都继承自
BaseEntity
。这种继承使MySQL中的底层
accesslogs
数据表只有一个
actor\u entity\u id
字段和一个
target\u entity\u id
字段,而不必每个字段都有几个字段。当我将
@Entity
上面的
BaseEntity
更改为
@MappedSuperClass
时,会抛出另一个错误,指示
AccessLog
无法找到
BaseEntity
BaseEntity
需要
@Entity
注释,以便
AccessLog
具有多态属性

@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表,如下所示:

CREATE TABLE IF NOT EXISTS hibernate_sequences(
  sequence_next_hi_value int(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
)engine=InnoDB;SHOW WARNINGS;
但现在我得到了以下错误:

ERROR SqlExceptionHelper - Table 'docbd.hibernate_sequences' doesn't exist  
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'sequence_name' in 'where clause'  
下面是导致错误的hibernate sql,然后是堆栈跟踪的下两行:

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'

我该如何解决这个问题?

真是一团糟
AUTO_INCREMENT
是MySQL的隐藏序列。根本的问题是,
MySQL
不能同时插入和返回PK,但是Hibernate在插入新实体时需要这样做

您遇到的问题:

  • 如果Hibernate保存一个新实体,他会尝试直接将id设置为新的EntityBean。因此,在hibernate将新元组保存到表之前,hibernate必须读取数据库将使用的ID
  • 如果有多台服务器访问数据库,则应让hibernate的会话工厂决定使用内置序列(自动递增)或让hibernate决定(
    GenerationType.AUTO
    /
    GenerationType.IDENTITY
    )保留PK的开放范围有多大(DB架构师的工作)。(一个数据库大约有20台服务器,所以在一个使用良好的表上,我们使用的PK距离为+100)。如果只有一台服务器可以访问数据库
    GenerationType。表应正确
  • Hibernate必须使用
    max(*)+1自己计算下一个id,但是:

    • 如果两个请求同时请求
      max(*)+1
      ,结果相同,该怎么办?右:最后一次尝试插入将失败
    因此,您需要在数据库中有一个存储最后一个表PK的表
    LAST\u id
    。如果要添加一个,必须执行以下步骤:

  • 开始读取乐观事务
  • 从最后的\u id中选择MAX(地址\u id)
  • 将最大值存储在java变量中,即:$OldID
  • $NewID=$OldID+1。(+100在悲观锁中)
  • 更新上一个\u id设置地址\u id=
    $newID
    其中地址\u id=
    $oldID
  • 提交读乐观事务
  • 如果提交成功,请将
    $newID
    存储到要保存的HibernateBean中的
    setID()
  • 最后让Hibernate调用insert
  • 这是我唯一知道的方法


    顺便说一句:如果数据库支持表之间的继承,例如
    PostgreSQL
    Oracle

    ,则Hibernate实体只能使用继承,因为您使用需要创建该表的表标识符生成器。如果您没有使用,那么您很可能会使用

    MultipleHiLoPerTableGenerator可以对所有表标识符生成器使用一个表

    我的建议是从集成测试中获取表ddl,以防使用hbmddl构建测试模式。如果使用flyway或liquibase进行测试,则可以添加一个来生成ddl模式


    一旦有了模式,就需要使用确切的CREATETABLE命令并将其添加到MySQL数据库。

    您真的不应该使用实体继承来实现这一点。BaseEntity应该用
    @Mappedsuperclass
    注释,而不是用
    @Entity
    注释。是的,您正在寻找映射的超类。经验法则:当您需要对基类型执行查询时,使用继承,因为您不知道将返回哪些具体实例。为什么您有一个
    BaseEntity
    ,用于管理模型中所有其他实体的ID值?@JBNizet我刚刚在我的原始帖子末尾添加了一个编辑