jci*_*ity 15 java mysql transactions jdbi dropwizard
我在使用IDBI处理事务时遇到了很多麻烦.我们正在使用dropwizard框架,简单的插入,更新,选择和删除已找到工作,但现在我们似乎无法使事务正常工作.这是我正在尝试的
public class JDb {
private JustinTest2 jTest2 = null;
private Handle dbHandle = null;
public JDb(final IDBI idbi) {
try {
dbHandle = idbi.open();
dbHandle.getConnection().setAutoCommit(false);
jTest2 = dbHandle.attach(JustinTest2.class);
} catch( SQLException e ) {
}
}
public void writeJustin(final int styleId, final int eventId) {
dbHandle.begin();
int num = jTest2.findByStyleId(styleId);
try {
jTest2.doStuff(styleId, eventId);
dbHandle.commit();
} catch(Exception e) {
dbHandle.rollback(); // Never rolls back here, always get the inserted row!
}
num = jTest2.findByStyleId(styleId);
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的JustinTest2课程
public abstract class JustinTest2 {
@SqlUpdate("INSERT INTO jTest2 (styleId, jNum) VALUES (:styleId, :jNum)")
public abstract void insert(@Bind("styleId") int styleId, @Bind("jNum") int jNum);
@SqlQuery("SELECT count(styleId) " +
"FROM jTest2 " +
"WHERE styleId=:styleId")
public abstract int findByStyleId(@Bind("styleId") int styleId);
public int doStuff(int styleId, int eventId) throws Exception{
int count = findByStyleId(styleId);
insert(styleId, eventId);
count = findByStyleId(styleId);
if(count==1) {
throw new Exception("Roll back");
}
return count;
}
}
Run Code Online (Sandbox Code Playgroud)
我也尝试过实现writeJustin:
public void writeJustin(final int styleId, final int eventId) throws Exception {
int rows_updated = jTest2.inTransaction(new Transaction<Integer, JustinTest2>() {
@Override
public Integer inTransaction(JustinTest2 transactional, TransactionStatus status) throws Exception {
jTest2.insert(styleId, eventId);
int num = transactional.findByStyleId(styleId);
try {
if(num == 1) throw new Exception("BOOM");
} catch (Exception e) {
transactional.rollback();
throw e;
}
num = transactional.findByStyleId(styleId);
return num;
}
});
}
Run Code Online (Sandbox Code Playgroud)
我似乎无法让事务回滚,在每种方式中插入的行总是在回滚之后,无论我是直接尝试通过句柄还是我使用inTransaction(从我的理解不应该提交事务,如果异常在回调中被抛出)任何人都知道我可能做错了什么?
Pat*_*k M 27
这与您的问题相关,但我将其添加为答案,因为您的问题在Google搜索结果中很高,并且没有很多示例.
使用JDBI v2,您可以使用@Transaction注释来简化代码.只需使用注释修饰public方法,JDBI将在后台处理begin,commit和rollback.
public abstract class JustinTest2 {
@SqlUpdate("INSERT INTO jTest2 (styleId, jNum) VALUES (:styleId, :jNum)")
protected abstract void insert(@Bind("styleId") int styleId, @Bind("jNum") int jNum);
@SqlQuery("SELECT count(styleId) " +
"FROM jTest2 " +
"WHERE styleId=:styleId")
protected abstract int findByStyleId(@Bind("styleId") int styleId);
@Transaction
public int doStuff(int styleId, int eventId) throws Exception{
int count = findByStyleId(styleId);
insert(styleId, eventId);
count = findByStyleId(styleId);
if(count==1) {
throw new Exception("Roll back");
}
return count;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我使insert和findByStyleId方法受到保护; 从下public执行他们可以在交易完成在一起(在公共doStuff方法); 不是private因为JDBI自动生成的实现无法覆盖它们(因为方法private abstract不适用于那个原因 - 你要强制编译器接受没有主体的方法).
您还可以TransactionIsolationLevel在注释中指定a 来覆盖数据库的默认值.
@Transaction(TransactionIsolationLevel.REPEATABLE_READ)
Run Code Online (Sandbox Code Playgroud)
我想通了.事实证明我正在测试的表是使用MyISAM而不是InnoDB作为存储引擎.MyISAM不支持交易.我使用InnoDB重建了表,上面的代码运行正常.
对于任何不知道的人,您可以通过以下方式查看表正在使用的引擎:
show create table <tablename>;
Run Code Online (Sandbox Code Playgroud)
应该看到类似的东西:
CREATE TABLE `grades` (
`id` int(11) NOT NULL,
`percent` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Run Code Online (Sandbox Code Playgroud)