Давайте сначала поймем, что такое тип Xmltype.
Xmltype - это уникальный тип данных для Oracle с 9i. Это мощное существование, которое наследует каплей. Его можно использовать для хранения XML и обеспечивает множество функций работы. Теоретически, он может сохранить данные 2G.
Итак, как вы вставляете данные XMLTYPE через Java? Проект использует Mybatis, и всегда есть необъяснимые исключения. Я не могу понять, является ли это проблемой Mybatis или самой JDBC, поэтому я планирую сделать это шаг за шагом, сначала решить JDBC, а затем решать Mybatis.
JDBC
После долгого времени борьбы я обнаружил, что есть три основных метода для работы JDBC:
1. Используйте Xmltype в качестве строки строки в Java, и конкретная задача создания Xmltype полностью передается в базу данных:
String sql = "Вставка в xmltable (xml) значения (sys.xmltype.createxml (?))"; String xmldata = "<sabel> Это фрагмент XML </label>"; Ps.SetString (1, Xmldata); ps.executeupdate ();
Этот метод сделает напряжение базы данных слишком сильным, потому что этот метод прост и не требует дополнительных зависимостей. Этот метод использовался в начале, но во время фактического использования было обнаружено, что, когда длина контента превышает около 4000, он будет бросить: ORA-01461: может связывать длинное значение только для вставки в исключение длинного столбца. Сначала я думал, что причина использования Mybatis оставалась одинаковой при использовании теста JDBC, и при использовании многих методов не было никакого решения. Невозможно сохранить данные с длиной менее 4000 при использовании этого большого поля в проекте. Таким образом, использования VARCHAR2 достаточно, поэтому этот метод устраняется.
2. Используйте тип Clob для работы. Xmltype наследует существование Clob, поэтому он может работать через Clob. Метод состоит в том, чтобы создать данные Clob на клиенте и передать их в базу данных, чтобы построить значение XMLTYPE через функцию oRacle xmltype ():
String sql = "Вставка в xmltable (xml) значения (xmltype (?))"; String xmldata = "<sabel> Это фрагмент XML </label>"; // Создать clobclob empClob = clob.createTemporary (соединение, false, clob.duration_session); // открыть clobtempclob.open (clob.mode_readwrite); // Получить writerwriter clobwriter = tempclob.setcharacterstream (100); // Написать данные clobwriter.write (xmldata); // fresh clobwriter.flush (); // close writeclobwriter.close (); // clobtempclob.close (); PST.SetObject (1, TempClob);
Этот метод клиент и база данных несут ответственность за создание XMLTYPE одновременно, поэтому давление является относительно средним, и нет проблем с превышением длины. Однако во время фактического использования было обнаружено, что заголовок контента XML не может содержать следующую информацию:
<? xml version = "1.0" Encoding = "UTF-8"?>
В противном случае будет брошено исключение:
Имена PI, начиная с XML, зарезервированы
Давайте не будем говорить о том, столкнетесь ли вы какие -либо проблемы с искаженным кодом при обработке содержания включения XML в китайском языке в будущем. Просто просмотр этого заставляет людей чувствовать себя некомфортно, и требования также требуют сбережений. Там нет пути, и этот метод не будет работать.
3. Используйте класс Oracle.xdb.xmltype, предоставленный Oracle. После того, как клиент создает xmltype, объект напрямую передается в базу данных:
Соединение conn = ...; // Получить подключение подготовки ps = ...; // получить подготовку строки sql = "Вставить в xmltable (xml) значения (?)"; String xmldata = "<sabel> Это фрагмент 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 фрагментов данных:
Первый метод: самое короткое время и потребление ЦП -сервера является самым большим;
Второй метод: самое длительное время используется, и потребление ЦП -сервера центрируется;
Третий метод: трудоемкий и центрированный, потребление ЦП-сервера минимально.
На этом этапе JDBC наконец -то сделал некоторые мелочи при работе данных типа XMLTYPE. Само собой разумеется, третье решение принято, но проект в основном не использует JDBC для работы. Например, в текущем проекте используется Mybatis. Вышеуказанное также упоминалось, что всегда есть исключения при использовании mybatis. После проверки Mybatis нет реализации XMLType. Кажется, что есть еще некоторые проблемы, но JDBC была сделана, так что идея ясна, верно?
Mybatis
Используя MyBatis для работы XMLTYPE, мы также сопоставляем тип строки на Java. Когда прямая операция не выполняет никакой обработки, как и JDBC, все нормально, когда передаваемое содержание составляет менее 4000. Когда передаваемое содержание превышает 4000, также отменяется исключение:
ORA-01461: может связать длинное значение только для вставки в длинную колонку
Можно видеть, что операция Mybatis на самом деле такая же, как JDBC, за исключением того, что она инкапсулирует слой вне JDBC, чтобы мы могли использовать файлы конфигурации и другие методы отображения для более удобного доступа к базе данных. Что нам нужно сделать, так это вставить данные типа Xmltype на основе исходного удобства Mybatis. В этом случае реализация пользовательского процессора TypeHandler типа Xmltype является лучшим выбором.
Здесь мы все еще используем решение три, упомянутые выше. Естественно, два пакета банка: xdb.jar и xmlparserv2.jar также необходимо добавить.
Добавьте Xmltypetypehandler, чтобы реализовать интерфейс TypeHandler. Поскольку вставка данных в основном использует метод SetParameter, здесь указан только этот метод. Другой код метода опущен:
/*** Oracle sys.xmltype Тип пользовательского процессора*/public class xmltypetypehandler реализует typehandler <string> {@override public void setParameter (подготовленное Statement PS, int i, String Parameter, jdbctype jdbctype) Throws sqlexcept {} ...}Этот метод SetParameter используется MyBatis для установки параметров при вставке данных в базу данных. Что касается параметров этого метода, я считаю, что вы уже поняли код. Мы вставим здесь следующий код в соответствии с предыдущим методом реализации JDBC:
public void setParameter (подготовка ps, int i, String parameter, jdbctype jdbctype) throws sqlexception {xmltype xmltype = xmltype.createxml (ps.getConnection (), parameter); ps.setObject (i, xmltype);}И зарегистрируйте преобразователь в mapper-config.xml, потому что в перечислении, определяемом Mybatis org.apache.ibatis.type.jdbctype, нам нет типа xmltype, здесь мы определяем его как не определенное:
<FONIVERUTION> <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 Connection Object Oracleconnection. После проверки мы обнаружили, что наш источник данных использует DBCP Apache, который должен быть несовместимы с этими двумя. Я проверил онлайн, и парень сказал, что он дал идеальное решение, которое должно загрузить класс драйвера Oracle в методе SetParameter, чтобы создать соединение следующим образом:
Class.forname ("oracle.jdbc.oracledriver"); connection connection = drivermanager.getConnection (URL, имя пользователя, пароль);Это действительно может решить проблему, что объект соединения не может быть преобразован на 100%, но с точки зрения реализации, ха -ха, я все еще не буду комментировать. Есть также люди, проходящие по Интернету, говоря, что они могут быть преобразованы в объект PoolableConnection, а затем использовать метод GetDelegate для получения оригинальной прокси -ссылки. Это кажется возможным, давайте попробуем:
Connection 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 , не может быть преобразовано.
Там нет никакого способа, кажется, что статьи, циркулирующие онлайн, не являются надежными, поэтому нет ярлыка, поэтому вы должны проверить исходный код самостоятельно.
Посмотрев на исходный код, мы обнаружили, что PoolableConnection наследует класс DelegatingConnection, а класс DelegatingConnection реализует интерфейс соединения. Давайте преобразуем его в делегирование, чтобы попробовать:
DelgatingConnection Connection = (DelgatingConnection) ps.getConnection (); Xmltype xmltype = xmltype.createxml (connection.getDelegate (), parameter); ps.setObject (i, xmltype);
В результате было брошено исключение: невозможно построить дескрипторы: неверные аргументы; Вложенное исключение - java.sql.sqlexception: невозможно построить дескрипторы: неверные аргументы, посредством отладки точки останова, я обнаружил, что объект соединения на самом деле нулевой. Как это могло быть нулевым? Люди в Интернете хорошо используют это, но это не сработает со мной. Это действительно боль. Это не неразрешимо. Вам действительно нужно загрузить класс водителей в одиночку, как сказал выше, сказал выше? Там никакого пути, давайте изучим это снова.
Наконец, я обнаружил, что оригинальное прокси -соединение может быть получено с помощью метода GetMetAdata. Это так ярко, и тест настолько ясен. Наконец -то это нормально и не легко. Окончательный код заключается в следующем:
@OverridePublic void setParameter (подготовка PS, Int I, String Parameter, JDBCTYPE JDBCTYPE) THROHS SQLEXCEPTION {DelgatingConnection Connection = (DelgatingConnection) ps.getConnection (). GetMetAdata () .getConnection (); Xmltype xmltype = xmltype.createxml (connection.getDelegate (), параметр); ps.setObject (i, xmltype);}На данный момент, наконец -то было сделано использование Mybatis для управления типами Xmltype, и процесс полон поворотов. Конечно, должны быть запросы, когда данные вставлены. Далее нам нужно реализовать операции запроса типа XMLTYPE.