EntityManager操作顺序(EntityManager operations order)
我最近遇到了一个有趣的问题。 我在项目JPA + Hibernate + EJB中使用。 该问题涉及在同一事务中保存和删除实体。 使用的数据库表具有在两列上定义的唯一约束。
我所做的是删除实体调用
entityManager.remove();
然后,新实体在与唯一约束中使用的列关联的两个属性中添加相同的值,但在其他属性中使用不同的值:
entityManager.persist();
这两个操作在单个事务中执行,并按照上述顺序执行。 先移除,再加上第二。 然而,似乎在违反唯一约束时以颠倒的顺序执行操作。 看起来在删除前一个实体之前添加了新实体。
显然,我可以打电话
entityManager.flush()
删除后,然后不违反约束。 但是,在这种情况下,数据会在整个事务提交之前保存到数据库中。 这不是一个理想的行为。 如果在刷新之后出现任何问题,并且事务将被标记为回滚,则无论如何都将删除该实体。
我认为操作顺序与添加到事务中的操作顺序相同。 从我的例子可以看出事实并非如此。
删除后没有刷新或提交事务有没有办法解决问题?
谢谢。
I have run into interesting issue recently. I use in the project JPA + Hibernate + EJB. The issue concerns saving and deleting entities in the same transaction. Database table which is used has an unique constraint defined on two columns.
What I do is removing entity calling
entityManager.remove();
then the new entity is added with the same values in two properties associated with columns used in the unique constraint but different values in other properties using:
entityManager.persist();
Those two operations are carried out in a single transaction and are executed in the order as presented above. Removal first, addition second. However it seems that the operations are executed in the inverted order as unique constraint is violated. It looks like the new entity is added before removing the previous one.
Obviously, I can call
entityManager.flush()
after removal and then constraint is not violated. However in this case the data is saved to the database before the whole transaction commits. That is not a desirable behavior. If anything goes wrong after flush and transaction will be marked for rollback, the entity will be deleted anyway.
I thought that order of operations is the same as they were added to the transaction. From my example it turns out that it is not.
Is there any way to solve the issue without flushing or committing the transaction after delete?
Thank you.
原文:https://stackoverflow.com/questions/20284027
最满意答案
我终于明白了这里的实际行为。 这不是调用未定义的行为,而是定义您不想要的行为。
cin >> position;
这试图读取你的12位数字,它不适合int,所以读取失败。 因为格式错误失败,12位数字仍保留在缓冲区中,因此循环中的下一次传递尝试再次读取它。
当您打算读取键盘输入时,请始终使用
cin::getline()
。cin
的错误/清除逻辑不是为了重新同步键盘输入,而是为了重新同步从无法读取错误消息的生成器输入的输入。 将来,当您尝试将cin
与管道一起使用时,最好的解决方案是检查cin::fail()
并保存程序(如果它已设置)。I finally understand the actual behavior here. This is not invoking undefined behavior but rather defined behavior you don't want.
cin >> position;
This tried to read your 12 digit number, which didn't fit into an int, so the read failed. Because it failed on a format error, the 12 digit number remained in the buffer, so the next pass around the loop tried to read it again.
Always use
cin::getline()
when you intend to read keyboard input. The error/cleanup logic incin
is not designed to resync keyboard input, but rather to resync input piped from a generator that can't read your error messages. In the future, when you try to usecin
with a pipe, the best solution is to checkcin::fail()
and bail the program if it ever gets set.
相关问答
更多-
c语言之后还可以学什么[2022-05-01]
c++ -
根据语言规范,迭代化学中的空条件等同于true条件。 6.5.3 for语句 1 for语句 for(for-init-statement condition opt ; expression opt )语句 相当于 { for-init-statement while ( condition ) { statement expression ; } } ... 2可以省略条件和表达式中的任何一个或两个。 缺失条件使隐含的while子句等同于while(true) 。 所以,循 ...
-
我终于明白了这里的实际行为。 这不是调用未定义的行为,而是定义您不想要的行为。 cin >> position; 这试图读取你的12位数字,它不适合int,所以读取失败。 因为格式错误失败,12位数字仍保留在缓冲区中,因此循环中的下一次传递尝试再次读取它。 当您打算读取键盘输入时,请始终使用cin::getline() 。 cin的错误/清除逻辑不是为了重新同步键盘输入,而是为了重新同步从无法读取错误消息的生成器输入的输入。 将来,当您尝试将cin与管道一起使用时,最好的解决方案是检查cin::fail( ...
-
正如其他答案所说,这是因为它没有签名和全部。 我会告诉你一个优雅的方式来做你想做的事情与一个无符号的整数。 unsigned int i=10; while(i --> 0) printf("Hello:%u\n", i+1); 这个-->有时被称为去运算符。 但事实上只是--和> 。 如果你改变间距,你会得到 while( i-- > 0 ) MY2C As other answers said, it's because it's unsigned and all. I will tell you ...
-
这是部分答案。 我不明白这部分“......基于它是否是双重”PDRcount“或不是。” 这里是使用dplyr库的PDR!= 2的情况的部分答案。 在任何计算之前,我还通过在crossdata变量上使用dput简化了数据输入。 crossdata1<-structure(list(PDR = c(1, 2, 3, 4, 5, 2, 1, 2, 3, 4, 5, 2, 1, 2, 3, 4, 5, 2, 1, 2, 3, 4, 5, 2 ...
-
循环在C帮助!(Loop in C help!)[2022-04-28]
也许是一个setjmp循环? 这很特别。 static jmp_buf buf; int i = 0; if ( setjmp(buf) < end ) { /* do stuff */ longjmp(buf, i++); } A setjmp loop perhaps? That is pretty special. static jmp_buf buf; int i = 0; if ( setjmp(buf) < end ) { /* do stuff */ l ... -
C无限循环(C infinite do while loop)[2022-04-07]
总是检查scanf()的返回值: int result; do { printf("How long is your shower(in minutes)?:"); result = scanf("%d", &minutes); if(result != 1) break; } while (minutes < 1); 较短的版本(如果只需要一次扫描): printf("How long is your shower(in minutes)?:"); while ... -
For循环需要永远运行(For loop takes forever to run)[2022-03-22]
很难知道你的真实数据是什么样的,但是沿着这条线 full <- strptime(cloudFull[,1], '%d.%m.%Y %H:%M') ref <- strptime(clouds[,1], '%d.%m.%Y %H:%M') ## ref <- sort(ref) cloudsFull[, 2:3] <- clouds[findInterval(full, ref), 2:3] 使用findInterval()将问题转换为线性扩展而非二次扩展的问题。 Its hard to know wha ... -
C ++做循环建议(C++ Do while loop advice)[2020-04-22]
夫妇的事情要注意。 你有用户输入一个字符的选择,所以让userChoice一个字符。 请注意,在这种情况下do-while如何用于输入验证。 我更改了额外的while循环,并在末尾使用了分号来表示条件语句。 您可以用开关“菜单驱动程序”替代if和ifs。 这是您想要的工作程序。 如果您希望在整个条件语句中使用do-while而不是将其用作输入验证,那么将其用于所有条件语句并检查,而不是C. #include#include using namespace std; ... -
C ++:循环条件连续执行时,循环体永远不会执行(C++: While loop condition executes continuously, loop body never executes)[2022-04-02]
当然我是盲目的,原因是在“while”之后错误的分号! 编译器认为没有循环体,只是重复执行“无”。 我读到的循环体,编译器只是认为是一个未命名的/匿名的范围,在循环之后,所以它永远不会被执行。 Of course I am blind, and the reason is the errant semicolon after the "while"! The compiler thinks there is no loop body, and just executes "nothing" repeated ...