[原创]牛刀小试——用Groovy实现最简单的ORM(2006.9.25更新)

[原创]牛刀小试——用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

你可能感兴趣的:([原创]牛刀小试——用Groovy实现最简单的ORM(2006.9.25更新))