DS.*_*DS. 11 java sql oracle spring spring-boot
我正在尝试从 > 4000 个字符的字符串(在 file_data 绑定变量中提供)创建一个 Clob,以在下面的 Oracle SELECT 谓词中使用:
myQuery=
select *
from dcr_mols
WHERE flexmatch(ctab,:file_data,'MATCH=ALL')=1;
Run Code Online (Sandbox Code Playgroud)
如果我在 file_data 中添加 TO_CLOB() ,它就会使 varchar 的臭名昭著的 Oracle 4k 限制失败(对于 <4k 字符串很好)。错误(在 SQL Developer 中)是:
ORA-01460: unimplemented or unreasonable conversion requested
01460. 00000 - "unimplemented or unreasonable conversion requested"
Run Code Online (Sandbox Code Playgroud)
仅供参考 flexmatch 功能用于搜索分子,这里有一个描述:http : //help.accelrysonline.com/ulm/onelab/1.0/content/ulm_pdfs/direct/developers/direct_2016_developersguide.pdf
函数本身有点复杂,但本质是第二个参数必须是一个clob。所以我的问题是如何将超过 4000 个字符的 Java 字符串 bind_variable 转换为 sql(或 Java)中的 clob。
我在 Java (Spring boot 2) 中尝试了以下方法(在插入 clobs 时有效),使用:
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("file_data", fileDataStr,Types.CLOB);
jdbcNamedParameterTemplate.query(myQuery,parameters,…
Run Code Online (Sandbox Code Playgroud)
这种方法应该可以工作,但它会失败,并出现一个复杂的 flexmatch 错误,仅供参考:
SQL state [99999]; error code [29902]; ORA-29902: error in executing ODCIIndexStart() routine\nORA-20100:
MDL-0203: Unable to read from CLOB (csfrm=1, csid=873):
ORA-22922: nonexistent LOB value\nMDL-0021: Unable to copy LOB to string\nMDL-1051: Molstructure search query is not a valid molecule\nMDL-0976:
Molecule index search initialization failed\nORA-06512: at \"C$MDLICHEM80.MDL_MXIXMDL\", line 329\nORA-06512: at \"C$MDLICHEM80.MDL_MXIXMDL\", line 309\n; nested exception is java.sql.SQLException:
ORA-29902: error in executing ODCIIndexStart() routine\nORA-20100: MDL-0203: Unable to read from CLOB (csfrm=1, csid=873):
ORA-22922: nonexistent LOB value\nMDL-0021: Unable to copy LOB to string\nMDL-1051: Molstructure search query is not a valid molecule\nMDL-0976:
Molecule index search initialization failed\nORA-06512: at \"C$MDLICHEM80.MDL_MXIXMDL\", line 329\nORA-06512: at \"C$MDLICHEM80.MDL_MXIXMDL\", line 309\n"
Run Code Online (Sandbox Code Playgroud)
请注意,我正在使用 SpringBoot 2,但我无法使用 OracleConnection(从我的 Spring NamedParametersJdbcTemplate 对象获得)获得任何方法来工作(即使在 clobs <4k 上),所以我怀疑我做了一些愚蠢的事情。我试过了:
@Autowired
NamedParameterJdbcTemplate jdbcNamedParameterTemplate;
OracleConnection conn = this.jdbcNamedParameterTemplate.getJdbcTemplate().getDataSource().getConnection().unwrap(OracleConnection.class);
Clob myClob = conn.createClob();
myClob.setString( 1, fileDataStr);
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("file_data", myClob,Types.CLOB);
Run Code Online (Sandbox Code Playgroud)
应用程序属性:
spring.datasource.url=jdbc:oracle:thin:@//${ORA_HOST}:${ORA_PORT}/${ORA_SID}
spring.datasource.username=${ORA_USER}
spring.datasource.password=${ORA_PASS}
Run Code Online (Sandbox Code Playgroud)
请注意,如果我去老学校并使用非弹簧连接加上 PreparedStatement,它可以正常工作,它有一个 setClob() 方法:
OracleDataSource ods = new OracleDataSource();
String url ="jdbc:oracle:thin:@//" + ORA_HOST +":"+ORA_PORT +"/"+ORA_SID;
ods.setURL(url);
ods.setUser(user);
ods.setPassword(passwd);
Connection conn = ods.getConnection();
Clob myClob=conn.createClob();
PreparedStatement ps = conn.prepareStatement("select dcr_number from dcr_mols WHERE flexmatch(ctab,?,'MATCH=ALL')=1");
myClob.setString(1,myMol);
ps.setClob(1,myClob);
ResultSet rs =ps.executeQuery();
Run Code Online (Sandbox Code Playgroud)
但我更喜欢 Java 或 Sql 中的 Spring 2 解决方案。任何帮助,建议表示赞赏。
我不得不恢复使用PreparedStatement,但我通过从Spring获取连接并使用apache commons BeanListHandler将ResultSet映射到对象列表,对正常实现进行了一些改进
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
@Autowired
DataSource dataSource;
List<MyDao> myMethod(String fileData){
String myQuery="select * from dcr_mols WHERE flexmatch(ctab,?,'MATCH=ALL')=1";
try {
Connection conn = this.dataSource.getConnection() // Get connection from spring
Clob myClob = conn.createClob(); // Open a dB clob
myClob.setString( 1, fileData); // add data to clob
PreparedStatement ps = conn.prepareStatement(myQuery);
ps.setClob(1,myClob); // Add a clob into the PreparedStatement
ResultSet rs =ps.executeQuery(); // Execute the prepared statement
//ResultSetHandler<List<MyDao>> handler = new BeanListHandler<MyDao>(MyDao.class); // Define the ResultSet handler
ResultSetHandler<List<MyDao>> handler = new BeanListHandler<MyDao>(MyDao.class, new BasicRowProcessor(new GenerousBeanProcessor())); // This is better than the above handler , because GenerousBeanProcessor removes the requirement for the column names to exactly match the java variables
List<MyDao> myDaoList = handler.handle(rs); // Map ResultSet to List of MyDao objects
}catch (Exception e) {
e.printStackTrace();
}
return myDaoList;
}
Run Code Online (Sandbox Code Playgroud)