正如它在DBLookup Mediator的文档中所述,它只返回查询的第一行,如果忽略了其他结果,则会被忽略。
我想知道是否有一种“最好的方法”来运行一个返回多个记录然后处理它们的查询(SELECT * FROM X)。现在有一天我们正在实现实现axis2服务,但还有另一种方法是使用wso2 esb提供的调解器组合来完成这个要求吗?
提前致谢。
圣地亚哥。
答案 0 :(得分:7)
是DBlookup介体不会返回多行。您可以使用两种替代方案。
1)使用WSO2数据服务服务器创建数据服务,并使用调出中介从ESB调用该服务。
2)你可以编写一个类中介来查询数据库中的数据,然后从中创建一个有效负载,然后通过序列发送它。
答案 1 :(得分:2)
为了避免编写其他服务或设置一个完整的WSO2数据服务服务器以克服DB Lookup Mediator的缺点,我扩展了现有的中介,但由于时间限制,他没有将代码贡献给社区。以下是更新的org.apache.synapse.mediators.db.DBLookupMediator的代码。
基本上,它将ResultSet转换为XML格式,并将结果设置为DB_SEARCH_RESULT属性。它也可能需要在竞争条件下进行一些抛光和测试。
package org.apache.synapse.mediators.db;
import org.apache.synapse.MessageContext;
import org.apache.synapse.SynapseException;
import org.apache.synapse.SynapseLog;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.StringWriter;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Connection;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
/**
* Simple database table lookup mediator. Designed only for read/lookup
*/
public class DBLookupMediator extends AbstractDBMediator {
public static final String DB_SEARCH_RESULTS_PROPERTY_NAME = "DB_SEARCH_RESULT";
protected void processStatement(Statement stmnt, MessageContext msgCtx) {
SynapseLog synLog = getLog(msgCtx);
// execute the prepared statement, and extract the first result row and
// set as message context properties, any results that have been specified
Connection con = null;
ResultSet rs = null;
try {
PreparedStatement ps = getPreparedStatement(stmnt, msgCtx);
con = ps.getConnection();
rs = ps.executeQuery();
// convert RS to XML
String rsXML = convertRSToXML(rs);
// add result XML to the Message Context
msgCtx.setProperty(DB_SEARCH_RESULTS_PROPERTY_NAME, rsXML);
// rollback to the beginning of ResultSet to allow standard processing
rs = ps.executeQuery();
if (rs.next()) {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug(
"Processing the first row returned : " + stmnt.getRawStatement());
}
for (String propName : stmnt.getResultsMap().keySet()) {
String columnStr = stmnt.getResultsMap().get(propName);
Object obj;
try {
int colNum = Integer.parseInt(columnStr);
obj = rs.getObject(colNum);
} catch (NumberFormatException ignore) {
obj = rs.getObject(columnStr);
}
if (obj != null) {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Column : " + columnStr +
" returned value : " + obj +
" Setting this as the message property : " + propName);
}
msgCtx.setProperty(propName, obj.toString());
} else {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebugWarn("Column : " + columnStr +
" returned null Skip setting message property : " + propName);
}
}
}
} else {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Statement : "
+ stmnt.getRawStatement() + " returned 0 rows");
}
}
} catch (SQLException e) {
handleException("Error executing statement : " + stmnt.getRawStatement() +
" against DataSource : " + getDSName(), e, msgCtx);
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {}
}
if (con != null) {
try {
con.close();
} catch (SQLException ignore) {}
}
}
}
private String convertRSToXML(ResultSet rs) throws SQLException {
ResultSetMetaData rsmd = rs.getMetaData();
// create XML document
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder;
Document doc = null;
try {
docBuilder = dbfac.newDocumentBuilder();
doc = docBuilder.newDocument();
} catch (ParserConfigurationException pce) {
throw new SynapseException("Failed to transform Resultset to XML", pce);
}
// create Root element
Element rootElement = doc.createElement("table");
doc.appendChild(rootElement);
while (rs.next()) {
// add Record element
Element recordElement = doc.createElement("record");
rootElement.appendChild(recordElement);
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
String columnName = rsmd.getColumnName(i);
String columnValue = rs.getObject(i).toString();
// add Field element
Element fieldElement = doc.createElement("field");
fieldElement.appendChild(doc.createTextNode(columnValue));
// set Name attribute to Field element
Attr nameAttr = doc.createAttribute("name");
nameAttr.setValue(columnName);
fieldElement.setAttributeNode(nameAttr);
// add Field to Record
recordElement.appendChild(fieldElement);
}
}
//Output the XML
String xmlString = null;
try {
//set up a transformer
TransformerFactory transfac = TransformerFactory.newInstance();
Transformer trans = transfac.newTransformer();
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
trans.setOutputProperty(OutputKeys.INDENT, "yes");
//create string from XML tree
StringWriter sw = new StringWriter();
StreamResult result = new StreamResult(sw);
DOMSource source = new DOMSource(doc);
trans.transform(source, result);
xmlString = sw.toString();
} catch (javax.xml.transform.TransformerException te) {
throw new SynapseException("Failed to transform Resultset to XML", te);
}
return xmlString;
}
}
答案 2 :(得分:2)
您无法使用DBLookUp介体检索多行。但您可以使用数据服务服务器(DSS)并创建查询。然后,您可以使用call mediator或send mediator调用它们。在WSO2 EI中,DSS也可用。请参阅文档
https://docs.wso2.com/display/EI611/Generating+a+Data+Service https://docs.wso2.com/display/EI611/Exposing+Data+as+a+REST+Resource
此处数据可以作为REST(在DSS资源中)或SOAP(在DSS操作中)公开。
答案 3 :(得分:0)
只需使用DBSelect Mediator https://github.com/ichakios/dbselect-wso2-mediator 易于使用并返回JSON结果