使用 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) 问题的主要内容,如果未能解决你的问题,请参考以下文章