Java和MySQL事务

Java和MySQL事务,java,mysql,jdbc,transactions,Java,Mysql,Jdbc,Transactions,我有一个java应用程序,在多台计算机上运行,它们都连接到同一个MySQL数据库。我需要事务以确保数据库正确更新 我在释放锁时遇到问题。代码如下: public boolean bookSeats(int numeroSala, Calendar dataOra, List<Posto> posti) { JDBConnection connection = JDBConnection.getDbConnection(); Connection conn = conn

我有一个java应用程序,在多台计算机上运行,它们都连接到同一个MySQL数据库。我需要事务以确保数据库正确更新

我在释放锁时遇到问题。代码如下:

public boolean bookSeats(int numeroSala, Calendar dataOra, List<Posto> posti) {
    JDBConnection connection = JDBConnection.getDbConnection();
    Connection conn = connection.conn;
    java.sql.Date javaSqlDate = new java.sql.Date(dataOra.getTime().getTime());
    java.sql.Time javaSqlTime = new java.sql.Time(dataOra.getTime().getTime());

    try {
        conn.setAutoCommit(false);
        conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
    } catch (SQLException e) {
        e.printStackTrace();
    }

    try
    {
        Posto p = null;
        ListIterator<Posto> itr = posti.listIterator();
        PreparedStatement stmt = null;
        stmt = conn.prepareStatement(
            "INSERT INTO sala?_tickets " + 
            "(giornoSpettacolo, orarioSpettacolo, fila, posto) " + 
            "VALUES (?, ?, ?, ?)");

        stmt.setInt(1, numeroSala);
        while(itr.hasNext())
        {
            p = itr.next();
            stmt.setString(2, javaSqlDate.toString()); // giornoSpettacolo
            stmt.setString(3, javaSqlTime.toString()); // orarioSpettacolo
            stmt.setInt(4, p.getFila()); // fila
            stmt.setInt(5, p.getNumero()); // posto
            stmt.addBatch();
        }

        stmt.executeBatch();

        conn.commit();
        return true;
    }
    catch (SQLException e) {
        e.printStackTrace();
    }

    return false;
}
public boolean bookSeats(整数、日历数据、列表posti){
JDBConnection connection=JDBConnection.getDbConnection();
连接连接=Connection.conn;
java.sql.Date javaSqlDate=new java.sql.Date(dataOra.getTime().getTime());
java.sql.Time javaSqlTime=new java.sql.Time(dataOra.getTime().getTime());
试一试{
连接设置自动提交(错误);
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
}捕获(SQLE异常){
e、 printStackTrace();
}
尝试
{
Posto p=null;
ListIterator itr=posi.ListIterator();
PreparedStatement stmt=null;
stmt=conn.prepareStatement(
“插入sala?_门票”+
“(giornoSpettacolo、orarioSpettacolo、fila、posto)”
“值(?,?,?)”;
stmt.setInt(1,numeroSala);
while(itr.hasNext())
{
p=itr.next();
stmt.setString(2,javaSqlDate.toString());//giornoSpettacolo
stmt.setString(3,javaSqlTime.toString());//orarioSpettacolo
stmt.setInt(4,p.getFila());//fila
stmt.setInt(5,p.getNumero());//posto
stmt.addBatch();
}
stmt.executeBatch();
conn.commit();
返回true;
}
捕获(SQLE异常){
e、 printStackTrace();
}
返回false;
}
此方法工作正常,但当我同时尝试在另一台计算机上执行此操作时,即使
conn.commit()
已完成,也会出现死锁错误


一旦我关闭第一个应用程序,另一个应用程序就可以运行该方法而不会出现死锁错误。提交似乎没有释放锁?

您可以参考如何使用裸JDBC进行事务。希望有帮助。

您应该始终在
finally
块中执行
conn.close()
,以确保释放方法使用的所有资源。

根据MySQL文档,关于可序列化:

此级别类似于可重复读取,但InnoDB隐式地转换所有 要选择的纯SELECT语句。。。如果自动提交,则锁定共享模式 它是残疾的


您可能希望在提交后尝试重新启用自动提交,或者尝试连接。可重复读取。

是,按照第一个答案关闭连接。但是,另外,如果您可以将上述代码放入“syncronized”方法中,它将确保一次只有一个线程可以访问它

除此之外,只需看看下面的链接,其中讨论了JDBC中的死锁处理


谢谢,这解决了我的问题!