Spring 整合 Hibernate - HibernateTemplate

Java

繼承關係圖

  • 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> implements BaseDao<T> {
    @Autowired
    protected HibernateTemplate hibernateTemplate;

    public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
        this.hibernateTemplate = hibernateTemplate;
    }

    @Override
    public void insert(T entity) {
        hibernateTemplate.saveOrUpdate(entity);
    }
}

說明:

  • 使用HibernateTemplate可避免使用Hibernate的session進行操作。每次操作流程都要「拿session/操作db/關session」不太優雅,將這個lifecycle交給Spring會簡單的多。其實這樣的封裝就是模板模式(Template Pattern),故而命名HibernateTemplate
  • 相依的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)的問題。解決方法是在xml裡定義或hibernateTemplate.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>
    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
        <property name="sessionFactory" ref="sessionFactory"/>
        <!-- fix : Write operations are not allowed in read-only mode (FlushMode.MANUAL) -->
        <property name="checkWriteOperations" value="false"/>
    </bean>
    <!-- Dao -->
    <bean id="baseDao" class="my.dao.impl.BaseDaoImpl">
        <property name="hibernateTemplate" ref="hibernateTemplate" />
    </bean>    
    <bean id="eventDao" class="my.dao.impl.EventDaoImpl">
        <property name="hibernateTemplate" ref="hibernateTemplate" />
    </bean> 
</beans>

說明:

  • id=dataSource定義db driver相關
  • id=sessionFactory定義hibernate的session相關
  • id=hibernateTemplate定義hibernateTemplate相關。繼承HibernateDaoSupport的缺點是,java唯一的繼承會被用掉。
  • id=eventDao中注入hibernateTemplate

results matching ""

    No results matching ""