В Data Geekery мы любим Java. И так как мы действительно входим в свободный API jOOQ и запросы DSL , мы абсолютно взволнованы тем, что Java 8 принесет в нашу экосистему. Мы пару раз писали о приятных вкусностях Java 8 , и теперь мы чувствуем, что пришло время начать новую серию блогов,…
Ява 8 Пятница
Каждую пятницу мы показываем вам пару замечательных новых функций Java 8 в виде учебника, в которых используются лямбда-выражения, методы расширения и другие замечательные вещи. Вы найдете исходный код на GitHub .
Java 8 Goodie: лямбды и SQL
Если вы привыкли писать на Groovy, это может показаться вам «так 2003». Мы знаем. Groovy с самого начала знал очень полезный способ написания SQL на основе строк. Вот пример, написанный на Groovy ( см. Официальные документы здесь ):
1
2
3
4
5
6
7
8
9
|
import groovy.sql.Sql sql = Sql.newInstance( 'jdbc:h2:~/test' , 'sa' , '' , 'org.h2.Driver' ) sql.eachRow( 'select * from information_schema.schemata' ) { println "$it.SCHEMA_NAME -- $it.IS_DEFAULT" } |
Обратите внимание также на встроенную в Groovy строковую интерполяцию, где вы можете помещать выражения в строки. Но мы находимся в среде Java, и с Java 8 дела обстоят лучше и в интеграции Java / SQL, если мы будем использовать сторонние библиотеки вместо JDBC напрямую.
В следующих примерах мы рассмотрим, как извлекать данные из базы данных H2 и отображать записи в пользовательские POJO / DTO с помощью этих трех популярных библиотек:
- JOOQ . (Шокер, я знаю)
- Spring Data / JDBC
- Apache Commons DbUtils
Как всегда, источники также доступны на GitHub . Для этих тестов мы создаем небольшой POJO / DTO, чтобы обернуть метаинформацию схемы:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
class Schema { final String schemaName; final boolean isDefault; Schema(String schemaName, boolean isDefault) { this .schemaName = schemaName; this .isDefault = isDefault; } @Override public String toString() { return "Schema{" + "schemaName='" + schemaName + '\ '' + ", isDefault=" + isDefault + '}' ; } } |
Наш основной метод получит соединение H2 через DriverManager
:
1
2
3
4
5
6
7
8
9
|
Class.forName( "org.h2.Driver" ); try (Connection c = getConnection( "jdbc:h2:~/test" , "sa" , "" )) { String sql = "select schema_name, is_default " + "from information_schema.schemata " + "order by schema_name" ; // Library code here... } |
Теперь, как Java 8 улучшает API jOOQ при использовании SQL на основе строк? Сильно! Проверьте следующий маленький запрос:
1
2
3
4
5
6
7
|
DSL.using(c) .fetch(sql) .map(r -> new Schema( r.getValue( "SCHEMA_NAME" , String. class ), r.getValue( "IS_DEFAULT" , boolean . class ) )) .forEach(System.out::println); |
Так должно быть, верно? Обратите внимание, что нативные API jOOQ также могут отображать Record
базы данных непосредственно в ваш POJO, как таковой:
1
2
3
4
|
DSL.using(c) .fetch(sql) .into(Schema. class ) .forEach(System.out::println); |
Вещи выглядят так же хорошо, когда делают то же самое с Spring JDBC и RowMapper
(обратите внимание, что следующие броски проверяют SQLException
s):
1
2
3
4
5
6
7
8
|
new JdbcTemplate( new SingleConnectionDataSource(c, true )) .query(sql, (rs, rowNum) -> new Schema( rs.getString( "SCHEMA_NAME" ), rs.getBoolean( "IS_DEFAULT" ) )) .forEach(System.out::println); |
… и если вы используете Apache DbUtils , вы можете сделать почти то же самое:
1
2
3
4
5
6
7
8
|
new QueryRunner() .query(c, sql, new ArrayListHandler()) .stream() .map(array -> new Schema( (String) array[ 0 ], (Boolean) array[ 1 ] )) .forEach(System.out::println); |
Вывод
Все три решения более или менее эквивалентны и достаточно просты. Суть в том, что Java 8 улучшит все существующие API. Чем больше однозначных (несколько перегрузок!) Методов, принимающих аргументы SAM (одиночные абстрактные типы методов), тем лучше для интеграции с Java 8.
На следующей неделе мы увидим несколько вещей, которые значительно улучшатся при использовании API java.util.Map .