[原创]牛刀小试——用Groovy实现最简单的ORM(2006.9.25更新)
潜水那么久,也该写点东西跟各位朋友分享一下了:-)
小弟关注Groovy已有数月(您可以到Groovy官方网站 http://groovy.codehaus.org 下载),发现其极具魅力,故在我参加的学校'创新试验项目'中,就用它来实现最简易的ORM,做的非常简单,主要原因是没有时间,因为小弟学业繁重,所以抽出一个下午的时间来实现一个简易版的ORM,数据库用的是MySQL。现在简单说明一下所示代码,将User类的一个实例通过save方法保存到数据库中,然后再根据给定条件通过findBy方法从数据库中取出实例,最后删除一个特定实例。由于深知通过XML文件进行配置的痛苦,所以在设计时没有用到任何XML文件。此程序让程序员只需关注自己要处理的对象,而不用关心数据库方面的东西,简化开发过程。最后我想说明的是,由于时间问题,所以编码方面只注重算法的体现,没有考虑其他方面。下面给出的代码仅供演示及参考(源码已经上传,点击下载):
1
package
edu.ecust.orm
2![]()
3
import
groovy.sql.Sql
4
import
groovy.text.Template
5
import
groovy.text.SimpleTemplateEngine
6![]()
7![]()
public
class
User
{
8
private int id
9
private String name
10
private int age
11![]()
12![]()
public User()
{}
13![]()
14![]()
public User( int id)
{
15
this .id = id
16
}
17![]()
18![]()
public User( int id, String name, int age)
{
19
this.id = id
20
this.name = name
21
this.age = age
22
}
23![]()
24![]()
public int getId()
{
25
return id
26
}
27![]()
28![]()
public void setId( int id)
{
29
this.id = id
30
}
31![]()
32![]()
public String getName()
{
33
return name
34
}
35![]()
36![]()
public void setName(String name)
{
37
this.name = name
38
}
39![]()
40![]()
public int getAge()
{
41
return age
42
}
43![]()
44![]()
public void setAge( int age)
{
45
this.age = age
46
}
47![]()
48![]()
49![]()
50![]()
public String toString()
{
51
return name + "(#" + id + ", " + age + ")"
52
}
53
}
54![]()
55
typemap
=
[
"
int
"
:
"
INTEGER
"
,
"
java.lang.Integer
"
:
"
INTEGER
"
,
"
long
"
:
"
BIGINT
"
,
"
java.lang.Long
"
:
"
BIGINT
"
,
"
short
"
:
"
SMALLINT
"
,
"
java.lang.Short
"
:
"
SMALLINT
"
,
"
byte
"
:
"
TINYINT
"
,
"
java.lang.Byte
"
:
"
TINYINT
"
,
"
float
"
:
"
FLOAT
"
,
"
java.lang.Float
"
:
"
FLOAT
"
,
"
double
"
:
"
DOUBLE
"
,
"
java.lang.Double
"
:
"
DOUBLE
"
,
"
java.math.BigDecimal
"
:
"
NUMERIC
"
,
"
char
"
:
"
CHAR(1)
"
,
"
java.lang.Character
"
:
"
CHAR(1)
"
,
"
java.lang.String
"
:
"
VARCHAR(50)
"
,
"
boolean
"
:
"
BIT
"
,
"
java.lang.Boolean
"
:
"
BIT
"
]
56![]()
57![]()
def capitalize(str)
{
58
def c = str.charAt( 0 )
59
int asci = ( int )c
60![]()
if (asci > 96 && asci < 123 )
{
61
return (( char )(asci - 32 )).toString() + str.substring( 1 )
62
}
63
}
64![]()
65
def user
=
new
User(
1
,
"
Daniel
"
,
21
)
66![]()
67![]()
def connect()
{
68
return Sql.newInstance(
69
"jdbc:mysql://localhost:3306/orm" , "root" ,
70
"1106" , "com.mysql.jdbc.Driver" )
71
}
72![]()
73![]()
def pointToLine(str)
{
74
return str.replaceAll( "\\p{Punct}" , "_" )
75
}
76![]()
77![]()
def getFields(u)
{
78
def clazz = u.getClass()
79
def fields = clazz.getDeclaredFields()
80
def fieldunit = [:]
81![]()
for (f in fields)
{
82
def fstr = f.toString()
83![]()
if (fstr.startsWith( "private" ))
{
84
def fieldname = fstr.substring(fstr.lastIndexOf( "." ) + 1 )
85
def methodname = "get" + capitalize(fieldname)
86
fieldunit.put(fieldname, clazz.getMethod(methodname).invoke(u))
87
}
88
}
89![]()
90
return fieldunit
91
}
92![]()
93
tablename
=
""
;
94![]()
def save(u)
{
95
def clazz = u.getClass()
96
def classname = clazz.getName()
97
def classunit = [:]
98
fieldunit = getFields(u)
99
classunit.put(classname, fieldunit)
100
def keySet = classunit.keySet()
101
def it = keySet.iterator()
102
def fields
103![]()
while (it.hasNext())
{
104
tablename = it.next()
105
fields = classunit.get(tablename)
106
}
107
tablename = pointToLine(tablename)
108
def fkeySet = fields.keySet()
109
def fit = fkeySet.iterator()
110
def creationstmt = ""
111![]()
112
def order = [:]
113
def num = 0
114![]()
while (fit.hasNext())
{
115
def fieldname = fit.next()
116
def fieldvalue = fields.get(fieldname)
117![]()
if ( "id" == fieldname)
{
118
creationstmt += "id INTEGER PRIMARY KEY not null,"
119![]()
} else
{
120
creationstmt += fieldname + " " + typemap.get(fieldvalue.getClass().getName()) + ","
121
}
122
order.put(num++ , fieldname)
123
}
124
creationstmt = creationstmt.substring( 0 , creationstmt.length() - 1 )
125
def valuestr = "("
126
def vkeySet = order.keySet()
127
def vit = vkeySet.iterator()
128
params = "("
129![]()
while (vit.hasNext())
{
130
def elem = vit.next()
131
def v = order.get(elem)
132
valuestr += "'\${" + v + "}',"
133
params += "`" + v + "`,"
134
}
135
valuestr = valuestr.substring( 0 , valuestr.length() - 1 )
136
params = params.substring( 0 , params.length() - 1 )
137
valuestr += ")"
138
params += ")"
139
def insertstmt = "INSERT INTO `" + tablename + "`" + params + " VALUES"
140
insertstmt += valuestr
141
def engine = new SimpleTemplateEngine()
142
def template = engine.createTemplate(insertstmt).make(fields)
143
insertstmt = template.toString()
144
def createstmt = """
145
CREATE TABLE IF NOT EXISTS `""" + tablename + """`
146
(
147
""" + creationstmt + """
148
);
149
"""
150![]()
try
{
151
def sql = connect()
152
sql.execute(createstmt)
153
sql.execute(insertstmt)
154![]()
155![]()
} catch (Exception e)
{
156
int id = u.getId()
157
id++
158
u.setId(id)
159
save(u)
160
//println e.getMessage()
161
}
162![]()
163
return u.getId()
164
}
165![]()
166![]()
def delete(u)
{
167![]()
try
{
168
def id = u.getId()
169
def sql = connect()
170
def result = sql.execute("DELETE FROM `" + tablename + "` WHERE id=" + id);
171
println "delete operation completed!"
172![]()
} catch (Exception e)
{
173
println e.getMessage()
174
}
175
}
176![]()
177![]()
def findBy(classname, condition)
{
178
def sql = connect()
179
objs = []
180![]()
sql.eachRow( "select * from " + pointToLine(classname) + " where " + condition)
{
181
obj = Class.forName(classname).newInstance()
182![]()
183
def clazz = obj.getClass()
184
def fields = clazz.getDeclaredFields()
185
def methods = clazz.getDeclaredMethods()
186![]()
for (f in fields)
{
187
def fstr = f.toString()
188![]()
if (fstr.startsWith( "private" ))
{
189
def fieldname = fstr.substring(fstr.lastIndexOf( "." ) + 1 )
190
def setmethodname = "set" + capitalize(fieldname)
191
def setmethod
192![]()
for (m in methods)
{
193
def methodname = m.toString()
194![]()
if (methodname.contains(setmethodname))
{
195
setmethod = m
196
}
197
}
198
def fieldvalue = it.getProperty(fieldname)
199
setmethod.invoke(obj, fieldvalue)
200
}
201
}
202![]()
203
objs.add(obj)
204
}
205![]()
206
return objs
207
}
208![]()
209
println
"
Id of the saved object is
"
+
save(user)
210
println
"
Found
"
+
findBy(
"
edu.ecust.orm.User
"
,
"
id = '11'
"
)
211
userToDelete
=
new
User(
12
,
"
Daniel
"
,
21
)
212
delete(userToDelete)
213
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213