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

来源:互联网 发布:ios 存储数组 编辑:程序博客网 时间:2024/06/06 13:03

前两天在网上看到一篇文章,说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
);
0 0
原创粉丝点击