【爱上Java8】Java 8 不在需要ORM了

前两天在网上看到一篇文章,说java8不再需要ORM了。看了以后 ,觉得还可以,再次做一下分享。

首先,我要对ORM做一些吐槽,以hibernate为代表的ORM简直见识开发者的噩梦呀。本人对此深恶痛绝。什么one-to-many, many-to-many ,搞死人不说,还特别麻烦,该死的延迟加载等等,用起来就是非常不爽。这里我还是觉得MyBatis靠谱一点。很早就想吐槽Hibernate的,一直没机会。

不需要ORM,java8提供了什么东东呢?那就是流式api以及函数式编程。

来看一个简单的例子,这里使用H2(我超喜欢H2,绝对是个好东西呀~~~),访问H2的系统表INFORMATION_SCHEMA ,去收集表和列的关系。

数据结构使用 Map<String, List<String>>,使用jOOQ来操作SQL。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public  static  void main ( String [ ] args )
throws  Exception  {
Class. forName ( "org.h2.Driver" ) ;
try  ( Connection c  = getConnection (
"jdbc:h2:~/sql-goodies-with-mapping",
"sa""" ) )  {
// This SQL statement produces all table
// names and column names in the H2 schema
String sql  =
"select table_name, column_name "  +
"from information_schema.columns "  +
"order by "  +
"table_catalog, "  +
"table_schema, "  +
"table_name, "  +
"ordinal_position" ;
// This is jOOQ's way of executing the above
// statement. Result implements List, which
// makes subsequent steps much easier
Result result  =
DSL. using (c )
. fetch (sql )
}
}

产生处理结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
DSL. using (c )
   . fetch (sql )
   . stream ( )
   . collect (groupingBy (
       r  -> r. getValue ( "TABLE_NAME" ),
       mapping (
           r  -> r. getValue ( "COLUMN_NAME" ),
           toList ( )
        )
    ) )
   . forEach (
        (table, columns )  -> 
            System. out. println (table  +  ": "  + columns )
    ) ;

输出如下:

1
2
3
FUNCTION_COLUMNS: [ALIAS_CATALOG, ALIAS_SCHEMA, ...]
CONSTANTS: [CONSTANT_CATALOG, CONSTANT_SCHEMA, ...]
SEQUENCES: [SEQUENCE_CATALOG, SEQUENCE_SCHEMA, ...]

它的工作过程如下的注释:

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
DSL. using (c )
   . fetch (sql )
 
//将List转为流
   . stream ( )
 
// 将流内的内容转入另外一个集合
   . collect (
 
// 用group操作产生一个Map
            groupingBy (
 
//  指定Group操作的key
       r  -> r. getValue ( "TABLE_NAME" ),
 
// 这个mapping返回group操作的内容
       mapping (
 
// 我要的值就是表的列名啦
           r  -> r. getValue ( "COLUMN_NAME" ),
 
// 将收集到的东东转为List
           toList ( )
        )
    ) )
 
// 得到集合后,用lambda 表达式输出
   . forEach (
        (table, columns )  -> 
            System. out. println (table  +  ": "  + columns )
    ) ;

以上代码直接用流式表达式处理了SQL的返回。当然,这是有些革命性的变化,如果你不喜欢java这么写,理解起来要花点时间,
但是,习惯的话,应该还好。
这里注意一下,以上代码有一个static import

1
import  static java. util. stream. Collectors. *;

还有一个问题,就是排序,因为我们用了HashMap,如果需要排序就可以用 LinkedHashMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DSL. using (c )
   . fetch (sql )
   . stream ( )
   . collect (groupingBy (
       r  -> r. getValue ( "TABLE_NAME" ),
 
        // Add this Supplier to the groupingBy
        // method call
       LinkedHashMap :: new,
       mapping (
           r  -> r. getValue ( "COLUMN_NAME" ),
           toList ( )
        )
    ) )
   . forEach (... ) ;

LinkedHashMap的特点以及与HashMap的区别,大家可以参考这本书看看。

更进一步,让我们看看如何根据数据库的信息,来产生对应的DDL脚本。首先,我们要取得我们需要的信息,列明,数据类型云云。

1
2
3
4
5
6
7
8
9
10
11
String sql  =
     "select "  +
         "table_name, "  +
         "column_name, "  +
         "type_name "  +  // Add the column type
     "from information_schema.columns "  +
     "order by "  +
         "table_catalog, "  +
         "table_schema, "  +
         "table_name, "  +
         "ordinal_position" ;

引入一个类,来包装一下,

1
2
3
4
5
6
7
8
9
class Column  {
     final  String name ;
     final  String type ;
 
    Column ( String name,  String type )  {
         this. name  = name ;
         this. type  = type ;
     }
}

改一下我们的流式代码,让他生成DDL

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
result
    . stream ( )
    . collect (groupingBy (
        r  -> r. getValue ( "TABLE_NAME" ),
        LinkedHashMap :: new,
        mapping (
 
             // 我们要包装到我们自己的类里去了哦~~~
            r  ->  new Column (
                r. getValue ( "COLUMN_NAME"String. class ),
                r. getValue ( "TYPE_NAME"String. class )
             ),
            toList ( )
         )
     ) )
    . forEach (
         (table, columns )  ->  {
 
             // Just emit a CREATE TABLE statement
             System. out. println (
                 "CREATE TABLE "  + table  +  " (" ) ;
 
             System. out. println (
                columns. stream ( )
                       . map (col  ->  "  "  + col. name  +
                                     " "  + col. type )
                       . collect (Collectors. joining ( ",\n" ) )
             ) ;
 
             System. out. println ( ");" ) ;
         }
     ) ;

以下就是程序的输出,完美的DDL脚本:

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
CREATE  TABLE CATALOGS (
  CATALOG_NAME  VARCHAR
);
CREATE  TABLE COLLATIONS (
  NAME  VARCHAR ,
   KEY  VARCHAR
);
CREATE  TABLE  COLUMNS (
  TABLE_CATALOG  VARCHAR ,
  TABLE_SCHEMA  VARCHAR ,
   TABLE_NAME  VARCHAR ,
  COLUMN_NAME  VARCHAR ,
  ORDINAL_POSITION  INTEGER ,
  COLUMN_DEFAULT  VARCHAR ,
  IS_NULLABLE  VARCHAR ,
  DATA_TYPE  INTEGER ,
  CHARACTER_MAXIMUM_LENGTH  INTEGER ,
  CHARACTER_OCTET_LENGTH  INTEGER ,
  NUMERIC_PRECISION  INTEGER ,
  NUMERIC_PRECISION_RADIX  INTEGER ,
  NUMERIC_SCALE  INTEGER ,
  CHARACTER_SET_NAME  VARCHAR ,
  COLLATION_NAME  VARCHAR ,
  TYPE_NAME  VARCHAR ,
   NULLABLE  INTEGER ,
  IS_COMPUTED  BOOLEAN ,
  SELECTIVITY  INTEGER ,
  CHECK_CONSTRAINT  VARCHAR ,
  SEQUENCE_NAME  VARCHAR ,
  REMARKS  VARCHAR ,
  SOURCE_DATA_TYPE  SMALLINT
);
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值