View Javadoc
1   /*
2    *    Copyright 2009-2023 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    *       https://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  package org.apache.ibatis.type;
17  
18  import static org.assertj.core.api.Assertions.assertThat;
19  import static org.mockito.Mockito.verify;
20  import static org.mockito.Mockito.when;
21  
22  import java.io.BufferedReader;
23  import java.io.ByteArrayInputStream;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.io.InputStreamReader;
27  import java.sql.Blob;
28  
29  import javax.sql.DataSource;
30  
31  import org.apache.ibatis.BaseDataTest;
32  import org.apache.ibatis.annotations.Insert;
33  import org.apache.ibatis.annotations.Select;
34  import org.apache.ibatis.mapping.Environment;
35  import org.apache.ibatis.session.Configuration;
36  import org.apache.ibatis.session.SqlSession;
37  import org.apache.ibatis.session.SqlSessionFactory;
38  import org.apache.ibatis.session.SqlSessionFactoryBuilder;
39  import org.apache.ibatis.transaction.TransactionFactory;
40  import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
41  import org.junit.jupiter.api.BeforeAll;
42  import org.junit.jupiter.api.Test;
43  import org.mockito.Mock;
44  
45  /**
46   * Tests for {@link BlobInputStreamTypeHandler}.
47   *
48   * @since 3.4.0
49   *
50   * @author Kazuki Shimizu
51   */
52  class BlobInputStreamTypeHandlerTest extends BaseTypeHandlerTest {
53  
54    private static final TypeHandler<InputStream> TYPE_HANDLER = new BlobInputStreamTypeHandler();
55  
56    private static SqlSessionFactory sqlSessionFactory;
57  
58    @Mock
59    protected Blob blob;
60  
61    @BeforeAll
62    static void setupSqlSessionFactory() throws Exception {
63      DataSource dataSource = BaseDataTest.createUnpooledDataSource("org/apache/ibatis/type/jdbc.properties");
64      TransactionFactory transactionFactory = new JdbcTransactionFactory();
65      Environment environment = new Environment("Production", transactionFactory, dataSource);
66      Configuration configuration = new Configuration(environment);
67      configuration.addMapper(Mapper.class);
68      sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
69  
70      BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(),
71          "org/apache/ibatis/type/BlobInputStreamTypeHandlerTest.sql");
72    }
73  
74    @Override
75    @Test
76    public void shouldSetParameter() throws Exception {
77      InputStream in = new ByteArrayInputStream("Hello".getBytes());
78      TYPE_HANDLER.setParameter(ps, 1, in, null);
79      verify(ps).setBlob(1, in);
80    }
81  
82    @Override
83    @Test
84    public void shouldGetResultFromResultSetByName() throws Exception {
85      InputStream in = new ByteArrayInputStream("Hello".getBytes());
86      when(rs.getBlob("column")).thenReturn(blob);
87      when(blob.getBinaryStream()).thenReturn(in);
88      assertThat(TYPE_HANDLER.getResult(rs, "column")).isEqualTo(in);
89  
90    }
91  
92    @Override
93    @Test
94    public void shouldGetResultNullFromResultSetByName() throws Exception {
95      when(rs.getBlob("column")).thenReturn(null);
96      assertThat(TYPE_HANDLER.getResult(rs, "column")).isNull();
97    }
98  
99    @Override
100   @Test
101   public void shouldGetResultFromResultSetByPosition() throws Exception {
102     InputStream in = new ByteArrayInputStream("Hello".getBytes());
103     when(rs.getBlob(1)).thenReturn(blob);
104     when(blob.getBinaryStream()).thenReturn(in);
105     assertThat(TYPE_HANDLER.getResult(rs, 1)).isEqualTo(in);
106   }
107 
108   @Override
109   @Test
110   public void shouldGetResultNullFromResultSetByPosition() throws Exception {
111     when(rs.getBlob(1)).thenReturn(null);
112     assertThat(TYPE_HANDLER.getResult(rs, 1)).isNull();
113   }
114 
115   @Override
116   @Test
117   public void shouldGetResultFromCallableStatement() throws Exception {
118     InputStream in = new ByteArrayInputStream("Hello".getBytes());
119     when(cs.getBlob(1)).thenReturn(blob);
120     when(blob.getBinaryStream()).thenReturn(in);
121     assertThat(TYPE_HANDLER.getResult(cs, 1)).isEqualTo(in);
122   }
123 
124   @Override
125   @Test
126   public void shouldGetResultNullFromCallableStatement() throws Exception {
127     when(cs.getBlob(1)).thenReturn(null);
128     assertThat(TYPE_HANDLER.getResult(cs, 1)).isNull();
129   }
130 
131   @Test
132   void integrationTest() throws IOException {
133     try (SqlSession session = sqlSessionFactory.openSession()) {
134       Mapper mapper = session.getMapper(Mapper.class);
135       // insert (InputStream -> Blob)
136       {
137         BlobContent blobContent = new BlobContent();
138         blobContent.setId(1);
139         blobContent.setContent(new ByteArrayInputStream("Hello".getBytes()));
140         mapper.insert(blobContent);
141         session.commit();
142       }
143       // select (Blob -> InputStream)
144       {
145         BlobContent blobContent = mapper.findOne(1);
146         assertThat(new BufferedReader(new InputStreamReader(blobContent.getContent())).readLine()).isEqualTo("Hello");
147       }
148     }
149 
150   }
151 
152   interface Mapper {
153     @Select("SELECT ID, CONTENT FROM TEST_BLOB WHERE ID = #{id}")
154     BlobContent findOne(int id);
155 
156     @Insert("INSERT INTO TEST_BLOB (ID, CONTENT) VALUES(#{id}, #{content})")
157     void insert(BlobContent blobContent);
158   }
159 
160   static class BlobContent {
161     private int id;
162     private InputStream content;
163 
164     public int getId() {
165       return id;
166     }
167 
168     public void setId(int id) {
169       this.id = id;
170     }
171 
172     public InputStream getContent() {
173       return content;
174     }
175 
176     public void setContent(InputStream content) {
177       this.content = content;
178     }
179   }
180 
181 }