jooq record 取数据时是否使用列索引?
Does jooq record use column indexes when fetching data?
我正在调查一个问题,我们看到与 jooq 相关的奇怪异常试图填充生成的记录 class,因为它使用 java.sql.ResultSet::getXXX( int)(基于列索引)获取数据。
我可以分享的堆栈跟踪部分如下所示:
Caused by: java.sql.SQLDataException: Value 'ABC' is outside of valid range for type java.lang.Byte
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:114)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:73)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:92)
at com.mysql.cj.jdbc.result.ResultSetImpl.getObject(ResultSetImpl.java:1423)
at com.mysql.cj.jdbc.result.ResultSetImpl.getByte(ResultSetImpl.java:710)
at com.zaxxer.hikari.pool.HikariProxyResultSet.getByte(HikariProxyResultSet.java)
at org.jooq.tools.jdbc.DefaultResultSet.getByte(DefaultResultSet.java:124)
at org.jooq.tools.jdbc.DefaultResultSet.getByte(DefaultResultSet.java:124)
at org.jooq.impl.CursorImpl$CursorResultSet.getByte(CursorImpl.java:688)
at org.jooq.impl.DefaultBinding$DefaultByteBinding.get0(DefaultBinding.java:1783)
at org.jooq.impl.DefaultBinding$DefaultByteBinding.get0(DefaultBinding.java:1755)
at org.jooq.impl.DefaultBinding$AbstractBinding.get(DefaultBinding.java:871)
at org.jooq.impl.CursorImpl$CursorIterator$CursorRecordInitialiser.setValue(CursorImpl.java:1725)
这肯定是使用错误的列索引导致的列不匹配。
出现此问题是因为我们在不断发展的模式中使用记录,因此底层 table 包含记录定义中不可用的列。
请注意,触发此操作的实际代码是:
jooq.insertInto(TABLE)
.set(TABLE.COL, "ABC")
.returning(TABLE.asterisk())
.fetchOne();
这里让我有点害怕的是,如果它确实在设计上使用了列索引,那将使模式演化变得有些困难(您如何从 运行 应用程序中删除列)。
长话短说(抱歉),问题是:jooq 是否在 jooq-generator 生成的记录中使用列索引,有没有办法使用列名代替?
我注意到的一件事是,当我比较 https://www.jooq.org/doc/3.14/manual/code-generation/codegen-records/ 处的文档时,显示的生成记录与生成器实际生成的记录不匹配。文档显示方法如下:
// Every column generates a setter and a getter
@Override
public void setId(Integer value) {
setValue(BOOK.ID, value);
}
但实际上生成的代码看起来像(取自jOOQ-examples):
/**
* Setter for <code>PUBLIC.BOOK.ID</code>.
*/
public void setId(Integer value) {
set(0, value);
}
顺便说一句,我们正在使用 jooq 3.14.15。
好的,这是本地错误。真正导致这个问题的是我们的代码是这样写的:
jooq.insertInto(TABLE)
.set(TABLE.COL, "ABC")
.returning(TABLE.asterisk())
.fetchOne();
而 TABLE.asterisk()
是什么搞砸了(因为在包含额外列的数据库上它不 return jooq 期望的)。幸运的是,删除它解决了问题,所以我们的代码现在看起来像:
jooq.insertInto(TABLE)
.set(TABLE.COL, "ABC")
.returning()
.fetchOne();
我正在调查一个问题,我们看到与 jooq 相关的奇怪异常试图填充生成的记录 class,因为它使用 java.sql.ResultSet::getXXX( int)(基于列索引)获取数据。
我可以分享的堆栈跟踪部分如下所示:
Caused by: java.sql.SQLDataException: Value 'ABC' is outside of valid range for type java.lang.Byte
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:114)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:73)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:92)
at com.mysql.cj.jdbc.result.ResultSetImpl.getObject(ResultSetImpl.java:1423)
at com.mysql.cj.jdbc.result.ResultSetImpl.getByte(ResultSetImpl.java:710)
at com.zaxxer.hikari.pool.HikariProxyResultSet.getByte(HikariProxyResultSet.java)
at org.jooq.tools.jdbc.DefaultResultSet.getByte(DefaultResultSet.java:124)
at org.jooq.tools.jdbc.DefaultResultSet.getByte(DefaultResultSet.java:124)
at org.jooq.impl.CursorImpl$CursorResultSet.getByte(CursorImpl.java:688)
at org.jooq.impl.DefaultBinding$DefaultByteBinding.get0(DefaultBinding.java:1783)
at org.jooq.impl.DefaultBinding$DefaultByteBinding.get0(DefaultBinding.java:1755)
at org.jooq.impl.DefaultBinding$AbstractBinding.get(DefaultBinding.java:871)
at org.jooq.impl.CursorImpl$CursorIterator$CursorRecordInitialiser.setValue(CursorImpl.java:1725)
这肯定是使用错误的列索引导致的列不匹配。
出现此问题是因为我们在不断发展的模式中使用记录,因此底层 table 包含记录定义中不可用的列。
请注意,触发此操作的实际代码是:
jooq.insertInto(TABLE)
.set(TABLE.COL, "ABC")
.returning(TABLE.asterisk())
.fetchOne();
这里让我有点害怕的是,如果它确实在设计上使用了列索引,那将使模式演化变得有些困难(您如何从 运行 应用程序中删除列)。
长话短说(抱歉),问题是:jooq 是否在 jooq-generator 生成的记录中使用列索引,有没有办法使用列名代替?
我注意到的一件事是,当我比较 https://www.jooq.org/doc/3.14/manual/code-generation/codegen-records/ 处的文档时,显示的生成记录与生成器实际生成的记录不匹配。文档显示方法如下:
// Every column generates a setter and a getter
@Override
public void setId(Integer value) {
setValue(BOOK.ID, value);
}
但实际上生成的代码看起来像(取自jOOQ-examples):
/**
* Setter for <code>PUBLIC.BOOK.ID</code>.
*/
public void setId(Integer value) {
set(0, value);
}
顺便说一句,我们正在使用 jooq 3.14.15。
好的,这是本地错误。真正导致这个问题的是我们的代码是这样写的:
jooq.insertInto(TABLE)
.set(TABLE.COL, "ABC")
.returning(TABLE.asterisk())
.fetchOne();
而 TABLE.asterisk()
是什么搞砸了(因为在包含额外列的数据库上它不 return jooq 期望的)。幸运的是,删除它解决了问题,所以我们的代码现在看起来像:
jooq.insertInto(TABLE)
.set(TABLE.COL, "ABC")
.returning()
.fetchOne();