View Javadoc
1   /*
2    * Copyright (c) 2012-2023, jcabi.com
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met: 1) Redistributions of source code must retain the above
8    * copyright notice, this list of conditions and the following
9    * disclaimer. 2) Redistributions in binary form must reproduce the above
10   * copyright notice, this list of conditions and the following
11   * disclaimer in the documentation and/or other materials provided
12   * with the distribution. 3) Neither the name of the jcabi.com nor
13   * the names of its contributors may be used to endorse or promote
14   * products derived from this software without specific prior written
15   * permission.
16   *
17   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
19   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21   * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28   * OF THE POSSIBILITY OF SUCH DAMAGE.
29   */
30  package com.jcabi.jdbc;
31  
32  import com.jcabi.aspects.Parallel;
33  import java.sql.PreparedStatement;
34  import java.sql.ResultSet;
35  import java.sql.SQLException;
36  import java.sql.Statement;
37  import javax.sql.DataSource;
38  import org.hamcrest.MatcherAssert;
39  import org.hamcrest.Matchers;
40  import org.junit.jupiter.api.Test;
41  
42  /**
43   * Test case for {@link JdbcSession}.
44   * @since 0.1
45   */
46  final class JdbcSessionTest {
47  
48      /**
49       * JdbcSession can do SQL manipulations.
50       * @throws Exception If there is some problem inside
51       */
52      @Test
53      void sendsSqlManipulationsToJdbcDriver() throws Exception {
54          final DataSource source = new H2Source("tiu78");
55          new JdbcSession(source)
56              .autocommit(false)
57              .sql("CREATE TABLE foo (name VARCHAR(50))")
58              .execute()
59              .sql("INSERT INTO foo (name) VALUES (?)")
60              .set("Jeff Lebowski")
61              .execute()
62              .commit();
63          final String name = new JdbcSession(source)
64              .sql("SELECT name FROM foo WHERE name = 'Jeff Lebowski'")
65              .select(
66                  new Outcome<String>() {
67                      @Override
68                      public String handle(final ResultSet rset,
69                          final Statement stmt)
70                          throws SQLException {
71                          rset.next();
72                          return rset.getString(1);
73                      }
74                  }
75              );
76          MatcherAssert.assertThat(name, Matchers.startsWith("Jeff"));
77      }
78  
79      /**
80       * JdbcSession can execute SQL.
81       * @throws Exception If there is some problem inside
82       * @since 0.9
83       */
84      @Test
85      void executesSql() throws Exception {
86          final DataSource source = new H2Source("tpl98");
87          new JdbcSession(source)
88              .autocommit(false)
89              .sql("CREATE TABLE foo5 (name VARCHAR(30))")
90              .execute()
91              .sql("DROP TABLE foo5")
92              .execute()
93              .commit();
94      }
95  
96      /**
97       * JdbcSession can automatically commit.
98       * @throws Exception If there is some problem inside
99       */
100     @Test
101     void automaticallyCommitsByDefault() throws Exception {
102         final DataSource source = new H2Source("tt8u");
103         new JdbcSession(source)
104             .sql("CREATE TABLE foo16 (name VARCHAR(50))")
105             .execute()
106             .sql("INSERT INTO foo16 (name) VALUES (?)")
107             .prepare(
108                 new Preparation() {
109                     @Override
110                     public void prepare(final PreparedStatement stmt)
111                         throws SQLException {
112                         stmt.setString(1, "Walter");
113                     }
114                 }
115             )
116             .execute();
117         final String name = new JdbcSession(source)
118             .sql("SELECT name FROM foo16 WHERE name = 'Walter'")
119             .select(
120                 new Outcome<String>() {
121                     @Override
122                     public String handle(final ResultSet rset,
123                         final Statement stmt)
124                         throws SQLException {
125                         rset.next();
126                         return rset.getString(1);
127                     }
128                 }
129             );
130         MatcherAssert.assertThat(name, Matchers.startsWith("Wa"));
131     }
132 
133     /**
134      * JdbcSession can release connections from the pool.
135      * @throws Exception If there is some problem inside
136      * @since 0.10.2
137      */
138     @Test
139     @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
140     void releasesConnectionsFromThePool() throws Exception {
141         final DataSource source = new H2Source("t445p");
142         new JdbcSession(source)
143             .sql("CREATE TABLE foo776 (name VARCHAR(30))")
144             .execute();
145         for (int idx = 0; idx < 10; ++idx) {
146             new JdbcSession(source)
147                 .sql("INSERT INTO foo776 VALUES ('hello, world!')")
148                 .execute();
149         }
150     }
151 
152     /**
153      * JdbcSession can execute SQL in parallel threads.
154      * @throws Exception If there is some problem inside
155      * @since 0.10.2
156      */
157     @Test
158     void executesSqlInParallelThreads() throws Exception {
159         final DataSource source = new H2Source("til87");
160         new JdbcSession(source)
161             .sql("CREATE TABLE foo99 (name VARCHAR(30))")
162             .execute();
163         this.insert(source, "foo99");
164     }
165 
166     /**
167      * JdbcSession can rollback transaction.
168      * @throws Exception If there is some problem inside
169      */
170     @Test
171     void rollbacksTransaction() throws Exception {
172         final DataSource source = new H2Source("t228x");
173         new JdbcSession(source)
174             .sql("CREATE TABLE t228x (name VARCHAR(30))")
175             .execute()
176             .sql("INSERT INTO t228x VALUES ('foo')")
177             .execute();
178         new JdbcSession(source).autocommit(false)
179             .sql("INSERT INTO t228x VALUES ('bar')")
180             .execute()
181             .rollback();
182         MatcherAssert.assertThat(
183             new JdbcSession(source).sql("SELECT * FROM t228x")
184                 .select(new ListOutcome<>(rset -> rset.getString("name"))),
185             Matchers.contains("foo")
186         );
187     }
188 
189     /**
190      * Insert a row into a table.
191      * @param src Data source
192      * @param table Name of the table to INSERT into
193      * @throws Exception If there is some problem inside
194      * @since 0.10.2
195      */
196     @Parallel(threads = 50)
197     private void insert(final DataSource src, final String table)
198         throws Exception {
199         new JdbcSession(src)
200             .sql(String.format("INSERT INTO %s VALUES ('hey')", table))
201             .execute();
202     }
203 
204 }