You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring项目中基于MyBatis读取Oracle SYS.XMLTYPE字段及解析内部指定字段值的方法

Spring + MyBatis 处理 Oracle XMLTYPE 字段完全指南

我来帮你搞定这个在Spring项目里用MyBatis操作Oracle XMLTYPE字段的问题,分字段映射到实体和XML内容提取两个核心部分来讲解:

一、将XMLTYPE字段映射到Java实体

这里有两种简单可行的方案,你可以根据自己的场景选择:

方案1:SQL层面直接转换(推荐,无需额外代码)

在查询SQL中,利用Oracle内置函数getClobVal()把XMLTYPE字段转成字符串,直接映射到实体类的String类型字段。

1. 定义Student实体类

public class Student {
    private String name;
    // 用String存储XML内容,后续解析更方便
    private String xmlContent;

    // 省略getter、setter和toString方法
}

2. 编写Mapper接口和XML映射文件

Mapper接口:

public interface StudentMapper {
    // 根据姓名查询学生(包含XML字段)
    Student selectStudentByName(String name);
}

Mapper XML文件:

<mapper namespace="com.example.mapper.StudentMapper">
    <select id="selectStudentByName" resultType="com.example.entity.Student">
        SELECT 
            name,
            -- 把XMLTYPE字段转成字符串
            xml_column.getClobVal() AS xml_content
        FROM student_table
        WHERE name = #{name}
    </select>
</mapper>

这样查询出来的xml_content会直接映射到Student的xmlContent字段,非常省心。

方案2:自定义MyBatis类型处理器(适合复杂场景)

如果不想在SQL里做转换,可以自定义TypeHandler来处理Oracle XMLTYPE和Java类型的互相转换。

1. 自定义类型处理器

import oracle.xdb.XMLType;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class OracleXmlTypeHandler extends BaseTypeHandler<String> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        // 把Java字符串转成Oracle XMLTYPE
        XMLType xmlType = XMLType.createXML(ps.getConnection(), parameter);
        ps.setObject(i, xmlType);
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 把Oracle XMLTYPE转成Java字符串
        XMLType xmlType = (XMLType) rs.getObject(columnName);
        return xmlType != null ? xmlType.getStringVal() : null;
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        XMLType xmlType = (XMLType) rs.getObject(columnIndex);
        return xmlType != null ? xmlType.getStringVal() : null;
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        XMLType xmlType = (XMLType) cs.getObject(columnIndex);
        return xmlType != null ? xmlType.getStringVal() : null;
    }
}

2. 注册类型处理器并配置ResultMap

在MyBatis配置文件中注册:

<configuration>
    <typeHandlers>
        <typeHandler handler="com.example.handler.OracleXmlTypeHandler" 
                     javaType="String" 
                     jdbcType="OTHER"/>
    </typeHandlers>
</configuration>

然后在Mapper XML中用ResultMap指定字段映射:

<mapper namespace="com.example.mapper.StudentMapper">
    <resultMap id="StudentResultMap" type="com.example.entity.Student">
        <result property="name" column="name"/>
        <result property="xmlContent" column="xml_column" 
                typeHandler="com.example.handler.OracleXmlTypeHandler"/>
    </resultMap>

    <select id="selectStudentByName" resultMap="StudentResultMap">
        SELECT name, xml_column FROM student_table WHERE name = #{name}
    </select>
</mapper>

二、从XML内容中提取指定字段

拿到XML字符串后,有3种常用的提取方式,按需选择:

方式1:JDK原生DOM解析(无依赖)

适合简单场景,不需要额外引入依赖:

import org.w3c.dom.Document;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;

public class XmlParseUtil {

    /**
     * 从XML字符串中提取指定标签的内容
     * @param xmlContent XML字符串
     * @param tagName 要提取的标签名
     * @return 标签内容,失败返回null
     */
    public static String extractTagContent(String xmlContent, String tagName) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(new InputSource(new StringReader(xmlContent)));
            return doc.getElementsByTagName(tagName).item(0).getTextContent();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

使用示例:

Student student = studentMapper.selectStudentByName("张三");
String age = XmlParseUtil.extractTagContent(student.getXmlContent(), "age");
String gender = XmlParseUtil.extractTagContent(student.getXmlContent(), "gender");

方式2:Jackson XML解析(推荐,优雅高效)

如果需要提取多个字段,推荐把XML映射成Java实体类,用Jackson XML来解析。

首先添加依赖:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.15.2</version> <!-- 使用最新稳定版 -->
</dependency>

定义XML对应的实体类:

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName = "studentInfo") // XML根节点名称
public class StudentInfo {
    private String age;
    private String gender;
    private String major;

    // 省略getter、setter
}

编写解析工具类:

import com.fasterxml.jackson.dataformat.xml.XmlMapper;

public class XmlParseUtil {
    private static final XmlMapper XML_MAPPER = new XmlMapper();

    public static StudentInfo parseToStudentInfo(String xmlContent) {
        try {
            return XML_MAPPER.readValue(xmlContent, StudentInfo.class);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

使用示例:

Student student = studentMapper.selectStudentByName("张三");
StudentInfo info = XmlParseUtil.parseToStudentInfo(student.getXmlContent());
String age = info.getAge();
String major = info.getMajor();

方式3:XPath解析(灵活通用)

适合需要复杂路径提取的场景,比如嵌套标签:

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
import org.xml.sax.InputSource;
import java.io.StringReader;

public class XmlParseUtil {

    public static String extractByXPath(String xmlContent, String xpathExpr) {
        try {
            XPath xpath = XPathFactory.newInstance().newXPath();
            InputSource source = new InputSource(new StringReader(xmlContent));
            return xpath.evaluate(xpathExpr, source);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

使用示例:

// 提取根节点下的age字段
String age = XmlParseUtil.extractByXPath(student.getXmlContent(), "/studentInfo/age");
// 如果有嵌套,比如/studentInfo/detail/address
String address = XmlParseUtil.extractByXPath(student.getXmlContent(), "/studentInfo/detail/address");

内容的提问来源于stack exchange,提问作者Самир Шахмурад

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 08:19:09