【爱上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
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)
}
}
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
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)
);
.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
2
3
FUNCTION_COLUMNS: [ALIAS_CATALOG, ALIAS_SCHEMA, ...]
CONSTANTS: [CONSTANT_CATALOG, CONSTANT_SCHEMA, ...]
SEQUENCES: [SEQUENCE_CATALOG, SEQUENCE_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
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)
);
.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
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(...);
.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
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";
"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
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;
}
}
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
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(");");
}
);
.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
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
);
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
- 【爱上Java8】Java 8 不在需要ORM了
- Java 8:ORM已经过时了
- 【爱上Java8】一步一步走进 java8 lambda表达式
- 【爱上Java8】BigInteger在Java8中的改进
- 爱上了程序,爱上了你
- 【爱上Java8】ACC_SUPER和早期的invokespecial
- 【爱上Java8】Java8函数式方法的方法引用
- 我爱上RSS了
- 爱上了心会痛。。。
- 爱上它了
- 因为爱上了你!
- Apps爱上了MeeGo
- 爱上了你
- 爱上了疯狂
- 爱上了美女
- 爱上博客了
- 《爱上Android》出版了
- 品味Java:爱上你 爱上Java
- python扩展实现方法--python与c混和编程(转)
- MATLAB学习心得~
- 定制导航栏和状态栏
- hadoop+hive-完全分布式环境搭建
- codeforces 458B
- 【爱上Java8】Java 8 不在需要ORM了
- LeetCode | Reverse Words in a String(字符串中的单词序反转)
- PyQt4在TextEdit控件中创建右键菜单
- Leetcode【15】:3Sum
- FASDVZXCVZXCV
- 二极管、三极管、场效应管的原理及特性
- 函数包装器,函数私有类处理
- C语言 select函数使用
- java 8 使用Lambdas, Paths and Files