sql中<![CDATA[]]>的具體使用詳解
在這篇文章中,通過實際項目詳述<![CDATA[ ]]>用法及說明。
1. 文章引言
今天在寫完根據(jù)賬戶名查詢除本身之外的用戶接口后,在啟動項目時報出如下錯誤:

Caused by: org.apache.ibatis.builder.BuilderException: Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: 50; columnNumber: 21; 元素內(nèi)容必須由格式正確的字符數(shù)據(jù)或標(biāo)記組成。 at org.apache.ibatis.parsing.XPathParser.createDocument(XPathParser.java:263) at org.apache.ibatis.parsing.XPathParser.<init>(XPathParser.java:127) at org.apache.ibatis.builder.xml.XMLMapperBuilder.<init>(XMLMapperBuilder.java:81) at com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean.buildSqlSessionFactory(MybatisSqlSessionFactoryBean.java:573) ... 67 common frames omitted Caused by: org.xml.sax.SAXParseException: 元素內(nèi)容必須由格式正確的字符數(shù)據(jù)或標(biāo)記組成。 at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203) at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:177) at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:400) at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:327) at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1472) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.startOfMarkup(XMLDocumentFragmentScannerImpl.java:2635) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2732) at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:841) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770) at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243) at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339) at org.apache.ibatis.parsing.XPathParser.createDocument(XPathParser.java:261) ... 70 common frames omitted
即Caused by: org.xml.sax.SAXParseException: 元素內(nèi)容必須由格式正確的字符數(shù)據(jù)或標(biāo)記組成。
正趕上最近ChatGPT比較火,借助它來分析我的錯誤,如下圖所示:

ChatGPT說我的XML文件中存在格式不正確的字符或標(biāo)記導(dǎo)致的,讓我檢查XML文件的語法是否正確。
如果說xml文件中的格式不正確,那么,可以確定的是我在userMapper.xml文件中,寫的sql語句不符合xml定義的語法。
于是,前去查看我的sql語句,如下代碼所示:
<select id="queryByUsernameAndId" resultType="com.test.entity.po.User">
SELECT
*
FROM
`user`
<where>
username = #{username}
AND id <> #{userId}
and deleted = 0
and user_status = 1 LIMIT 1
</where>
</select>
并沒有看出我的代碼,哪里存在不合理的地方。
通過查閱網(wǎng)上的資料可知,原來在xml中,不能存在如下的特殊字符:
大于等于符號:
>=小于等于符號:
<=不等于符號:
<>大于符號:
>小于符號:
<且符號:
&英文雙引號符號:
"英文單引號符號:
'…
如果xml中需要寫入特殊符號,則需要添加<![CDATA[]]>。
2. 概述<![CDATA[ ]]>
上文提到了<![CDATA[]]>,那么,我就簡要概述它。
被<![CDATA[]]>這個標(biāo)記,所包含的內(nèi)容將表示為純文本,比如<![CDATA[ < ]]>表示文本內(nèi)容"<"。
平時在mybatis的映射文件寫sql時,很多時候都需要寫一些特殊的字符。例如:<字符、>字符、>=字符、<=字符,但是在xml文件中并不能直接寫上述列舉的字符,否則就會報錯。
因為在解析xml文件時,我們?nèi)绻麜鴮懥颂厥庾址?,在沒有特殊處理的情況下。
這些字符會被轉(zhuǎn)義,但我們并不希望它被轉(zhuǎn)義,所以我們要使用<![CDATA[ ]]>來解決。
那為什么要這樣書寫呢?<![CDATA[ ]]>是XML語法,在CDATA內(nèi)部的所有內(nèi)容都會被解析器忽略。
所以,當(dāng)我們在xml文本中包含了很多的<、<= 和 &字符,就像程序代碼一樣,那么最好把他們都放到CDATA部件中。
3. 書寫規(guī)范
需要注意的問題就是,在我們的mybatis的映射文件中,以下<where>、<select> 等這些標(biāo)簽都不會被解析,所以,我們只把有特殊字符的語句放在<![CDATA[ ]]>中,盡量縮小<![CDATA[ ]]>的范圍。
因而,我在上文的sql語句中,存在不等于符號(<>),那么,我可以進(jìn)行如下修改:
<select id="queryByUsernameAndId" resultType="com.test.entity.po.User">
SELECT
*
FROM
`user`
<where>
username = #{username}
AND id <![CDATA[ <> ]]> #{userId}
and deleted = 0
and user_status = 1 LIMIT 1
</where>
</select>

修改完后,測試該方法,如下代碼所示:
@Resource
UserMapper userMapper;
@Test
public void test() {
User user = userMapper.queryByUsernameAndId("zhangsan", 1L);
System.out.println(user);
}
能夠正常執(zhí)行queryByUsernameAndId防范,如下圖所示:

4. 文末總結(jié)
不管怎么樣,轉(zhuǎn)義前的字符也好,轉(zhuǎn)義后的字符也好,都會被xml解析器解析。
為了方便起見,使用<![CDATA[]]>來包含不被xml解析器解析的內(nèi)容。
但要注意的是:
此部分不能再包含
]]>不允許嵌套使用
]]>這部分不能包含空格或者換行。
最后,說說<![CDATA[]]>和xml轉(zhuǎn)移字符的關(guān)系,它們兩個看起來是不是感覺功能重復(fù)了?
是的,它們的功能就是一樣的,只是應(yīng)用場景和需求有些不同:
<![CDATA[]]>不能適用所有情況,轉(zhuǎn)義字符可以對于短字符串
<![CDATA[]]>寫起來啰嗦,對于長字符串轉(zhuǎn)義字符寫起來可讀性差;<![CDATA[]]>表示xml解析器忽略解析,所以更快。
到此這篇關(guān)于sql中<![CDATA[ ]]>的具體使用詳解的文章就介紹到這了,更多相關(guān)sql <![CDATA[ ]]>內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
隨機(jī)抽取的sql語句 每班任意抽取3名學(xué)生
表 student ,字段 class 及name 。其中class 表示班級,name 表示每班學(xué)生姓名。要求每班任意抽取3名學(xué)生出來,進(jìn)行學(xué)校大掃除2014-07-07
SQL Server驅(qū)動和TLS版本不兼容的原因分析和解決方案
這篇文章主要介紹了在將Java程序部署到Docker容器時,由于SQL Server和OpenJDK 8之間的TLS/SSL版本不兼容問題導(dǎo)致的錯誤,通過修改`java.security`文件放寬TLS/SSL的安全限制,解決了本地服務(wù)器和Docker容器的兼容性問題,需要的朋友可以參考下2025-11-11
SQL Server數(shù)據(jù)庫簡單的事務(wù)日志備份恢復(fù)流程
在一些對數(shù)據(jù)可靠性要求很高的行業(yè),若發(fā)生意外停機(jī)或數(shù)據(jù)丟失,其損失是十分慘重的,數(shù)據(jù)庫管理員應(yīng)針對具體的業(yè)務(wù)要求指定詳細(xì)的數(shù)據(jù)庫備份與災(zāi)難恢復(fù)策略,本文給大家詳細(xì)介紹了SQL Server數(shù)據(jù)庫簡單的事務(wù)日志備份恢復(fù)流程,需要的朋友可以參考下2024-09-09
SQL語句中的DDL類型的數(shù)據(jù)庫定義語言操作
這篇文章主要介紹了SQL語句中的DDL類型的數(shù)據(jù)庫定義語言,主要是用來定義數(shù)據(jù)庫中的對象的,例如數(shù)據(jù)庫、表和字段的定義,簡單的理解就是DDL語言是來操作數(shù)據(jù)庫、表和字段的,需要的朋友可以參考下2022-08-08
學(xué)會sql數(shù)據(jù)庫關(guān)系圖(Petshop)
花了這么多時間最終還是回到了數(shù)據(jù)庫,但是數(shù)據(jù)庫中一張一張的表格找不到腳本,也不是自己設(shè)計的數(shù)據(jù)庫,完全沒有一點頭緒,后來突然想起來sql有個數(shù)據(jù)庫關(guān)系圖,可以很快的適合數(shù)據(jù)庫程序員很快的掌握數(shù)據(jù)庫表之間的關(guān)系2012-08-08
SQL語句的各個關(guān)鍵字的解析過程詳細(xì)總結(jié)
由于最近需要做一些sql query性能提升的研究,因此研究了一下sql語句的解析過程;本文是我在看了各種資料后手機(jī)總結(jié)的,會詳細(xì)的,一步一步的講述一個sql語句的各個關(guān)鍵字的解析過程,歡迎大家互相學(xué)習(xí)2013-01-01

