みなさま、こんばんわ。
非DIコンテナの世界で使いやすいORM
OSGi上で使い勝手のよさそうなORMを探しているんですけど、いいものがないですね。
ORMといえばS2JDBCなんだけど。SQLがメソッドチェーンでかけてIDEでリファクタリングできるのはあまりにもメリットが大きいと。個人的に思っている。
OSGi上で動くフレームワークを実装しようとしていて、そこではまずDIコンテナ非依存な世界なんで、S2は使えないということで非常にクマった。
ならば、S2JDBCのソースをS2非依存にしてみようかしらと少し逝った発想でソースコードをみながら改造改造w
実際のソースコード
DIの恩恵に授かれないので初期化処理がかなり大変でしたw
まぁ、でもこれでDIコンテナに依存しなくなったので、GuiceやSpring用のアダプタもかけるようになるね。時間があったら作ってみよう。
で、断っておきますが、普通にS2JDBCを使いたい人はオリジナルを使った方がよいです。
とりあえず、S2から分離しただけなので、もう少しコードをきれいにしていく必要があるな。ちなみに、ソースコードはオリジナルから派生物としてApacheライセンスで公開します。
初期化処理部分
public class Sample { public static void main(String[] args) { // 汎用的なコンテナ(今回のものはインターフェイスにインスタンスを関連づける単純なもの) ComponentContainerImpl componentContainer = new ComponentContainerImpl(); // トランザクションマネージャの初期化 TransactionManagerImpl transactionManager = new TransactionManagerImpl(); UserTransactionImpl userTransaction = new UserTransactionImpl( transactionManager); JTATransactionManagerAdapter jtaTransactionManagerAdapter = new JTATransactionManagerAdapter( userTransaction, transactionManager); TransactionSynchronizationRegistryImpl syncRegistry = new TransactionSynchronizationRegistryImpl(); syncRegistry.setTransactionManager(transactionManager); // データソースファクトリの初期化 DataSourceFactoryImpl dataSourceFactory = new DataSourceFactoryImpl( componentContainer); XADataSourceImpl xaDataSource = new XADataSourceImpl(); xaDataSource.setDriverClassName("org.postgresql.Driver"); xaDataSource .setURL("jdbc:postgresql://localhost:5432/sisioh?schema=sisioh"); xaDataSource.setUser("postgres"); xaDataSource.setPassword(null); componentContainer.registerComponent(XADataSource.class, xaDataSource); // コネクションプールの初期化 ConnectionPoolImpl connectionPool = new ConnectionPoolImpl(); connectionPool.setXADataSource(xaDataSource); connectionPool.setTransactionManager(transactionManager); connectionPool.setTimeout(600); connectionPool.setMaxPoolSize(10); connectionPool.setAllowLocalTx(true); componentContainer.registerComponent(ConnectionPool.class, connectionPool); // データソースの初期化 DataSourceImpl dataSource = new DataSourceImpl(connectionPool); componentContainer.registerComponent(DataSource.class, dataSource); // トランザクション用インターセプタの初期化 RequiredInterceptor ri = new RequiredInterceptor(); ri.setTransactionControl(jtaTransactionManagerAdapter); // エンティティメタファクトリの初期化 EntityMetaFactoryImpl entityMetaFactory = new EntityMetaFactoryImpl(); PersistenceConvention persistenceConvention = new PersistenceConventionImpl(); entityMetaFactory.setPersistenceConvention(persistenceConvention); PropertyMetaFactoryImpl propertyMetaFactory = new PropertyMetaFactoryImpl( componentContainer); ColumnMetaFactoryImpl columnMetaFactory = new ColumnMetaFactoryImpl(); columnMetaFactory.setPersistenceConvention(persistenceConvention); propertyMetaFactory.setColumnMetaFactory(columnMetaFactory); propertyMetaFactory.setPersistenceConvention(persistenceConvention); entityMetaFactory.setPropertyMetaFactory(propertyMetaFactory); TableMetaFactoryImpl tableMetaFactory = new TableMetaFactoryImpl(); tableMetaFactory.setPersistenceConvention(persistenceConvention); entityMetaFactory.setTableMetaFactory(tableMetaFactory); // ダイアレクトの初期化 Postgre81Dialect postgre81Dialect = new Postgre81Dialect(); // JdbcManagerの初期化 JdbcManagerImpl jdbcManager = new JdbcManagerImpl(); jdbcManager.setSyncRegistry(syncRegistry); jdbcManager.setPersistenceConvention(persistenceConvention); jdbcManager.setEntityMetaFactory(entityMetaFactory); jdbcManager.setDataSource(dataSource); jdbcManager.setDataSourceFactory(dataSourceFactory); jdbcManager.setDialect(postgre81Dialect); componentContainer.registerComponent(JdbcManager.class, jdbcManager); // JdbcSampleにトランザクション管理用のAOPをかける FactoryEnhancer<JdbcSampleFactory> factoryEnhancer = new FactoryEnhancer<JdbcSampleFactory>( JdbcSampleFactory.class, // ファクトリのインターフェース JdbcSampleFactoryImpl.class, // 実装クラス new Enhance(new Pointcut(), ri)); try { JdbcSampleFactory jdbcSampleFactory = factoryEnhancer.getEnhanced() .newInstance(); JdbcSample jdbcSample = jdbcSampleFactory .newJdbcSample(componentContainer); // JdbcMangerを呼び出す jdbcSample.process(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (EnhanceException e) { e.printStackTrace(); } } }
JdbcManagerを使っているロジック部分
processメソッドは、Factory Enhancerでトランザクション管理のインターセプタがかかっています。
public class JdbcSample { private ComponentContainer componentContainer; public JdbcSample(ComponentContainer componentContainer) { this.componentContainer = componentContainer; } public void process() { JdbcManager jdbcManager = componentContainer .getComponent(JdbcManager.class); long count = jdbcManager.getCountBySql("SELECT * FROM USER_ACCOUNT"); System.out.println("count = (" + count + ")"); } }
ログ
デバッグログが超適当なんで、まともにでてないけど。うごいてます。
22:35:18.298 [main] DEBUG o.s.extension.jta.TransactionImpl - DSSR0003 22:35:18.313 [main] DEBUG o.s.e.jdbc.query.SqlSelectImpl - select count(*) from ( SELECT * FROM USER_ACCOUNT ) COUNT_ 22:35:18.503 [main] DEBUG o.s.e.dbcp.impl.ConnectionPoolImpl - DSSR0006 22:35:18.506 [main] DEBUG o.s.e.dbcp.impl.ConnectionPoolImpl - DSSR0007 count = (0) 22:35:18.561 [main] DEBUG o.s.extension.jta.TransactionImpl - DSSR0004 22:35:18.561 [main] DEBUG o.s.e.d.impl.ConnectionWrapperImpl - DSSR0002