JDBC 4.0 (Java SE 6, JSR-221) 引入 java.sql.SQLXML 介面,標準化映射 SQL:2003 XML 數據類型。主流數據庫支援情況:
XMLTypexmlXMLxml (需擴展)JSON 或 TEXT 替代// Connection 創建 SQLXML 對象
SQLXML sqlxml = conn.createSQLXML();
// 寫入 XML 數據(三種方式)
sqlxml.setString(xmlString); // 1. 字符串
sqlxml.setBinaryStream().write(xmlBytes); // 2. 二進制流
sqlxml.setCharacterStream().write(xmlChars); // 3. 字符流
// 綁定到 PreparedStatement
ps.setSQLXML(1, sqlxml); // 參數索引 1
// 讀取 ResultSet 中的 XML
SQLXML sqlxml = rs.getSQLXML("xml_column"); // 或 getSQLXML(1)
String xml = sqlxml.getString(); // 1. 字符串
InputStream is = sqlxml.getBinaryStream(); // 2. 二進制流
Reader reader = sqlxml.getCharacterStream(); // 3. 字符流
// 進階:轉換為 DOM/SAX/StAX/JAxB
DOMResult dom = new DOMResult();
sqlxml.getSource(DOMSource.class); // 獲取 Source
// 或
sqlxml.setResult(DOMResult.class); // 設置 Result
Document doc = (Document) dom.getNode();
public class XmlDbDemo {
static final String[] ARTICLES = {
"First John Short. ",
"Second Mary Another. ",
"Third John Last. "
};
public static void main(String[] args) throws Exception {
// 假設使用支援 JDBC 4.0 XML 的數據庫(如 Derby 10.14+ / Oracle / SQL Server)
try (Connection conn = DriverManager.getConnection(url, user, pwd)) {
createTable(conn);
insertXml(conn);
queryXml(conn);
}
}
static void createTable(Connection conn) throws SQLException {
try (Statement stmt = conn.createStatement()) {
stmt.execute("CREATE TABLE articles (id INT PRIMARY KEY, content XML)");
}
}
static void insertXml(Connection conn) throws SQLException {
String sql = "INSERT INTO articles (id, content) VALUES (?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
for (int i = 0; i < ARTICLES.length; i++) {
ps.setInt(1, i + 1);
SQLXML sqlxml = conn.createSQLXML();
sqlxml.setString(ARTICLES[i]);
ps.setSQLXML(2, sqlxml);
ps.addBatch();
}
ps.executeBatch();
}
}
static void queryXml(Connection conn) throws SQLException {
String sql = "SELECT id, content FROM articles";
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
int id = rs.getInt("id");
SQLXML sqlxml = rs.getSQLXML("content");
// 方式一:直接獲取字符串
String xml = sqlxml.getString();
System.out.println("ID=" + id + " XML=" + xml);
// 方式二:解析為 DOM 文檔
DOMResult domResult = new DOMResult();
sqlxml.setResult(DOMResult.class);
Document doc = (Document) domResult.getNode();
// XPath 查詢等...
}
}
}
}
原文使用 Derby 10.2(不支援 SQLXML),現代版本 (10.14+) 已支援。若數據庫驅動未完全實現 SQLXML,常見回退方案:
CLOB/TEXT:ps.setString(1, xml) / rs.getString(1)。ps.setBytes(1, xml.getBytes(StandardCharsets.UTF_8))。// 寫入:對象 → XML → SQLXML
JAXBContext ctx = JAXBContext.newInstance(Article.class);
SQLXML sqlxml = conn.createSQLXML();
Result result = sqlxml.setResult(JAXBResult.class);
Marshaller marshaller = ctx.createMarshaller();
marshaller.marshal(article, result);
ps.setSQLXML(1, sqlxml);
// 讀取:SQLXML → XML → 對象
SQLXML sqlxml = rs.getSQLXML(1);
Source source = sqlxml.getSource(DOMSource.class);
Unmarshaller unmarshaller = ctx.createUnmarshaller();
Article article = (Article) unmarshaller.unmarshal(source);
setBinaryStream()/getBinaryStream() 避免全量載入內存。java.sql.SQLXML 為 JDBC 層面提供了標準化的 XML 類型訪問介面,支援字符串、流、DOM/SAX/StAX/JAXB 多種交互方式。雖然各數據庫廠商實現程度不一,但在支援原生 XML 類型的場景下(Oracle XMLType、SQL Server xml),使用 SQLXML 可避免手動序列化/反序列化,實現類型安全、流式處理與標準化綁定。