一つ前のエントリーではHibernate単体だったが、Spring上で動かしてみる。
以下を使用するため、入手してライブラリをクラスパスに追加しておく。
http://commons.apache.org/dbcp/ から commons-dbcp-1.2.2.zip
http://commons.apache.org/pool/ から commons-pool-1.5.2-bin.zip
ソースフォルダのルートに applicationContext.xml のファイルを用意。テンプレートは以下。beans タグ内に設定を追加していく。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> </beans>
applicationContext.xml にデータソースの定義を追加
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="org.h2.Driver"/> <property name="url" value="jdbc:h2:tcp://localhost:9092/spring"/> <property name="username" value="sa"/> <property name="password" value=""/> </bean>
同様に applicationContext.xml の SessionFactory の Bean 定義を追加
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="hibernateProperties"> <value> hibernate.dialect = org.hibernate.dialect.H2Dialect hibernate.show_sql = true hibernate.format_sql = true hibernate.hbm2ddl.auto = create </value> </property> <property name="annotatedClasses"> <list><value>etc9.domain.entity.Product</value></list> </property> <property name="annotatedPackages"> <list><value>etc9.domain.entity</value></list> </property> </bean>
この後に作成するBeanの定義も加えておく。
<bean id="productService" class="etc9.domain.ProductService"> <property name="productDao" ref="productDao"/> </bean> <bean id="productDao" class="etc9.dao.ProductDaoImpl"> <property name="sessionFactory" ref="sessionFactory"/> </bean>
Entityから作成。
package etc9.domain.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity public class Product { private Long id; private String name; private String category; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } }
Dao用のインターフェースを作成。
package etc9.dao; import java.util.Collection; import org.springframework.dao.DataAccessException; import etc9.domain.entity.Product; public interface ProductDao { Collection<Product> findByCategory(final String category) throws DataAccessException; Product get(Long id); Product save(Product product); }
Implは、
package etc9.dao; import java.sql.SQLException; import java.util.Collection; import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.criterion.Restrictions; import org.springframework.dao.DataAccessException; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.HibernateTemplate; import etc9.domain.entity.Product; public class ProductDaoImpl implements ProductDao { private HibernateTemplate hibernateTemplate; public void setSessionFactory(SessionFactory sessionFactory) { this.hibernateTemplate = new HibernateTemplate(sessionFactory); } @Override @SuppressWarnings("unchecked") public Collection<Product> findByCategory(final String category) throws DataAccessException { return (Collection<Product>) this.hibernateTemplate.execute(new HibernateCallback(){ @Override public Object doInHibernate(Session session) throws HibernateException, SQLException { Criteria criteria = session.createCriteria(Product.class); criteria.add(Restrictions.eq("category", category)); criteria.setMaxResults(6); return criteria.list(); }}); } @Override public Product get(final Long id) { return (Product) this.hibernateTemplate.get(Product.class, id); } @Override public Product save(final Product product) { this.hibernateTemplate.save(product); return product; } }
Daoを利用するサービスを作成。
package etc9.domain; import etc9.dao.ProductDao; import etc9.domain.entity.Product; public class ProductService { private ProductDao productDao; public void setproductDao(ProductDao productDao) { this.productDao = productDao; } public Collection<Product> exec() { Product p1 = new Product(); p1.setCategory("category"); p1.setName("name1"); this.productDao.save(p1); return this.productDao.findByCategory("category"); } }
テストケース。
package etc9; import org.h2.tools.Server; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeSuite; import etc9.domain.ProductService; public class Test { private static final String BASE_DIR = "db\\h2"; private static Server tcpServer; @BeforeSuite public void beforeSuite() throws Exception { tcpServer = org.h2.tools.Server.createTcpServer( new String[] { "-baseDir", BASE_DIR, "-tcpPort", "9092" }).start(); } @AfterSuite public void afterSuite() { tcpServer.shutdown(); } @org.testng.annotations.Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); ProductService service = (ProductService)context.getBean("productService"); service.exec(); } }
Autowired化する
applicationContext.xmlの冒頭部を以下に変更し、
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:annotation-config/>
DI対象のメソッドに@Autowiredアノテーションを付ける。
ProductDaoImplに以下の変更を行う。
@Autowired public void setSessionFactory(SessionFactory sessionFactory) { this.hibernateTemplate = new HibernateTemplate(sessionFactory); }
ProductServiceに以下の変更を行う。
@Autowired public void setproductDao(ProductDao productDao) { this.productDao = productDao; }
applicationContext.xmlの各Bean定義は以下のように簡略化できる。
<bean id="productService" class="etc9.domain.ProductService"> </bean> <bean id="productDao" class="etc9.dao.ProductDaoImpl"> </bean>