【发布时间】:2014-02-27 06:31:27
【问题描述】:
我正在从事一个项目,该项目从字符串中解析文本单元(称为“ngrams”)并将它们存储在 MySQL 数据库中。
在 MySQL 中,如果 ngram 尚不存在,我有以下过程应该将 ngram 存储在特定数据集(表)中并返回 ngram 的 id:
CREATE PROCEDURE `add_ngram`(IN ngram VARCHAR(400), IN dataset VARCHAR(128), OUT ngramId INT)
BEGIN
-- try get id of ngram
SET @s = CONCAT('SELECT `id` INTO @ngramId FROM `mdt_', dataset, '_b1` WHERE `ngram` = ''', ngram, ''' LIMIT 1');
PREPARE stm FROM @s;
EXECUTE stm;
SET ngramId = @ngramId;
-- if id could not be retrieved
IF ngramId IS NULL THEN BEGIN
-- insert ngram into dataset
SET @s = CONCAT('INSERT INTO `mdt_', dataset, '_b1`(`ngram`) VALUES (''', ngram, ''')');
PREPARE stm FROM @s;
EXECUTE stm;
SET ngramId = LAST_INSERT_ID();
END;
END IF;
END$$
一个数据集表只有两列:id,一个用作主键的自动递增 int,ngram,一个用作唯一索引的varchar(400)。
在我的 scala 应用程序中,我有一个方法,它接收一个字符串,将其拆分为 ngram,然后通过将 ngram 传递给上述过程来返回 ngram id 的 Seq:
private def processNgrams(text: String, dataSet: String) {
val ids = parser.parse(text).map(ngram => {
val query = dbConn.prepareCall("CALL add_ngram(?,?,?)")
query.setString(1, ngram)
query.setString(2, dataSet)
query.registerOutParameter(3, java.sql.Types.INTEGER)
query.executeUpdate()
dbConn.commit()
val id = query.getInt(3)
Debug(s"parsed ngram - id: $id ${" " * (3 - id.toString.length)}[ $ngram ]")
id
}
}
上述代码中的dbConn 是java.sql.Connection 的一个实例,并且自动提交设置为false。
执行此操作时,我注意到数据库中存储的 ngram 非常少。以下是上述方法中的调试语句打印出来的内容:
因此,有多个彼此明显不同的 ngram 似乎具有从该过程返回的相同 id。如果我查看数据库表,我可以看到例如 ngram“i”的 id 为“1”,但似乎紧随其后插入的 ngrams 也返回了一个 id 为“1”。我在表格中查找的其他 ngram 也是如此。这让我相信过程调用可能会被缓存?
我已经尝试了很多事情,例如在方法外部创建准备好的调用并重用它并每次调用 clearParameters,每次在方法内部创建一个新调用(如上所示),甚至休眠调用之间的线程,但似乎没有任何区别。
我还通过在 MySQL 客户端中手动运行查询来测试该过程,它似乎运行良好,尽管我的程序执行查询的速度比我手动执行的快得多,所以这可能会有所不同。
我不完全确定这是调用过程中的 JDBC 问题还是过程中的 MySQL 问题。我是 scala 和 MySQL 程序的新手,所以如果这真的很简单,我无法理解,请原谅我。
【问题讨论】:
标签: mysql scala stored-procedures jdbc