XMLType 유형이 무엇인지 먼저 이해해 봅시다.
XMLType는 9i 이후 Oracle의 고유 한 데이터 유형입니다. 얼룩을 물려받는 것은 강력한 존재입니다. XML을 저장하는 데 사용할 수 있으며 많은 작동 기능을 제공합니다. 이론적으로는 2G 데이터를 절약 할 수 있습니다.
그렇다면 Java를 통해 xmltype 데이터를 어떻게 삽입합니까? 이 프로젝트는 mybatis를 사용하며 항상 설명 할 수없는 예외가 있습니다. 그것이 mybatis의 문제인지 JDBC 자체인지 여부를 알 수 없으므로 단계별로, 먼저 JDBC를 해결 한 다음 mybatis를 해결할 계획입니다.
JDBC
오랜 시간이 지나면 JDBC 운영을위한 세 가지 주요 방법이 있음을 알았습니다.
1. XMLType를 Java의 문자열 문자열로 사용하면 XMLType를 만드는 특정 작업이 데이터베이스에 완전히 전달됩니다.
문자열 sql = "xmltable (xml) 값에 삽입 (sys.xmltype.createxml (?))"; 문자열 xmldata = "<label> 이것은 xml 조각 </label>"입니다. ps.SetString (1, xmldata); ps.ExecuteUpdate ();
이 방법은 데이터베이스 스트레스를 너무 많이 만들게됩니다.이 방법은 간단하고 추가 종속성이 필요하지 않기 때문입니다. 이 방법은 처음에 사용되었지만 실제로 사용하는 동안 내용의 길이가 약 4000을 초과하면 다음을 던질 것입니다. ORA-01461 : 긴 값을 긴 열 예외에만 바인딩 할 수 있습니다. 처음에 나는 JDBC 테스트를 사용할 때 mybatis를 사용하는 이유가 여전히 동일하다고 생각했으며 많은 방법을 사용할 때 해결책이 없었습니다. 프로젝트 에서이 큰 필드를 사용할 때 4000 미만의 길이로 데이터를 저장하는 것은 불가능합니다. 이런 식으로 Varchar2를 사용하면 충분 하므로이 방법이 제거됩니다.
2. 클로브 유형을 사용하여 작동합니다. xmltype는 클로브의 존재를 상속하므로 클로브를 통해 작동 할 수 있습니다. 이 방법은 클라이언트에서 클로브 데이터를 생성하여 데이터베이스로 전달하여 Oracle의 XMLType () 함수를 통해 XMLType 값을 구성하는 것입니다.
문자열 sql = "xmltable (xml) 값에 삽입 (xmltype (?))"; 문자열 xmldata = "<label> 이것은 xml 조각 </label>"입니다. // Clobclob tempclob 작성 = clob.createTemporary (Connection, false, clob.duration_session); // clobtempclob.open을 열어 (clob.mode_readwrite); //Get writerWriter clobWriter = tempClob.setCharacterStream(100);//Write data clobWriter.write(xmldata);//Fresh clobWriter.flush();//Close writerclobWriter.close();//Close CLOBtempClob.close(); pst.setobject (1, tempclob);
이 메소드 클라이언트와 데이터베이스는 동시에 XMLType를 생성 할 책임이 있으므로 압력은 비교적 평균이며 길이를 초과하는 데 문제가 없습니다. 그러나 실제로 사용하는 동안 XML의 컨텐츠 헤더에는 다음 정보가 포함될 수 없습니다.
<? xml 버전 = "1.0"encoding = "utf-8"?>
그렇지 않으면 예외가 발생합니다.
XML로 시작하는 PI 이름은 예약되어 있습니다
향후 중국어로 XML 포함의 내용을 처리 할 때 차량 코드 문제에 직면 할 것인지에 대해서는 이야기하지 마십시오. 그것을 보면 사람들이 불편 함을 느끼게되며 요구 사항도 절약해야합니다. 방법이 없으며이 방법은 작동하지 않습니다.
3. Oracle에서 제공하는 oracle.xdb.xmltype 클래스를 사용하십시오. 클라이언트가 XMLType를 생성 한 후 객체는 데이터베이스로 직접 전달됩니다.
Connection Conn = ...; // 연결 준비 상태 ps = ...; // preadSatement string sql = "xmltable (xml) 값 (?)에 삽입하십시오."; 문자열 xmldata = "<label> 이것은 xml 조각 </label>"입니다. // XMLTYPE 객체 생성 XMLTYPE XMLTYPE = XMLTYPE.CREATEXML (CONN, XMLDATA); ps.setobject (1, xmltype); ps.ExecuteUpdate ();
이 방법은 XMLType를 클라이언트에 생성하는 작업을 완전히 전달하므로 클라이언트가 큰 압력을 받고 있으며 데이터베이스는 저 압력을 받고 있습니다. 실제 테스트 중에 두 개의 JAR 패키지를 추가해야합니다. 그렇지 않으면 클래스를 찾을 수 없습니다.
xdb.jarxmlparserv2.jar
이 JAR 패키지에는 버전 주석이 없으므로 실수를 쉽게 할 수 있습니다. 처음에는 xdb.jar를 다운로드했지만 어떻게했는지에 관계없이 특정 클래스를 찾을 수 없다는 메시지가 표시되었습니다. 확인 후, 나는 그것이 이전 버전의 Oracle에 속한다는 것을 알았습니다. XDB.jar를 다시 다운로드 한 후에는 정상입니다.
위의 세 가지 방법은 200,000 조각의 데이터를 삽입하여 비교했습니다.
첫 번째 방법 : 가장 짧은 시간과 서버 CPU 소비는 가장 큽니다.
두 번째 방법 : 가장 긴 시간이 사용되며 서버 CPU 소비는 중심입니다.
세 번째 방법 : 시간이 많이 걸리고 중앙에있는 서버 CPU 소비는 최소화됩니다.
이 시점에서 JDBC는 마침내 XMLType 유형 데이터의 작동에서 작은 일을했습니다. 말할 것도없이, 세 번째 솔루션은 채택되었지만 프로젝트는 기본적으로 JDBC를 직접 사용하여 작동하지 않습니다. 예를 들어, 현재 프로젝트에서 MyBatis가 사용됩니다. 위의 내용은 Mybatis를 사용할 때 항상 예외가 있다고 언급했습니다. MyBatis를 확인한 후 XMLType의 구현은 없습니다. 여전히 약간의 문제가있는 것 같지만 JDBC가 완료되었으므로 아이디어는 분명합니다.
mybatis
mybatis를 사용하여 XMLType를 작동 시키면 Java 측에서 문자열 유형에도 매핑됩니다. 직접 작동이 JDBC와 같은 처리를 수행하지 않으면 전송 된 컨텐츠가 4000보다 작을 때 모든 것이 정상입니다. 전송 된 컨텐츠가 약 4000 이상인 경우 예외가 발생합니다.
ORA-01461 : 긴 열에 삽입하기 위해서만 긴 값을 바인딩 할 수 있습니다.
MyBatis의 작동은 실제로 JDBC와 동일하다는 것을 알 수 있습니다. JDBC 외부의 계층을 캡슐화하여 구성 파일 및 기타 매핑 방법을 사용하여 데이터베이스에보다 편리하게 액세스 할 수 있습니다. 우리가해야 할 일은 원래 mybatis 편의를 기반으로 XMLType 유형 데이터를 삽입하는 것입니다. 이 경우 XMLType 유형의 사용자 정의 유형 핸들러 프로세서를 구현하는 것이 최선의 선택입니다.
여기서 우리는 여전히 위에서 언급 한 솔루션 3을 사용합니다. 당연히 두 개의 JAR 패키지 : xdb.jar 및 xmlparserv2.jar도 추가해야합니다.
TypeHandler 인터페이스를 구현하려면 XMLTyPetypeHandler를 추가하십시오. 데이터 삽입은 주로 setParameter 메소드를 사용하기 때문에이 방법 만 여기에 나열됩니다. 다른 방법 코드는 생략됩니다.
/*** Oracle sys.xmltype 유형 사용자 정의 프로세서*/public class xmltypetypehandler 구현 유형 핸들러 <string> {@override public void setparameter (propledstatement ps, int i, string 매개 변수, jdbctype jdbctype) rows sqlexcection {} ...}.이 SetParameter 메소드는 MyBatis에 의해 데이터베이스에 데이터를 삽입 할 때 매개 변수를 설정하는 데 사용됩니다. 이 방법의 매개 변수는 이미 코드를 이해했다고 생각합니다. 이전 JDBC 구현 방법에 따라 다음 코드를 여기에 삽입합니다.
public void setParameter (Propuble Statement PS, int I, String Parameter, JDBCTYPE JDBCTYPE)는 sqlexection {xmltype xmltype = xmltype.createxml (ps.getConnection (), 매개 변수); ps.setobject (i, xmltype);}Mybatis org.apache.ibatis.type.jdbctype에 의해 정의 된 열거에서 컨버터를 Mapper-config.xml에 등록하십시오. 필요한 xmltype 유형이 없으므로 여기에 정의되지 않은 것으로 정의합니다.
<configuration> <typehandlers> <typehandler javatype = "String"jdbctype = "undefined"handler = "com.tyyd.dw.context.xmltypetypehandler"/> </typehandlers> </configuration>
구성 파일 매개 변수에서 정의 된 변환기를 사용하여 MyBatis를 찾을 수 있습니다.
#{xmlfile, jdbctype = undefined},물론, 당신은 또한보다 표준화되어 유형과 컨버터를 완전히 작성할 수 있습니다.
#{xmlfile, javatype = string, jdbctype = undefined, typehandler = com.tyyd.dw.context.xmltypetypehandler},
위의 단계를 완료하고 논리적으로 모든 것이 완료되면 실행합시다.
결과는 java.lang.ClassCastException: org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper cannot be cast to oracle.jdbc.OracleConnection 과 같습니다.
Oracle의 연결 객체 OracleConnection으로 변환 할 수 없습니다. 확인 후 데이터 소스는 Apache의 DBCP를 사용하여 두 가지와 호환되지 않아야합니다. 나는 온라인에서 확인했고 한 남자는 완벽한 솔루션을 제공했다고 말했습니다. 즉, SetParameter 방법에 Oracle 드라이버 클래스를로드하여 연결을 생성하는 것입니다.
class.forname ( "oracle.jdbc.oracledriver"); Connection Connection = DriverManager.GetConnection (URL, 사용자 이름, 암호);
이것은 실제로 연결 객체를 100%변환 할 수 없다는 문제를 해결할 수 있지만, 구현 측면에서 하하에도 여전히 언급하지 않을 것입니다. 인터넷 주변을 지나가는 사람들도 PoolbeBeConnection 객체로 변환 할 수 있다고 말한 다음 GetDelegate 메소드를 사용하여 원래 프록시 링크를 얻습니다. 이것은 가능해 보인다. 시도해 봅시다 :
poolableConnection Connection = (poolableConnection) ps.getConnection (); xmltype xmltype = xmltype.createxml (connection.getDelegate (), 매개 변수); ps.setObject (i, xmltype);
결과적으로 또 다른 예외가 발생했습니다.
org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper cannot be cast to org.apache.commons.dbcp.PoolableConnection . 변환 할 수 없습니다.
온라인으로 순환하는 기사는 신뢰할 수 없으므로 바로 가기가 없으므로 소스 코드를 직접 확인해야합니다.
소스 코드를 살펴보면 PoolBeLeConnection이 위임 연결 클래스를 상속하고 위임 콘센트 클래스가 연결 인터페이스를 구현한다는 것을 발견했습니다. 위임 구성으로 변환하여 시도해 봅시다.
위임 콘센트 연결 = (DelegatingConnection) ps.getConnection (); xmltype xmltype = xmltype.createxml (connection.getDelegate (), 매개 변수); ps.setObject (i, xmltype);
결과적으로 예외가 발생했습니다. 설명자를 구성 할 수 없습니다 : 유효하지 않은 인수; 중첩 된 예외는 java.sql.sqlexception입니다. 설명자를 구성 할 수 없습니다. 설명 자 : 유효하지 않은 인수, 중단 점 디버깅을 통해 연결 객체가 실제로 무일하게 나타났습니다. 어떻게 널이 될 수 있습니까? 인터넷에있는 사람들은 그것을 잘 사용하지만 나와 함께 작동하지 않습니다. 정말 고통입니다. 이것은 해결할 수 없습니다. 위의 사람이 말한 것처럼 운전자 클래스를 혼자로드해야합니까? 방법이 없습니다. 다시 공부합시다.
마지막으로, GetMetadata 메소드를 통해 원래 프록시 연결을 얻을 수 있음을 발견했습니다. 너무 밝고 테스트가 너무 명확합니다. 마침내 정상이며 쉽지 않습니다. 최종 코드는 다음과 같습니다.
@OverRidePublic void setParameter (preadStatement ps, int i, string parameter, jdbctype jdbctype) sqlexception {delegatingconnection connection = (DELEGATINGConnection) ps.getConnection (). getMetAdata () .getConnection (); xmltype xmltype = xmltype.createxml (connection.getDelegate (), 매개 변수); ps.setobject (i, xmltype);}이 시점에서 mybatis를 사용하여 XMLType 유형을 작동 시켰으며 프로세스는 비틀림과 회전으로 가득합니다. 물론 데이터가 삽입되면 쿼리가 있어야합니다. 다음으로 XMLType 유형 쿼리 작업을 구현해야합니다.