Eugene Burtsev's blog

Поддержка Java 7 Try-with-resources в MyBatis

В Java 7 появился аналог конструкции using из C# - try-with-resources. Данную фишку очень хорошо использовать для автоматического закрытия ресурсов типа коннектов к базам данных и тд. Например так:

1
2
3
4
try (SqlSession session = ConnectionFactory.getSqlSessionFactory().openSession()) {
  // Work with session
  session.commit();
}

Но вот беда - класс org.apache.ibatis.session.SqlSession из MyBatis 3.0.6 использующегося в проекте не реализует интерфейс AutoCloseable необходимый для того что бы эта конструкция заработала. Надеюсь что в следующей версии поддержку добавят, а пока предлагаю небольшой workaround.

В первую очередь реализуем обертку для класса SqlSession реализующую интерфейс AutoCloseable:

SqlSession.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package net.burtsev.example.dao.mybatis.session;

import java.io.Closeable;
import java.sql.Connection;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.executor.BatchResult;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

@SuppressWarnings("rawtypes")
public class SqlSession implements org.apache.ibatis.session.SqlSession, Closeable {

  private org.apache.ibatis.session.SqlSession wrappedSession;

  SqlSession(org.apache.ibatis.session.SqlSession wrappedSession) {
      this.wrappedSession = wrappedSession;
  }

  @Override
  public Object selectOne(String statement) {
      return wrappedSession.selectOne(statement);
  }

  @Override
  public Object selectOne(String statement, Object parameter) {
      return wrappedSession.selectOne(statement, parameter);
  }

  @Override
  public List selectList(String statement) {
      return wrappedSession.selectList(statement);
  }

  @Override
  public List selectList(String statement, Object parameter) {
      return wrappedSession.selectList(statement, parameter);
  }

  @Override
  public List selectList(String statement, Object parameter, RowBounds rowBounds) {
      return wrappedSession.selectList(statement, parameter, rowBounds);
  }

  @Override
  public Map selectMap(String statement, String mapKey) {
      return wrappedSession.selectMap(statement, mapKey);
  }

  @Override
  public Map selectMap(String statement, Object parameter, String mapKey) {
      return wrappedSession.selectMap(statement, parameter, mapKey);
  }

  @Override
  public Map selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
      return wrappedSession.selectMap(statement, parameter, mapKey, rowBounds);
  }

  @Override
  public void select(String statement, Object parameter, ResultHandler handler) {
      wrappedSession.select(statement, parameter, handler);
  }

  @Override
  public void select(String statement, ResultHandler handler) {
      wrappedSession.select(statement, handler);
  }

  @Override
  public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
      wrappedSession.select(statement, parameter, rowBounds, handler);
  }

  @Override
  public int insert(String statement) {
      return wrappedSession.insert(statement);
  }

  @Override
  public int insert(String statement, Object parameter) {
      return wrappedSession.insert(statement, parameter);
  }

  @Override
  public int update(String statement) {
      return wrappedSession.update(statement);
  }

  @Override
  public int update(String statement, Object parameter) {
      return wrappedSession.update(statement, parameter);
  }

  @Override
  public int delete(String statement) {
      return wrappedSession.delete(statement);
  }

  @Override
  public int delete(String statement, Object parameter) {
      return wrappedSession.delete(statement, parameter);
  }

  @Override
  public void commit() {
      wrappedSession.commit();
  }

  @Override
  public void commit(boolean force) {
      wrappedSession.commit(force);
  }

  @Override
  public void rollback() {
      wrappedSession.rollback();
  }

  @Override
  public void rollback(boolean force) {
      wrappedSession.rollback(force);
  }

  @Override
  public List<BatchResult> flushStatements() {
      return wrappedSession.flushStatements();
  }

  @Override
  public void close() {
      wrappedSession.close();
  }

  @Override
  public void clearCache() {
      wrappedSession.clearCache();
  }

  @Override
  public Configuration getConfiguration() {
      return wrappedSession.getConfiguration();
  }

  @Override
  public <T> T getMapper(Class<T> type) {
      return wrappedSession.getMapper(type);
  }

  @Override
  public Connection getConnection() {
      return wrappedSession.getConnection();
  }

}

Также нам понадобится обертка для SqlSessionFactory умеющая работать с нашим классом SqlSession.

SqlSessionFactory.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package net.burtsev.example.dao.mybatis.session;

import java.sql.Connection;

import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.TransactionIsolationLevel;

public class SqlSessionFactory implements org.apache.ibatis.session.SqlSessionFactory {

  private org.apache.ibatis.session.SqlSessionFactory wrappedFactory;

  SqlSessionFactory(org.apache.ibatis.session.SqlSessionFactory wrappedFactory) {
      this.wrappedFactory = wrappedFactory;
  }

  @Override
  public SqlSession openSession() {
      return new SqlSession(wrappedFactory.openSession());
  }

  @Override
  public SqlSession openSession(boolean autoCommit) {
      return new SqlSession(wrappedFactory.openSession(autoCommit));
  }

  @Override
  public SqlSession openSession(Connection connection) {
      return new SqlSession(wrappedFactory.openSession(connection));
  }

  @Override
  public SqlSession openSession(TransactionIsolationLevel level) {
      return new SqlSession(wrappedFactory.openSession(level));
  }

  @Override
  public SqlSession openSession(ExecutorType execType) {
      return new SqlSession(wrappedFactory.openSession(execType));
  }

  @Override
  public SqlSession openSession(ExecutorType execType, boolean autoCommit) {
      return new SqlSession(wrappedFactory.openSession(execType, autoCommit));
  }

  @Override
  public SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level) {
      return new SqlSession(wrappedFactory.openSession(execType, level));
  }

  @Override
  public SqlSession openSession(ExecutorType execType, Connection connection) {
      return new SqlSession(wrappedFactory.openSession(execType, connection));
  }

  @Override
  public Configuration getConfiguration() {
      return wrappedFactory.getConfiguration();
  }

}

Ну а теперь - магия: конфигурируем iBatis как обычно. Ну почти как обычно, за исключением строки 18, где мы инициализируем нашу обертку.

ConnectionFactory.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package net.burtsev.example.dao.mybatis.session;

import java.io.Reader;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public final class ConnectionFactory {

  private static SqlSessionFactory sqlSessionFactory;
  private static Reader reader;

  static {
      try {
          reader = Resources.getResourceAsReader("mybatis-config.xml");

          if (sqlSessionFactory == null) {
              sqlSessionFactory = new SqlSessionFactory(new SqlSessionFactoryBuilder().build(reader, Settings.getInstance()));
              sqlSessionFactory.getConfiguration().addMappers("net.burtsev.example.dao.mybatis.mappers");
          }
      } catch (Exception e) {
          e.printStackTrace();
      }
  }

  private ConnectionFactory() { }

  public static SqlSessionFactory getSqlSessionFactory() {
      return sqlSessionFactory;
  }
}

Это все, теперь мы можем радоваться фишками java7 в проекте :)

Comments