手写 Hibernate 系列
手写 Hibernate ORM 框架 00-hibernate 简介
手写 Hibernate ORM 框架 02-实体 Bean 定义,建表语句自动生成
手写 Hibernate ORM 框架 03-配置文件读取, 数据库连接构建
手写 Hibernate ORM 框架 05-整体效果测试验证
从零手写组件系列
本节内容
实体 Bean 的定义。
根据实体 Bean 生成对应的建表语句。
定义实体 Bean
简单的用户实体信息定义
[java]
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74package com.ryo.hibernate.simulator.model;
import com.ryo.hibernate.simulator.hibernate.annotations.Column;
import com.ryo.hibernate.simulator.hibernate.annotations.Entity;
import com.ryo.hibernate.simulator.hibernate.annotations.GenerateValue;
import com.ryo.hibernate.simulator.hibernate.annotations.Id;
import java.util.Date;
/**
* 用户实体类
* Created by houbinbin on 16/6/5.
*/
@Entity("t_user")
public class User {
@Id
@GenerateValue
private Long id;
private String name;
private String password;
@Column("myAge")
private Integer age;
private Date createOn;
private Date modifiedOn;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getCreateOn() {
return createOn;
}
public void setCreateOn(Date createOn) {
this.createOn = createOn;
}
public Date getModifiedOn() {
return modifiedOn;
}
public void setModifiedOn(Date modifiedOn) {
this.modifiedOn = modifiedOn;
}
}
Table
实现
Table 核心类的实现
[java]
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91package com.ryo.hibernate.simulator.hibernate;
import com.ryo.hibernate.simulator.hibernate.annotations.Column;
import com.ryo.hibernate.simulator.hibernate.constants.HibernateConstant;
import com.ryo.hibernate.simulator.hibernate.util.FieldUtil;
import com.ryo.hibernate.simulator.hibernate.util.TableUtil;
import com.ryo.hibernate.simulator.util.ReflectionUtil;
import com.ryo.hibernate.simulator.util.StringBuilderUtil;
import java.lang.reflect.Field;
/**
* 表
* @author houbinbin
* Created by houbinbin on 16/6/5.
*/
public class Table {
/**
* 构建创建表的 SQL
* @param t 泛型入参
* @param <T> 泛型
* @return sql
*/
public <T> String buildCreateTableSQL(T t) {
String tableName = TableUtil.getTableName(t);
StringBuilder stringBuilder = new StringBuilder("create table ");
stringBuilder.append(tableName).append(" (");
for(Field field : ReflectionUtil.getFieldList(t)) {
stringBuilder.append(buildFieldSQL(t, field));
}
String result = StringBuilderUtil.removeLastStr(stringBuilder, ", ");
result = buildPrimaryKey(t, result);
return String.format("%s );", result);
}
/**
* 构建主键SQL
* @param t 入参
* @param result 结果
* @param <T> 泛型
* @return SQL
*/
private <T> String buildPrimaryKey(T t, String result) {
Field field = FieldUtil.getIdField(t);
if(field != null) {
String idFieldName = FieldUtil.getFieldName(field);
result = String.format("%s , PRIMARY KEY (`%s`)", result, idFieldName);
}
return result;
}
private <T> String buildFieldSQL(T t, Field field) {
String result;
String fieldName = FieldUtil.getFieldName(field);
String sqlType = FieldUtil.getSqlType(field);
result = String.format("%s %s", fieldName, sqlType);
Column column = FieldUtil.getFieldColumnAnnotation(field);
if(ReflectionUtil.isType(field, String.class)) {
int length = column != null ? column.length() : HibernateConstant.DEFAULT_STRING_SIZE;
result = String.format("%s(%d)", result, length);
}
if(column != null) {
result = String.format("%s %s", result, getNullAbleInfo(column));
}
if(FieldUtil.isGenerateValueField(t, field)) {
result = String.format("%s AUTO_INCREMENT", result);
}
return String.format("%s, ", result);
}
/**
* 获取是否可以为空的信息
* @param column 列信息
* @return 是否可以为空的结果
*/
private String getNullAbleInfo(Column column) {
return column.nullable() ? "" : "NOT NULL";
}
}
测试
- TableTest.java
[java]
1
2
3
4
5
6
7
8
9/**
* 建表语句测试
*/
@Test
public void createTableSQLTest() {
Table table = new Table();
User user = new User();
System.out.println(table.buildCreateTableSQL(user));
}
测试结果:
[plaintext]
1create table t_user (id BIGINT AUTO_INCREMENT, name VARCHAR(255), password VARCHAR(255), myAge INTEGER , createOn DATETIME, modifiedOn DATETIME , PRIMARY KEY (`id`) );
Table 中涉及到的工具类
后面如有重复,将不再赘述
FieldUtil
[java]
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187package com.ryo.hibernate.simulator.hibernate.util;
import com.ryo.hibernate.simulator.hibernate.annotations.Column;
import com.ryo.hibernate.simulator.hibernate.annotations.GenerateValue;
import com.ryo.hibernate.simulator.hibernate.annotations.Id;
import com.ryo.hibernate.simulator.hibernate.constants.TypeMap;
import com.ryo.hibernate.simulator.util.CollectionUtil;
import com.ryo.hibernate.simulator.util.StringUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import static com.ryo.hibernate.simulator.util.ReflectionUtil.getAnnotation;
import static com.ryo.hibernate.simulator.util.ReflectionUtil.getFieldList;
import static com.ryo.hibernate.simulator.util.ReflectionUtil.getFieldValueForce;
import static com.ryo.hibernate.simulator.util.ReflectionUtil.isType;
/**
*
* 字段工具类
* @author houbinbin
* @date 16/6/5
*/
public class FieldUtil {
/**
* 获取对应SQL字段类型
* @param field
* @return
*/
public static String getSqlType(Field field) {
return TypeMap.getTypeMap().get(field.getType().getTypeName());
}
/**
* 获取字段名称
* @param field
* @return
*/
public static String getFieldName(Field field) {
String fieldName = field.getName();
Annotation annotation = getAnnotation(field, Column.class);
Column column = getFieldColumnAnnotation(field);
if(column != null) {
String columnValue = column.value();
fieldName = StringUtil.isEmpty(columnValue) ? fieldName : columnValue;
}
return fieldName;
}
/**
* 获取子弹注解信息
* @param field
* @return
*/
public static Column getFieldColumnAnnotation(Field field) {
Annotation annotation = getAnnotation(field, Column.class);
if(annotation != null) {
return (Column) annotation;
}
return null;
}
/**
* 获取ID字段
* - 不存在则返回null
* @param t
* @param <T>
* @return
*/
public static <T> Field getIdField(T t) {
for (Field field : getFieldList(t)) {
Annotation annotation = getAnnotation(field, Id.class);
if(annotation != null) {
return field;
}
}
return null;
}
/**
* 获取自增长字段。
* @param <T>
* @return
*/
public static <T> Field getGenerateValueField(T t) {
for(Field field : getFieldList(t)) {
Annotation annotation = getAnnotation(field, GenerateValue.class);
if(annotation != null) {
return field;
}
}
return null;
}
/**
* 是否为 GenerateValue 字段
* @param t
* @param field
* @param <T>
* @return
*/
public static <T> boolean isGenerateValueField(T t, Field field) {
Field generateValueField = getGenerateValueField(t);
return generateValueField != null && field.equals(generateValueField);
}
/**
* 获取字段名称列表
* @param t
* @param <T>
* @return
*/
public static <T> List<String> getFieldNameList(T t) {
List<String> fieldNameList = new LinkedList<>();
for(Field field : getFieldList(t)) {
fieldNameList.add(getFieldName(field));
}
return fieldNameList;
}
/**
* 获取字段名称字符串形式
* @param t
* @param <T>
* @return
*/
public static <T> String getFieldNameString(T t) {
return CollectionUtil.concatCollection2Str(FieldUtil.getFieldNameList(t));
}
/**
* 获取字段值字符串形式
* @param t
* @param <T>
* @return
*/
public static <T> String getFieldValueString(T t) {
List<String> valueStrList = new LinkedList<>();
for(Field field : getFieldList(t)) {
valueStrList.add(String.format("'%s'", getValueString(t, field)));
}
return CollectionUtil.concatCollection2Str(valueStrList);
}
/**
* 获取指定字段值字符串
* @param t
* @param field
* @param <T>
* @return
*/
private static <T> String getValueString(T t, Field field) {
Object value = getFieldValueForce(t, field.getName());
String result = value.toString();
if(isType(field, Date.class)) {
result = dateToString((Date) value);
}
return result;
}
/**
* 日期转字符串
* @param dateTime 日期
* @return 字符串
*/
private static String dateToString(Date dateTime) {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(dateTime);
}
}
TableUtil
[java]
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
33
34
35
36
37
38
39
40package com.ryo.hibernate.simulator.hibernate.util;
import com.ryo.hibernate.simulator.hibernate.annotations.Entity;
import com.ryo.hibernate.simulator.util.ReflectionUtil;
import com.ryo.hibernate.simulator.util.StringUtil;
import java.lang.annotation.Annotation;
/**
* 列表工具类
*
* @author houbinbin
* @date 16/6/5
*/
public class TableUtil {
private TableUtil() {
}
/**
* 获取表名称
*
* @param t
* @param <T>
* @return 表名称
*/
public static <T> String getTableName(T t) {
Annotation annotation = ReflectionUtil.getAnnotation(t, Entity.class);
String tableName = ReflectionUtil.getClassName(t);
if (annotation != null) {
Entity entity = (Entity) annotation;
String tableValue = entity.value();
tableName = StringUtil.isEmpty(tableValue) ? tableName : tableValue;
}
return tableName;
}
}
ReflectionUtil
[java]
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111package com.ryo.hibernate.simulator.util;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.List;
/**
*
* 反射工具类
* @author houbinbin
* @date 16/6/5
*/
public class ReflectionUtil {
/**
* 是否为某一类型
* @param field
* @param clazz
* @return
*/
public static Boolean isType(Field field, Class clazz) {
return field.getType().equals(clazz);
}
/**
* 获取类名
* @param t
* @param <T>
* @return
*/
public static <T> String getClassName(T t) {
Class clazz = t.getClass();
return clazz.getSimpleName();
}
/**
* 获取子弹列表
* @param t
* @param <T>
* @return
*/
public static <T> Field[] getFieldList(T t) {
Class clazz = t.getClass();
return clazz.getDeclaredFields();
}
/**
* 强制获取字段值
* @param t
* @param fieldName
* @param <T>
* @return
*/
public static <T> Object getFieldValueForce(T t, String fieldName) {
Class clazz = t.getClass();
Object value = null;
try {
Field field = clazz.getDeclaredField(fieldName);
value = getFieldValue(t, field);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return value;
}
/**
* 获取字段值
* @param t
* @param field
* @param <T>
* @return
*/
private static <T> Object getFieldValue(T t, Field field) {
Object value = null;
field.setAccessible(true);
try {
value = field.get(t);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return value;
}
/**
* 获取注解信息
* @param t
* @param annotationClass
* @param <T>
* @return
*/
public static <T> Annotation getAnnotation(T t, Class annotationClass) {
Class clazz = t.getClass();
return clazz.getAnnotation(annotationClass);
}
/**
* 获取注解信息
* @param field
* @param annotationClass
* @return
*/
public static Annotation getAnnotation(Field field, Class annotationClass) {
return field.getAnnotation(annotationClass);
}
}
StringBuilderUtil
[java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package com.ryo.hibernate.simulator.util;
/**
* 字符串Builder-工具类
*
* @author houbinbin
* @date 16/6/5
*/
public class StringBuilderUtil {
/**
* 移除最后一饿字符
*
* @param stringBuilder stringBuilder
* @param subStr 需要字符串
* @return 新的结果
*/
public static String removeLastStr(StringBuilder stringBuilder, String subStr) {
int lastIndex = stringBuilder.lastIndexOf(subStr);
return stringBuilder.substring(0, lastIndex);
}
}
StringUtil
[java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package com.ryo.hibernate.simulator.util;
/**
* 字符串-工具类
* @author houbinbin
* @date 16/6/5
*/
public class StringUtil {
/**
* 空字符串
*/
public static final String EMPTY_STRING = "";
/**
* 是否为空
* @param string
* @return
*/
public static Boolean isEmpty(String string) {
return string == null || EMPTY_STRING.equals(string.trim());
}
}
CollectionUtil
[java]
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48package com.ryo.hibernate.simulator.util;
import java.util.Collection;
/**
* 集合工具类
* @author houbinbin
* @date 16/6/5
*/
public class CollectionUtil {
/**
* 默认连接符
*/
public static final String CONNECTER = ",";
/**
* 是否为空
*
* @param array
* @return
*/
public static boolean isEmpty(Object[] array) {
return (array == null) || (array.length <= 0);
}
/**
* Collection<String>,根据连接符转成字符串.
* 注意:如set 是无序的。。。
*
* @param collection
* @param connector //连接符默认为","
* @return
*/
public static String concatCollection2Str(Collection<String> collection, String... connector) {
String conn = isEmpty(connector) ? CollectionUtil.CONNECTER : connector[0];
StringBuilder stringBuilder = new StringBuilder();
for (String str : collection) {
if (stringBuilder.length() > 0) {
stringBuilder.append(conn);
}
stringBuilder.append(str);
}
return stringBuilder.toString();
}
}