groovyでH 2データベースの保存過程を書きます。

3938 ワード

以前H 2のroadmapを見ましたが、中にはこのような「Groovy Stred Procesdures」があります。http://groovy.codehaus.org/GSQL」いつかgroovyで記憶過程を書くことを楽しみにしています。このようにすることができれば、groovy.sql.Sqlでデータベース操作を書いて、文法は簡単で、resultset、statment資源を漏らしません。SQLプレースホルダを直接サポートします。H 2にキティちゃんとgroovyを加えて、JVMだけでデータベース、WEBサーバ、アプリケーションサーバのすべての機能を完成させて、インストール・リリース・メンテナンスは多く幸せです。
この待つだけでここ三年近く待ちました。
最近H 2のソースコードを読んで、パッチを書きました。org.h 2.util.SourceComplerの実現を修正しました。50行以上のコードではなく、groovyの保存プロセスをサポートしました。そして、元のjavaコードと完全に互換しています。
実現原理:
  • 大域的なGrovyComplerがgroovyコンパイル機能を提供すると宣言しました。(ここでは複数のデータベースがそれぞれ異なるコンパイラを採用することを考慮していません。同じJVMにおいて多H 2が相互に影響する可能性があります。)
  • org.h.utill.SourceCompler.get Class方法を修正し、groovyコードであればGrouyComplerコンパイル
  • を呼び出すと判断した。
  • Methodの選択:コンパイルされたクラスの静的なpublic方法(「u」で始まるのではなく、「main」ではなく、これらはgroovy自動コンパイルされた方法)
  • その他は問題を考慮します:GrovyComplerは単独の種類で、このようにclassipathの中にgroovyのjarがなくてもSourceComplerが利用できないことをもたらすことはできません。classiloader自動import「java.sql.connection、java.sql.Types、java.sql.Result Set、groovy.sql.Sql、org.h.h.h.sh.SimpleResult Set」、groovy自動ローディングのjavat.javatjavatjavatjavant.lant.javant.javant.lanchを追加しました。
  • 余談はさておき、コードの見本例を示します。
    簡単な例:     ここで@groovy.transform.compleStaticの注釈を使って、静的なコンパイルを使って、簡単なコードに対して性能を向上させます。
    CREATE ALIAS tr AS [email protected] 
     static String tr(String str, String sourceSet, String replacementSet)  { 
     return str.tr(sourceSet, replacementSet); 
     } 
    $$
    呼び出し:
    call tr('hello', 'a-z', 'A-Z')='HELLO';
    --  
    public.tr('hello', 'a-z', 'a-z') = 'hello'  
    TRUE
    (1  , 2 ms)
    複雑な例:
        いくつかのシステム情報を表で返します。(注:H 2ドキュメントに明示されており、関数の最初のパラメータがConnectionであれば、呼び出し時に自動的にデータベース接続に入る)
    create alias sysinfo as $$//groovy
    	import java.lang.management.ManagementFactory
    	static ResultSet sysinfo(Connection conn, String pat){
    		SimpleResultSet rs = new SimpleResultSet()
    		rs.addColumn('type', Types.VARCHAR, 255, 0)
    		rs.addColumn('key', Types.VARCHAR, 255, 0)
    		rs.addColumn('value', Types.VARCHAR, 255, 0)
    		switch (pat){
    			case 'h2': _h2(rs, conn); break;
    			case 'groovy': _groovy(rs); break;
    			case 'jvm': _jvm(rs); break;
    			default: _h2(rs, conn); _groovy(rs); _jvm(rs);
    		}
    		rs
    	}
    	static void _h2(SimpleResultSet rs, Connection conn){
    		rs.addRow('h2', 'BUILD_DATE', org.h2.engine.Constants.BUILD_DATE)
    		rs.addRow('h2', 'BUILD_ID', org.h2.engine.Constants.BUILD_ID.toString())
    		//sample of db process
    		def sql = new Sql(conn)
    		sql.eachRow('SELECT TABLE_TYPE, count(1) AS ct FROM INFORMATION_SCHEMA.TABLES GROUP BY TABLE_TYPE'){
    			rs.addRow('h2', it['TABLE_TYPE'], it['CT'].toString())
    		}
    	}
    
    	static void _groovy(SimpleResultSet rs){
    		rs.addRow('groovy', 'version', groovy.lang.GroovySystem.getVersion())
    	}
    	static void _jvm(SimpleResultSet rs){
    		def defs = [ ['os', ManagementFactory.operatingSystemMXBean, ['arch', 'name', 'version', 'availableProcessors']],
    			['runtime', ManagementFactory.runtimeMXBean, ['name', 'specName', 'specVendor', 'specVersion', 'managementSpecVersion']],
    			['classloading', ManagementFactory.classLoadingMXBean, ['loadedClassCount', 'totalLoadedClassCount', 'unloadedClassCount']],
    			['compilation', ManagementFactory.compilationMXBean, ['totalCompilationTime']],
    			['heap', ManagementFactory.memoryMXBean.heapMemoryUsage, ['committed', 'init', 'max', 'used']],
    			['noneheap', ManagementFactory.memoryMXBean.nonHeapMemoryUsage, ['committed', 'init', 'max', 'used']],
    		]
    		for (ad in defs){
    			def mx=ad[1]
    			for (fe in ad[2]){
    				rs.addRow(ad[0], fe, mx[fe].toString())
    			}
    		}
    	}
    $$;