使用 MariaDB 10.4 和 eclipselink 的 java @GeneratedValue (strategy = GenerationType.IDENTITY) 问题

Posted

技术标签:

【中文标题】使用 MariaDB 10.4 和 eclipselink 的 java @GeneratedValue (strategy = GenerationType.IDENTITY) 问题【英文标题】:Problems with java @GeneratedValue (strategy = GenerationType.IDENTITY) using MariaDB 10.4 and eclipselink 【发布时间】:2020-08-24 16:54:24 【问题描述】:

我正在使用 Java EE 开发 REST Web 服务:Glassfish 5.0 (build 25)、MariaDB 10.4 和 eclipselink (JPA 2.1) 这是我的代码:

命令行表

CREATE TABLE IF NOT EXISTS `cooldb`.`commande_line` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `quantity` INT NULL,
  `discount` INT NULL,
  `dish` INT NOT NULL,
  `commande` INT NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `id_UNIQUE` (`id` ASC),
  INDEX `fk_commande_line_dish1_idx` (`dish` ASC),
  INDEX `fk_commande_line_commande1_idx` (`commande` ASC),
  CONSTRAINT `fk_commande_line_dish1`
    FOREIGN KEY (`dish`)
    REFERENCES `cooldb`.`dish` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `fk_commande_line_commande1`
    FOREIGN KEY (`commande`)
    REFERENCES `cooldb`.`commande` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;

persistance.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
  <!-- Define Persistence Unit -->
  <persistence-unit name="my_persistence_unit" transaction-type="JTA">
    <jta-data-source>jdbc/mariadb</jta-data-source>
    <class>com.yac.model.Address</class>
    <class>com.yac.model.Commande</class>
    <class>com.yac.model.CommandeLine</class>
    <class>com.yac.model.Dish</class>
    <class>com.yac.model.Dishtype</class>
    <class>com.yac.model.Ingredient</class>
    <class>com.yac.model.Payement</class>
    <class>com.yac.model.Profil</class>
    <class>com.yac.model.Restaurant</class>
    <class>com.yac.model.Userapp</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
    </properties>
  </persistence-unit>
</persistence>

命令行实体

public class CommandeLine implements Serializable 

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Column(name = "quantity")
    private Integer quantity;
    @Column(name = "discount")
    private Integer discount;
    @JoinColumn(name = "commande", referencedColumnName = "id")
    @ManyToOne(optional = false)
    private Commande commande;
    @JoinColumn(name = "dish", referencedColumnName = "id")
    @ManyToOne(optional = false)
    private Dish dish;
    //Constructor
    // Setter and Getter

命令行网络服务

@Stateless
@Path("commandeline")
public class CommandeLineFacadeREST extends AbstractFacade<CommandeLine> 

    @PersistenceContext(unitName = "my_persistence_unit")
    private EntityManager em;

    public CommandeLineFacadeREST() 
        super(CommandeLine.class);
    

    @POST
    @Override
    @Consumes(MediaType.APPLICATION_JSON)
    public void create(CommandeLine entity) 
        super.create(entity);
    

    @Override
    protected EntityManager getEntityManager() 
        return em;
    

抽象立面

public abstract class AbstractFacade<T> 

    private Class<T> entityClass;

    public AbstractFacade(Class<T> entityClass) 
        this.entityClass = entityClass;
    

    protected abstract EntityManager getEntityManager();

    public void create(T entity) 
        getEntityManager().persist(entity);
    

问题是当我使用 Postman 测试我的 Web 服务并尝试使用 POST 请求插入记录时 这是我收到的错误消息:

Local Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.0.v20170811-d680af5): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: (conn=158) Table 'cooldb.sequence' doesn't exist
Error Code: 1146
Call: UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
    bind => [2 parameters bound]
Query: DataModifyQuery(name="SEQ_GEN_SEQUENCE" sql="UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?") ...

当我使用@GeneratedValue (strategy = GenerationType.IDENTITY) 时,我不明白为什么 SEQUANCE 会出现问题。 当我使用 @GeneratedValue (strategy = GenerationType.SEQUENCE) 进行更改并使用以下脚本创建表时:

CREATE SEQUENCE SEQUANCE START WITH 1 INCREMENT BY 1;

通过应用如下所示的解决方案:Table 'customerjpa.sequence' doesn't exist JPA 但同样的问题

提前感谢您的帮助。

【问题讨论】:

正在使用什么数据库平台类?检查它是否支持 IDENTITY 和/或 SEQUENCE,否则 EclipseLink 将默认为表排序。如果您不知道使用的平台类(您可以使用目标数据库持久性属性指定它),则应该在部署期间测试数据源以检测数据库时记录它。 另请注意,IDENTITY != SEQUENCE。如果要在数据库中创建序列“SEQUANCE”并希望使用它,则必须在 JPA 中使用指向序列定义的 GeneratedValue 和 SequenceGenerator 注释来定义序列本身。见wiki.eclipse.org/EclipseLink/UserGuide/JPA/…和wiki.eclipse.org/EclipseLink/UserGuide/JPA/… 感谢您的回答,我使用的是 MariaDB 10.4,它同时支持 IDENTITY 和 SEQUENCE,但我不明白的是它支持 IDENTITY 但它好像总是在 SEQUENCE 中配置尽管如此,我还是选择了身份。请原谅我的英语水平 DatabasePlatform 是一个 Eclipselink 类,它被扩展以提供 DB 特定的行为。您在持久性单元中使用的平台类必须具有内置的标识和序列支持,否则它可能默认使用序列或表序列。指定的目标数据库平台是什么? eclipse.org/eclipselink/documentation/2.4/jpa/extensions/… 非常感谢克里斯。 【参考方案1】:

使用 Chris cmets 解决了这个问题,我只需在我的 persistence.xml 文件中添加以下行:

<property name="eclipselink.target-database" value="mysql"/>

非常感谢克里斯。 所以我的新persistence.xml文件是:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
    <!-- Define Persistence Unit -->
    <persistence-unit name="my_persistence_unit" transaction-type="JTA">
        <jta-data-source>jdbc/mariadb</jta-data-source>
        <class>com.yac.model.Address</class>
        <class>com.yac.model.Commande</class>
        <class>com.yac.model.CommandeLine</class>
        <class>com.yac.model.Dish</class>
        <class>com.yac.model.Dishtype</class>
        <class>com.yac.model.Ingredient</class>
        <class>com.yac.model.Payement</class>
        <class>com.yac.model.Profil</class>
        <class>com.yac.model.Restaurant</class>
        <class>com.yac.model.Userapp</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <property name="eclipselink.target-database" value="MySQL"/>
        </properties>
    </persistence-unit>
</persistence>

我只是在MariaDB基于它的那一刻的persistence.xml文件中指定了MySQL中的数据库平台,因为列表中没有提到MariaDB。 如果有其他建议,请不要犹豫,谢谢。

【讨论】:

【参考方案2】:

另一种解决方案: 将?useMysqlMetadata=true 添加到您的 JDBC URL 连接中,如下所示:

<property name="URL" value="jdbc:mariadb://[HOST]:[PORT]/[DB NAME]?useMysqlMetadata=true"/>

这将使 MariaDB 使用 MySQL 元数据,然后 eclipselink 会将其检测为 MySQL。

【讨论】:

以上是关于使用 MariaDB 10.4 和 eclipselink 的 java @GeneratedValue (strategy = GenerationType.IDENTITY) 问题的主要内容,如果未能解决你的问题,请参考以下文章

二进制安装mariadb10.4

[转]更新升级到MariaDB 10.4

MariaDB10.4以上版本安装

mariadb10.4

MySQL 8.0与MariaDB 10.4,谁更易于填坑补锅?

计算 MariaDB 10.4 中 json 列的数组中有多少行具有嵌套值