Skip to content

Commit

Permalink
A new type handler for SQLXML data type. (mybatis#1221)
Browse files Browse the repository at this point in the history
Requires drivers support JDBC 4.0+.
  • Loading branch information
harawata authored May 2, 2018
1 parent b1122f8 commit 9829703
Show file tree
Hide file tree
Showing 4 changed files with 269 additions and 0 deletions.
72 changes: 72 additions & 0 deletions src/main/java/org/apache/ibatis/type/SqlxmlTypeHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* Copyright 2009-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.ibatis.type;

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

/**
* Convert <code>String</code> to/from <code>SQLXML</code>.
*
* @since 3.5.0
* @author Iwao AVE!
*/
public class SqlxmlTypeHandler extends BaseTypeHandler<String> {

@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
throws SQLException {
SQLXML sqlxml = ps.getConnection().createSQLXML();
try {
sqlxml.setString(parameter);
ps.setSQLXML(i, sqlxml);
} finally {
sqlxml.free();
}
}

@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
return sqlxmlToString(rs.getSQLXML(columnName));
}

@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return sqlxmlToString(rs.getSQLXML(columnIndex));
}

@Override
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return sqlxmlToString(cs.getSQLXML(columnIndex));
}

protected String sqlxmlToString(SQLXML sqlxml) throws SQLException {
if (sqlxml == null) {
return null;
}
try {
String result = sqlxml.getString();
return result;
} finally {
sqlxml.free();
}
}

}
2 changes: 2 additions & 0 deletions src/main/java/org/apache/ibatis/type/TypeHandlerRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ public TypeHandlerRegistry() {
register(java.sql.Time.class, new SqlTimeTypeHandler());
register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());

register(String.class, JdbcType.SQLXML, new SqlxmlTypeHandler());

// mybatis-typehandlers-jsr310
if (Jdk.dateAndTimeApiExists) {
this.register(Instant.class, InstantTypeHandler.class);
Expand Down
167 changes: 167 additions & 0 deletions src/test/java/org/apache/ibatis/type/SqlxmlTypeHandlerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/**
* Copyright 2009-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.ibatis.type;

import static org.junit.Assert.*;

import java.io.Reader;
import java.nio.file.Paths;
import java.sql.Connection;
import java.util.Collections;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSource;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.test.EmbeddedPostgresqlTests;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import ru.yandex.qatools.embed.postgresql.EmbeddedPostgres;
import ru.yandex.qatools.embed.postgresql.util.SocketUtil;

@Category(EmbeddedPostgresqlTests.class)
public class SqlxmlTypeHandlerTest {
private static final EmbeddedPostgres postgres = new EmbeddedPostgres();

private static SqlSessionFactory sqlSessionFactory;

@BeforeClass
public static void setUp() throws Exception {
// Launch PostgreSQL server. Download / unarchive if necessary.
String url = postgres.start(
EmbeddedPostgres.cachedRuntimeConfig(Paths.get(System.getProperty("java.io.tmpdir"), "pgembed")), "localhost",
SocketUtil.findFreePort(), "postgres_sqlxml", "postgres", "root", Collections.emptyList());

Configuration configuration = new Configuration();
Environment environment = new Environment("development", new JdbcTransactionFactory(), new UnpooledDataSource(
"org.postgresql.Driver", url, null));
configuration.setEnvironment(environment);
configuration.setUseGeneratedKeys(true);
configuration.addMapper(Mapper.class);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);

try (SqlSession session = sqlSessionFactory.openSession();
Connection conn = session.getConnection();
Reader reader = Resources
.getResourceAsReader("org/apache/ibatis/type/SqlxmlTypeHandlerTest.sql")) {
ScriptRunner runner = new ScriptRunner(conn);
runner.setLogWriter(null);
runner.runScript(reader);
}
}

@AfterClass
public static void tearDown() {
postgres.stop();
}

@Test
public void shouldReturnXmlAsString() throws Exception {
SqlSession session = sqlSessionFactory.openSession();
try {
Mapper mapper = session.getMapper(Mapper.class);
XmlBean bean = mapper.select(1);
assertEquals("<title>XML data</title>",
bean.getContent());
} finally {
session.close();
}
}

@Test
public void shouldReturnNull() throws Exception {
SqlSession session = sqlSessionFactory.openSession();
try {
Mapper mapper = session.getMapper(Mapper.class);
XmlBean bean = mapper.select(2);
assertNull(bean.getContent());
} finally {
session.close();
}
}

@Test
public void shouldInsertXmlString() throws Exception {
final Integer id = 100;
final String content = "<books><book><title>Save XML</title></book><book><title>Get XML</title></book></books>";
// Insert
{
SqlSession session = sqlSessionFactory.openSession();
try {
Mapper mapper = session.getMapper(Mapper.class);
XmlBean bean = new XmlBean();
bean.setId(id);
bean.setContent(content);
mapper.insert(bean);
session.commit();
} finally {
session.close();
}
}
// Select to verify
{
SqlSession session = sqlSessionFactory.openSession();
try {
Mapper mapper = session.getMapper(Mapper.class);
XmlBean bean = mapper.select(id);
assertEquals(content, bean.getContent());
} finally {
session.close();
}
}
}

interface Mapper {
@Select("select id, content from mbtest.test_sqlxml where id = #{id}")
XmlBean select(Integer id);

@Insert("insert into mbtest.test_sqlxml (id, content) values (#{id}, #{content,jdbcType=SQLXML})")
void insert(XmlBean bean);
}

public static class XmlBean {
private Integer id;

private String content;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}
}
}
28 changes: 28 additions & 0 deletions src/test/java/org/apache/ibatis/type/SqlxmlTypeHandlerTest.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
--
-- Copyright 2009-2018 the original author or authors.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--

CREATE SCHEMA mbtest;

CREATE TABLE mbtest.test_sqlxml (
id serial PRIMARY KEY,
content XML
);

INSERT INTO mbtest.test_sqlxml (id, content)
VALUES (1, '<title>XML data</title>');

INSERT INTO mbtest.test_sqlxml (id, content)
VALUES (2, NULL);

0 comments on commit 9829703

Please sign in to comment.