Spring 整合 Hibernate - HibernateDaoSupport
Java
繼承關係示意圖
一般會用XxxDaoImpl繼承HibernateDaoSupport並實作XxxDao介面的方式
如此便可以呼叫getHibernateTemplate()
如果做一個比較通用的架構,可定義一個BaseDao及BaseDaoImpl,XxxDao再去繼承之。如下:
- BaseDao: interface - 定義共用的db操作方法
- BaseDaoImpl: class - 實作 BaseDao,並以HibernateDaoSupport使用db
- XxxDao: interface - 定義每個entity的操作方法
- XxxDaoImpl: class - 實作XxxDao
BaseDao
// BaseDao: 所有dao共用的interface
public interface BaseDao<T> {
public void insert(T obj);
}
// BaseDaoImpl: 實作BaseDao
public class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T> {
@Override
public void insert(T entity) {
getHibernateTemplate().saveOrUpdate(entity);
}
}
說明:
- 繼承
HibernateDaoSupport
並使用getHibernateTemplate()
可避免使用Hibernate的session進行操作。每次操作流程都要「拿session/操作db/關session」,會很麻煩。將這個lifecycle交給Spring會簡單的多。 - 相依的spring jar有
spring-beans
,spring-core
,spring-orm
,spring-tx
。特別寫出來,是因為IDE報的錯會讓你很難找到底錯在哪。 - Hibernate相依的jar有
mysql-connector-java-8.0.12.jar
注意!
getHibernateTemplate()
在hibernate3沒有問題,在hibernate5則會發生Write operations are not allowed in read-only mode (FlushMode.MANUAL)
的問題。解決方法是getHibernateTemplate().setCheckWriteOperations(false);
。
Entity: Event
@Entity
@Table( name = "events" )
public class Event {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="name", length=30)
private String name;
@Column
@Temporal(TemporalType.DATE)
private Date date;
// getter/setter 略
}
EventDao
public interface EventDao extends BaseDao<Event> {
public void insert(Event e);
}
public class EventDaoImpl extends BaseDaoImpl<Event> implements EventDao {
}
設定檔
web.xml
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/servlet-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
servlet-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:component-scan base-package="my" />
<mvc:annotation-driven />
<!-- AOP -->
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- ########################################## -->
<!-- DB -->
<!-- ########################################## -->
<!-- DataSource -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/testHibernate" />
<property name="user" value="username" />
<property name="password" value="password" />
</bean>
<!-- SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect" >org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.connection.autocommit">false</prop>
</props>
</property>
<property name="packagesToScan" value="my.model" />
</bean>
<!-- Dao -->
<bean id="eventDao" class="my.dao.impl.EventDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
說明:
id=dataSource
定義db driver相關id=sessionFactory
定義hibernate的session相關id=eventDao
中注入sessionFactory