Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/387.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和JPA避免重复密钥_Java_Mysql_Jpa - Fatal编程技术网

Java 如何使用MySQL和JPA避免重复密钥

Java 如何使用MySQL和JPA避免重复密钥,java,mysql,jpa,Java,Mysql,Jpa,我正在使用JPA/Hibernate和MySQL处理一个Java应用程序,并试图理解正确的方法来做一些看起来应该很简单的事情 目标 目标是:允许两个线程并行运行,每个线程都有自己的事务,当然可以查询,如果找不到,则向数据库中插入唯一的值,并且这样做不会导致MySQL抛出任何异常 因此,每个线程首先执行一个查询以查看该记录是否存在,如果不存在,则插入该记录,然后完成查询。听起来很简单 理论 我认为可以通过在查询上设置LockModeType.悲观_WRITE来消除异常的可能性,因为这将转换为SEL

我正在使用JPA/Hibernate和MySQL处理一个Java应用程序,并试图理解正确的方法来做一些看起来应该很简单的事情

目标

目标是:允许两个线程并行运行,每个线程都有自己的事务,当然可以查询,如果找不到,则向数据库中插入唯一的值,并且这样做不会导致MySQL抛出任何异常

因此,每个线程首先执行一个查询以查看该记录是否存在,如果不存在,则插入该记录,然后完成查询。听起来很简单

理论

我认为可以通过在查询上设置LockModeType.悲观_WRITE来消除异常的可能性,因为这将转换为SELECT。。对于UPDATE,这意味着第一个线程的查询将在记录上设置一个独占写锁,因此第二个线程的查询将阻塞,直到第一个线程提交为止,第二个线程随后将唤醒并能够看到新记录

在直接使用MySQL之后,我意识到我缺少了一些基本的东西,因为第二个线程实际上在查询过程中没有阻塞

实践

我创建了一个如下表:

CREATE TABLE `test`.`A` (
  `id` BIGINT( 20 ) NOT NULL ,
  `name` VARCHAR( 255 ) NOT NULL ,
  PRIMARY KEY ( `id` ) ,
  UNIQUE (`name`)
) ENGINE = InnoDB;
然后在两个单独的窗口X和Y中执行以下命令,每次执行一个命令,先在X中执行,然后在Y中执行:

执行此测试时,X和Y中的每个语句都会立即被接受且无错误,两个语句中的语句3都返回零行,直到Y中的命令4之后出现错误:

其实这并不意外。。。令我意外的是,当我执行命令3时,Y并没有阻塞。一旦两个线程都查询了“琼斯”却什么也没看到,我的想法显然就注定了,因为它们不可能都是对的

我认为选择的重点是。。。对于UPDATE,它在记录上设置了一个排他锁,这将导致Y在语句3上阻塞

问题

我错过了什么?甚至可以在JPA甚至MySQL中做我想做的事情吗

注:

MySQL版本是5.5.23-log MySQL社区服务器GPL 更改为可序列化没有任何帮助。
您缺少的是,AFAIK,第3条语句锁定name='Jones'所在的行,而不是整个表。因为没有这样的行,所以没有任何行被锁定。InnoDB支持,但显然在这种情况下不使用它们。
1  SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
2  BEGIN;
3  SELECT * FROM A WHERE `name`='Jones' FOR UPDATE;
4  INSERT INTO A (`name`) VALUES ('Jones');
5  COMMIT;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction