Skip to content

Commit 9829703

Browse files
authored
A new type handler for SQLXML data type. (#1221)
Requires drivers support JDBC 4.0+.
1 parent b1122f8 commit 9829703

File tree

4 files changed

+269
-0
lines changed

4 files changed

+269
-0
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* Copyright 2009-2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.apache.ibatis.type;
18+
19+
import java.sql.CallableStatement;
20+
import java.sql.PreparedStatement;
21+
import java.sql.ResultSet;
22+
import java.sql.SQLException;
23+
import java.sql.SQLXML;
24+
25+
/**
26+
* Convert <code>String</code> to/from <code>SQLXML</code>.
27+
*
28+
* @since 3.5.0
29+
* @author Iwao AVE!
30+
*/
31+
public class SqlxmlTypeHandler extends BaseTypeHandler<String> {
32+
33+
@Override
34+
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
35+
throws SQLException {
36+
SQLXML sqlxml = ps.getConnection().createSQLXML();
37+
try {
38+
sqlxml.setString(parameter);
39+
ps.setSQLXML(i, sqlxml);
40+
} finally {
41+
sqlxml.free();
42+
}
43+
}
44+
45+
@Override
46+
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
47+
return sqlxmlToString(rs.getSQLXML(columnName));
48+
}
49+
50+
@Override
51+
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
52+
return sqlxmlToString(rs.getSQLXML(columnIndex));
53+
}
54+
55+
@Override
56+
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
57+
return sqlxmlToString(cs.getSQLXML(columnIndex));
58+
}
59+
60+
protected String sqlxmlToString(SQLXML sqlxml) throws SQLException {
61+
if (sqlxml == null) {
62+
return null;
63+
}
64+
try {
65+
String result = sqlxml.getString();
66+
return result;
67+
} finally {
68+
sqlxml.free();
69+
}
70+
}
71+
72+
}

src/main/java/org/apache/ibatis/type/TypeHandlerRegistry.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ public TypeHandlerRegistry() {
145145
register(java.sql.Time.class, new SqlTimeTypeHandler());
146146
register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());
147147

148+
register(String.class, JdbcType.SQLXML, new SqlxmlTypeHandler());
149+
148150
// mybatis-typehandlers-jsr310
149151
if (Jdk.dateAndTimeApiExists) {
150152
this.register(Instant.class, InstantTypeHandler.class);
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
/**
2+
* Copyright 2009-2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.apache.ibatis.type;
18+
19+
import static org.junit.Assert.*;
20+
21+
import java.io.Reader;
22+
import java.nio.file.Paths;
23+
import java.sql.Connection;
24+
import java.util.Collections;
25+
26+
import org.apache.ibatis.annotations.Insert;
27+
import org.apache.ibatis.annotations.Select;
28+
import org.apache.ibatis.datasource.unpooled.UnpooledDataSource;
29+
import org.apache.ibatis.io.Resources;
30+
import org.apache.ibatis.jdbc.ScriptRunner;
31+
import org.apache.ibatis.mapping.Environment;
32+
import org.apache.ibatis.session.Configuration;
33+
import org.apache.ibatis.session.SqlSession;
34+
import org.apache.ibatis.session.SqlSessionFactory;
35+
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
36+
import org.apache.ibatis.test.EmbeddedPostgresqlTests;
37+
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
38+
import org.junit.AfterClass;
39+
import org.junit.BeforeClass;
40+
import org.junit.Test;
41+
import org.junit.experimental.categories.Category;
42+
43+
import ru.yandex.qatools.embed.postgresql.EmbeddedPostgres;
44+
import ru.yandex.qatools.embed.postgresql.util.SocketUtil;
45+
46+
@Category(EmbeddedPostgresqlTests.class)
47+
public class SqlxmlTypeHandlerTest {
48+
private static final EmbeddedPostgres postgres = new EmbeddedPostgres();
49+
50+
private static SqlSessionFactory sqlSessionFactory;
51+
52+
@BeforeClass
53+
public static void setUp() throws Exception {
54+
// Launch PostgreSQL server. Download / unarchive if necessary.
55+
String url = postgres.start(
56+
EmbeddedPostgres.cachedRuntimeConfig(Paths.get(System.getProperty("java.io.tmpdir"), "pgembed")), "localhost",
57+
SocketUtil.findFreePort(), "postgres_sqlxml", "postgres", "root", Collections.emptyList());
58+
59+
Configuration configuration = new Configuration();
60+
Environment environment = new Environment("development", new JdbcTransactionFactory(), new UnpooledDataSource(
61+
"org.postgresql.Driver", url, null));
62+
configuration.setEnvironment(environment);
63+
configuration.setUseGeneratedKeys(true);
64+
configuration.addMapper(Mapper.class);
65+
sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
66+
67+
try (SqlSession session = sqlSessionFactory.openSession();
68+
Connection conn = session.getConnection();
69+
Reader reader = Resources
70+
.getResourceAsReader("org/apache/ibatis/type/SqlxmlTypeHandlerTest.sql")) {
71+
ScriptRunner runner = new ScriptRunner(conn);
72+
runner.setLogWriter(null);
73+
runner.runScript(reader);
74+
}
75+
}
76+
77+
@AfterClass
78+
public static void tearDown() {
79+
postgres.stop();
80+
}
81+
82+
@Test
83+
public void shouldReturnXmlAsString() throws Exception {
84+
SqlSession session = sqlSessionFactory.openSession();
85+
try {
86+
Mapper mapper = session.getMapper(Mapper.class);
87+
XmlBean bean = mapper.select(1);
88+
assertEquals("<title>XML data</title>",
89+
bean.getContent());
90+
} finally {
91+
session.close();
92+
}
93+
}
94+
95+
@Test
96+
public void shouldReturnNull() throws Exception {
97+
SqlSession session = sqlSessionFactory.openSession();
98+
try {
99+
Mapper mapper = session.getMapper(Mapper.class);
100+
XmlBean bean = mapper.select(2);
101+
assertNull(bean.getContent());
102+
} finally {
103+
session.close();
104+
}
105+
}
106+
107+
@Test
108+
public void shouldInsertXmlString() throws Exception {
109+
final Integer id = 100;
110+
final String content = "<books><book><title>Save XML</title></book><book><title>Get XML</title></book></books>";
111+
// Insert
112+
{
113+
SqlSession session = sqlSessionFactory.openSession();
114+
try {
115+
Mapper mapper = session.getMapper(Mapper.class);
116+
XmlBean bean = new XmlBean();
117+
bean.setId(id);
118+
bean.setContent(content);
119+
mapper.insert(bean);
120+
session.commit();
121+
} finally {
122+
session.close();
123+
}
124+
}
125+
// Select to verify
126+
{
127+
SqlSession session = sqlSessionFactory.openSession();
128+
try {
129+
Mapper mapper = session.getMapper(Mapper.class);
130+
XmlBean bean = mapper.select(id);
131+
assertEquals(content, bean.getContent());
132+
} finally {
133+
session.close();
134+
}
135+
}
136+
}
137+
138+
interface Mapper {
139+
@Select("select id, content from mbtest.test_sqlxml where id = #{id}")
140+
XmlBean select(Integer id);
141+
142+
@Insert("insert into mbtest.test_sqlxml (id, content) values (#{id}, #{content,jdbcType=SQLXML})")
143+
void insert(XmlBean bean);
144+
}
145+
146+
public static class XmlBean {
147+
private Integer id;
148+
149+
private String content;
150+
151+
public Integer getId() {
152+
return id;
153+
}
154+
155+
public void setId(Integer id) {
156+
this.id = id;
157+
}
158+
159+
public String getContent() {
160+
return content;
161+
}
162+
163+
public void setContent(String content) {
164+
this.content = content;
165+
}
166+
}
167+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--
2+
-- Copyright 2009-2018 the original author or authors.
3+
--
4+
-- Licensed under the Apache License, Version 2.0 (the "License");
5+
-- you may not use this file except in compliance with the License.
6+
-- You may obtain a copy of the License at
7+
--
8+
-- http://www.apache.org/licenses/LICENSE-2.0
9+
--
10+
-- Unless required by applicable law or agreed to in writing, software
11+
-- distributed under the License is distributed on an "AS IS" BASIS,
12+
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
-- See the License for the specific language governing permissions and
14+
-- limitations under the License.
15+
--
16+
17+
CREATE SCHEMA mbtest;
18+
19+
CREATE TABLE mbtest.test_sqlxml (
20+
id serial PRIMARY KEY,
21+
content XML
22+
);
23+
24+
INSERT INTO mbtest.test_sqlxml (id, content)
25+
VALUES (1, '<title>XML data</title>');
26+
27+
INSERT INTO mbtest.test_sqlxml (id, content)
28+
VALUES (2, NULL);

0 commit comments

Comments
 (0)