對(duì)其做了些優(yōu)化,但此種sql生成方式僅適用于復(fù)雜程度不高的sql,所以實(shí)用性不是很高,僅僅是寫著玩的,知道點(diǎn)mybatis的注解形式的使用方式,可能以后會(huì)逐漸完善起來。第一次寫博客,寫的簡單點(diǎn)。
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
|
package com.bob.config.mvc.mybatis; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 實(shí)體類對(duì)應(yīng)的列 * * @author jjb * @create 2017-09-08 14:42 */ @Documented @Retention (RetentionPolicy.RUNTIME) @Target ({ElementType.FIELD, ElementType.METHOD}) public @interface Column { /** * 當(dāng)前屬性對(duì)應(yīng)的列名 * * @return */ String value() default "" ; /** * 當(dāng)前屬性是不是表必須的 * * @return */ boolean required() default true ; } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package com.bob.config.mvc.mybatis; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 實(shí)體類對(duì)應(yīng)的表 * * @author jjb * @create 2017-09-08 14:44 */ @Documented @Retention (RetentionPolicy.RUNTIME) @Target ({ElementType.TYPE}) public @interface Table { String value() default "" ; /** * 當(dāng)前表的主鍵 * * @return */ String key(); } |
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
|
package com.bob.config.mvc.mybatis; import org.apache.ibatis.annotations.DeleteProvider; import org.apache.ibatis.annotations.InsertProvider; import org.apache.ibatis.annotations.Options; import org.apache.ibatis.annotations.SelectProvider; import org.apache.ibatis.annotations.UpdateProvider; /** * Mybatis基礎(chǔ)Mapper * * @author jjb * @create 2017-09-08 14:37 */ public interface BaseMapper<T> { /** * 插入語句 * * @param bean * @return */ @Options (useGeneratedKeys = true ) @InsertProvider (type = SqlProvider. class , method = "insert" ) public int insert(T bean); /** * 刪除語句 * * @param bean * @return */ @DeleteProvider (type = SqlProvider. class , method = "delete" ) public int delete(T bean); /** * 更新語句 * * @param bean * @return */ @UpdateProvider (type = SqlProvider. class , method = "update" ) public int update(T bean); /** * 查找語句 * * @param bean * @return */ @SelectProvider (type = SqlProvider. class , method = "select" ) public T findFirst(T bean); } |
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
|
package com.bob.config.mvc.mybatis; import java.time.LocalDate; /** * Mybatis實(shí)體類 * * @author jjb * @create 2017-09-08 17:16 */ @Table (key = "id" ) public class MybatisEntity { @Column () private String id; @Column ( "USER_NAME" ) private String name; @Column () private Integer age; private LocalDate date; @Column ( "ADRESS_NUMBER" ) private Integer userAdressNumber; public String getId() { return id; } public void setId(String id) { this .id = id; } public String getName() { return name; } public void setName(String name) { this .name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this .age = age; } @Column ( "CUR_DATE" ) public LocalDate getDate() { return date; } public void setDate(LocalDate date) { this .date = date; } public Integer getUserAdressNumber() { return userAdressNumber; } public void setUserAdressNumber(Integer userAdressNumber) { this .userAdressNumber = userAdressNumber; } } |
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
|
package com.bob.config.mvc.mybatis; import java.lang.reflect.Field; import java.util.Map; /** * 表到實(shí)體的格式化器 * * @author jjb * @create 2017-09-08 14:51 */ public interface TableFormatter { /** * 根據(jù)屬性獲取字段名稱 * * @param field * @return */ public String getColumnName(Field field); /** * 獲取主鍵屬性對(duì)應(yīng)的列名 * * @return */ public String getKeyColumnName(Class<?> clazz); /** * 獲取主鍵的屬性名稱 * * @param clazz * @return */ public String getKeyFiledName(Class<?> clazz); /** * 根據(jù)類獲取表名稱 * * @param clazz * @return */ public String getTableName(Class<?> clazz); /** * 獲取一個(gè)類的所有屬性的映射信息 * * @param clazz * @return */ public Map<Field, String> getFieldMappings(Class<?> clazz); } |
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
187
188
189
190
|
package com.bob.config.mvc.mybatis; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Component; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; /** * 依據(jù)駝峰原則來將表的信息格式化為實(shí)體類的信息,在駝峰處改小寫同時(shí)插入下劃線 * * @author jjb * @create 2017-09-08 14:55 */ @Component public class HumpToUnderLineFormatter implements TableFormatter { private static final Logger LOGGER = LoggerFactory.getLogger(HumpToUnderLineFormatter. class ); private static final Map<Class<?>, Map<Field, String>> FIELD_TO_COLUMN_MAPPINGS = new HashMap<Class<?>, Map<Field, String>>(); private static final Map<Class, String> CLASS_TO_TABLE_MAPPING = new HashMap<Class, String>(); private static final StringBuilder SB = new StringBuilder(); private static final Object LOCK = new Object(); @Override public String getColumnName(Field field) { Assert.notNull(field, "屬性不能為空" ); Map<Field, String> mappings = FIELD_TO_COLUMN_MAPPINGS.get(field.getDeclaringClass()); if (mappings == null ) { synchronized (LOCK) { mappings = FIELD_TO_COLUMN_MAPPINGS.get(field.getDeclaringClass()); if (mappings == null ) { mappings = buildMapping(field.getDeclaringClass()); } } } return mappings.get(field); } @Override public String getKeyColumnName(Class<?> clazz) { Table table = checkClass(clazz); return getColumnName(ReflectionUtils.findField(clazz,table.key())); } @Override public String getKeyFiledName(Class<?> clazz) { Table table = checkClass(clazz); Field field = ReflectionUtils.findField(clazz,table.key()); Assert.state(field != null , "@Table的key()指定的屬性必須存在" ); return field.getName(); } private Table checkClass(Class<?> clazz){ Assert.isTrue(clazz != null , "與Table對(duì)應(yīng)的Class不能為空" ); Table table = clazz.getAnnotation(Table. class ); Assert.isTrue(table != null && StringUtils.hasText(table.key()), "[" +clazz.getName()+ "]必須標(biāo)識(shí)@Table注解且key()不能為空" ); return table; } @Override public String getTableName(Class<?> clazz) { Assert.notNull(clazz, "類不能為空" ); Assert.isTrue(clazz.isAnnotationPresent(Table. class ), "[" + clazz.getName() + "]類上必須含有@Table注解" ); String name = CLASS_TO_TABLE_MAPPING.get(clazz); if (name == null ) { synchronized (LOCK) { name = CLASS_TO_TABLE_MAPPING.get(clazz); if (name == null ) { buildMapping(clazz); } } } return CLASS_TO_TABLE_MAPPING.get(clazz); } @Override public Map<Field, String> getFieldMappings(Class<?> clazz) { Assert.isTrue(clazz != null && clazz.isAnnotationPresent(Table. class ), "與Table對(duì)應(yīng)的Class不能為空且必須標(biāo)識(shí)@Table注解" ); Map<Field, String> mappings = FIELD_TO_COLUMN_MAPPINGS.get(clazz); if (mappings == null ) { synchronized (LOCK) { mappings = FIELD_TO_COLUMN_MAPPINGS.get(clazz); if (mappings == null ) { mappings = buildMapping(clazz); } } } return FIELD_TO_COLUMN_MAPPINGS.get(clazz); } /** * 創(chuàng)建實(shí)體到表映射 * * @param clazz */ private Map<Field, String> buildMapping(Class<?> clazz) { buildClassToTableMapping(clazz); Map<Field, String> mappings = new HashMap<Field, String>(); FIELD_TO_COLUMN_MAPPINGS.put(clazz, mappings); buildFiledToColumnMapping(clazz, mappings); buildFiledToColumnMappingWithGetter(clazz, mappings); return mappings; } /** * 創(chuàng)建類名到表名的名稱映射 * * @param clazz */ private void buildClassToTableMapping(Class<?> clazz) { Table table = clazz.getAnnotation(Table. class ); Assert.notNull(table, "[" + clazz.getName() + "]類上必須有@Table注解" ); CLASS_TO_TABLE_MAPPING.put(clazz, StringUtils.hasText(table.value()) ? table.value() : doFormatWithHunmRule(clazz.getSimpleName())); } /** * 通過Filed建立屬性名稱到字段名稱的映射 * * @param clazz * @param mappings */ private void buildFiledToColumnMapping(Class<?> clazz, Map<Field, String> mappings) { ReflectionUtils.doWithLocalFields(clazz, (field) -> { Column column = field.getAnnotation(Column. class ); if (column != null ) { if (Modifier.isStatic(field.getModifiers())) { LOGGER.error( "[{}]注解不適用于靜態(tài)方法:[{}]" , Column. class .toString(), field); return ; } mappings.put(field, StringUtils.hasText(column.value()) ? column.value() : doFormatWithHunmRule(field.getName())); } } ); } /** * 通過getter()建立屬性名稱到字段名稱的映射 * * @param clazz * @param mappings */ private void buildFiledToColumnMappingWithGetter(Class<?> clazz, Map<Field, String> mappings) { ReflectionUtils.doWithLocalMethods(clazz, (method) -> { Column column = method.getAnnotation(Column. class ); if (column != null ) { if (Modifier.isStatic(method.getModifiers())) { LOGGER.warn( "[{}]注解不適用于靜態(tài)方法: [{}]" , Column. class .toString(), method); return ; } if (!method.getName().startsWith( "get" ) || method.getParameterTypes().length > 0 ) { LOGGER.warn( "[{}]注解只適用于getter方法,而非: [{}]方法" , Column. class .toString(), method); return ; } String fieldName = BeanUtils.findPropertyForMethod(method).getName(); mappings.put(ReflectionUtils.findField(clazz, fieldName), StringUtils.hasText(column.value()) ? column.value() : doFormatWithHunmRule(fieldName)); } } ); } /** * 依據(jù)駝峰原則格式化屬性或者類名稱,在駝峰處改小寫同時(shí)前一位插入下劃線,忽略首字母 * * @param name * @return */ private static String doFormatWithHunmRule(String name) { Assert.hasText(name, "屬性或者類名稱不能為空" ); SB.delete( 0 , SB.length()); SB.append(toUpperCase(name.charAt( 0 ))); for ( int i = 1 ; i < name.length(); i++) { if (isUpperCase(name.charAt(i))) { SB.append( "_" ); } SB.append(toUpperCase(name.charAt(i))); } return SB.toString(); } /** * 將字符轉(zhuǎn)換為大寫 * * @param ch * @return */ private static char toUpperCase( char ch) { return Character.toUpperCase(ch); } /** * 判斷是否為大寫 * * @param ch * @return */ private static boolean isUpperCase( char ch) { return Character.isUpperCase(ch); } } |
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
|
package com.bob.config.mvc.mybatis; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; /** * Mybatis的SQL語句供應(yīng)器 * * @author jjb * @create 2017-09-08 14:37 */ public class SqlProvider { private static final Logger LOGGER = LoggerFactory.getLogger(SqlProvider. class ); private TableFormatter tableFormat = new HumpToUnderLineFormatter(); /** * 根據(jù)Bean對(duì)象生成插入SQL語句 * * @param bean * @return */ public String insert(Object bean) { Class<?> beanClass = bean.getClass(); String tableName = tableFormat.getTableName(beanClass); StringBuilder insertSql = new StringBuilder(); List<String> columns = new ArrayList<String>(); List<String> values = new ArrayList<String>(); insertSql.append( "INSERT INTO " ).append(tableName).append( "(" ); try { for (Entry<Field, String> entry : tableFormat.getFieldMappings(beanClass).entrySet()) { Field field = entry.getKey(); field.setAccessible( true ); if (field.get(bean) != null ) { columns.add(entry.getValue()); values.add( "#{" + field.getName() + "}" ); } } } catch (Exception e) { new RuntimeException( "get insert sql has exceptoin:" + e); } int columnSize = columns.size(); for ( int i = 0 ; i < columnSize; i++) { insertSql.append(columns.get(i)); insertSql.append(i != columnSize - 1 ? "," : ") VALUES(" ); } for ( int i = 0 ; i < columnSize; i++) { insertSql.append(values.get(i)); insertSql.append(i != columnSize - 1 ? "," : ")" ); } return insertSql.toString(); } /** * 根據(jù)Bean對(duì)象生成更新SQL語句 * * @param bean * @return */ public String update(Object bean) { Class<?> beanClass = bean.getClass(); String tableName = tableFormat.getTableName(beanClass); StringBuilder updateSql = new StringBuilder(); updateSql.append( " UPDATE " ).append(tableName).append( " SET " ); try { for (Entry<Field, String> entry : tableFormat.getFieldMappings(beanClass).entrySet()) { Field field = entry.getKey(); field.setAccessible( true ); if (field.get(bean) != null ) { updateSql.append(entry.getValue()).append( "=#{" ).append(field.getName()).append( "}," ); } } updateSql.deleteCharAt(updateSql.length() - 1 ); } catch (Exception e) { new RuntimeException( "get update sql is exceptoin:" + e); } updateSql.append( " WHERE " ).append(tableFormat.getKeyColumnName(beanClass) + " =#{" + tableFormat.getKeyFiledName(beanClass) + "}" ); return updateSql.toString(); } /** * 根據(jù)Bean對(duì)象生成刪除SQL語句 * * @param bean * @return */ public String delete(Object bean) { Class<?> beanClass = bean.getClass(); String tableName = tableFormat.getTableName(beanClass); StringBuilder deleteSql = new StringBuilder(); deleteSql.append( " DELETE FROM " ).append(tableName).append( " WHERE " ); try { for (Entry<Field, String> entry : tableFormat.getFieldMappings(beanClass).entrySet()) { Field field = entry.getKey(); field.setAccessible( true ); if (field.get(bean) != null ) { deleteSql.append(entry.getValue()).append( "=#{" ).append(field.getName()).append( "} AND " ); } } deleteSql.delete(deleteSql.length() - 5 , deleteSql.length() - 1 ); } catch (Exception e) { new RuntimeException( "get delete sql is exceptoin:" + e); } return deleteSql.toString(); } /** * 生成查詢SQL語句 * * @param bean * @return */ public String select(Object bean) { Class<?> beanClass = bean.getClass(); String tableName = tableFormat.getTableName(beanClass); StringBuilder selectSql = new StringBuilder(); List<String> columns = new ArrayList<String>(); List<String> values = new ArrayList<String>(); selectSql.append( "SELECT " ); try { for (Entry<Field, String> entry : tableFormat.getFieldMappings(beanClass).entrySet()) { Field field = entry.getKey(); field.setAccessible( true ); selectSql.append(entry.getValue() + "," ); if (field.get(bean) != null ) { columns.add(entry.getValue()); values.add( "#{" + field.getName() + "}" ); } } selectSql.deleteCharAt(selectSql.length() - 1 ); } catch (Exception e) { new RuntimeException( "get select sql is exceptoin:" + e); } selectSql.append( " FROM " ).append(tableName).append( " WHERE " ); int columnSize = columns.size(); for ( int i = 0 ; i < columnSize; i++) { selectSql.append(columns.get(i)).append( "=" ).append(values.get(i)).append( " AND " ); } selectSql.delete(selectSql.length() - 5 , selectSql.length() - 1 ); return selectSql.toString(); } } |
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
|
package com.bob.test.concrete.mysqlGenerate; import java.time.LocalDate; import com.bob.config.mvc.mybatis.MybatisEntity; import com.bob.config.mvc.mybatis.SqlProvider; import org.junit.Before; import org.junit.Test; /** * Mysql基于注解形式的sql語句生成測(cè)試 * * @author jjb * @create 2017-09-11 11:10 */ public class MysqlGenerateTest { private SqlProvider sqlProvider; private MybatisEntity mybatisEntity; @Before public void doBefore(){ sqlProvider = new SqlProvider(); mybatisEntity = new MybatisEntity(); mybatisEntity.setId( "0015415" ); mybatisEntity.setName( "lanboal" ); mybatisEntity.setAge( 28 ); mybatisEntity.setDate(LocalDate.now()); mybatisEntity.setUserAdressNumber( 24 ); } @Test public void testInsert(){ String sql = sqlProvider.insert(mybatisEntity); System.out.println(sql); } @Test public void testUpdate(){ String sql = sqlProvider.update(mybatisEntity); System.out.println(sql); } @Test public void testDelete(){ String sql = sqlProvider.delete(mybatisEntity); System.out.println(sql); } @Test public void testSelect(){ String sql = sqlProvider.select(mybatisEntity); System.out.println(sql); } } |
總結(jié)
以上所述是小編給大家介紹的 Mybatis基于注解形式的sql語句生成實(shí)例代碼,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)服務(wù)器之家網(wǎng)站的支持!
原文鏈接:http://blog.csdn.net/longdayu4544/article/details/77931795