Spring3.1.1+Hibernate3.6.10整合
博客专区 > yope 的博客 > 博客详情
Spring3.1.1+Hibernate3.6.10整合
yope 发表于3年前
Spring3.1.1+Hibernate3.6.10整合
  • 发表于 3年前
  • 阅读 97
  • 收藏 1
  • 点赞 0
  • 评论 0
摘要: Spring+Hibernate整合遇到的问题以及解决

本文通过hibernate注解实现对象映射

一、viewspace-dao.xml配置

 <!-- 扫描com.sunsharing.dao包下所有标注@Repository的DAO组件 -->
    <context:component-scan base-package="com.sunsharing.springdemo.dao"/>
    <!--使用spring提供的PropertyPlaceholderConfigurer读取数据库配置信息.properties-->
    <bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:jdbc.properties"/>
    </bean>
    <!--数据源配置-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
          destroy-method="close"
          p:driverClassName="${jdbc.driverClassName}"
          p:url="${jdbc.url}"
          p:username="${jdbc.username}"
          p:password="${jdbc.password}"/>
<!--SessionFactory接口负责初始化Hibernate,是重量级的,一般一个项目只要一个SessionFactory-->
    <bean id="sessionFactory"
          class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="packagesToScan" value="com.sunsharing.springdemo.domain"/>
        <property name="hibernateProperties">
            <props>
                <!--<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>-->
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
                <prop key="hibernate.cache.use_second_level_cache">true</prop>
                <prop key="hibernate.cache.use_query_cache">true</prop>
            </props>
        </property>
    </bean>

    <bean id="hibernateTemplate"
          class="org.springframework.orm.hibernate3.HibernateTemplate"
          p:sessionFactory-ref="sessionFactory" />
    <bean id="jdbcTemplate"
          class="org.springframework.jdbc.core.JdbcTemplate"
          p:dataSource-ref="dataSource"/>

在此配置过程中遇到过两个问题:

1、数据源问题,参看网友的代码案例,引入spring(org.springframework.jdbc.datasource.DriverManagerDataSource) 的数据源,发现destroy-method="close"处报错,经过查证后发现,DriverManagerDataSource数据源不存在这个关闭的方法,后改用BasicDataSource 数据源解决。关于数据源介绍请参看

Spring学习总结3——配置datasource三种方式 ,在此不做累述。

2、maven 中Oracle驱动没有授权问题,不能够引入Oracle的驱动包,解决方法见

在Maven仓库中添加Oracle JDBC驱动(11g)

二、模型层的User POJO

package com.sunsharing.springdemo.domain;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;

/**
 * Created by nyp on 2015/2/5.
 */
@Entity
@SequenceGenerator(name = "USER_ID_SEQUENCE",allocationSize=1,initialValue=1, sequenceName = "USER_ID_SEQUENCE")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Table(name = "T_USER")
public class User extends BaseDomain {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_ID_SEQUENCE")
    @Column(name="USER_ID")
    private int userId;
    @Column(name="USER_NAME")
    private String userName;
    @Column(name="PASSWORD")
    private String password;
    @Column(name="LAST_IP")
    private String lastIp;
    @Column(name="LAST_VISIT")
    private String lastVisit;
    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getLastIp() {
        return lastIp;
    }

    public void setLastIp(String lastIp) {
        this.lastIp = lastIp;
    }


    public String getLastVisit() {
        return lastVisit;
    }

    public void setLastVisit(String lastVisit) {
        this.lastVisit = lastVisit;
    }
}

注解的过程中需要注意的是Oracle中的主键生成策略与mysql 有所差别,Oracle需要自己建立序列(sequence的好处主要是在数据库各种情况下,不会生成重复值,保证插入的唯一性)。

1.首先需要在实体类前面申明一个Sequence如下

方法:

@SequenceGenerator(name="SEQ_Name",sequenceName="SEQ_DB_Name") 

参数注意:

SEQ_Name:表示为申明的这个Sequence指定一个名称,以便使用 

SEQ_DB_Name:表示为数据库中的Sequence指定一个名称。两个参数的名称可以一样。

此时主键id的增长是按照hibernate自动处理的方式,而并非数据库中定义的sequence来处理。

必须加allocationSize=1,initialValue=1这两项配置才可以解决上述问题。

2.然后使用@GeneratedValue注解 

方法:@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="SEQ_Name") 

参数:

strategy:固定为GenerationType.SEQUENCE 

Generator:在实体类前面申明的sequnce的名称 

以上这部分就是对Oracle中的序列主键的详细注解说明了。

三、dao层java代码

首先是BaseDao 作为DAO基类

package com.sunsharing.springdemo.dao;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.SQLException;
import java.util.List;
/**
 * Created by nyp on 2015/2/9.
 */
/**
 * DAO基类,其它DAO可以直接继承这个DAO,不但可以复用共用的方法,还可以获得泛型的好处。
 */
public class BaseDao<T>{
    private Class<T> entityClass;
    @Autowired
    private HibernateTemplate hibernateTemplate;
    // 查询条件
    private String hql;
    /**
     * 通过反射获取子类确定的泛型类
     */
    public BaseDao() {
        Type genType = getClass().getGenericSuperclass();
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        entityClass = (Class) params[0];
    }

    /**
     * 根据ID加载PO实例
     *
     * @param id
     * @return 返回相应的持久化PO实例
     */
    public T load(Serializable id) {
        return (T) getHibernateTemplate().load(entityClass, id);
    }

    /**
     * 根据ID获取PO实例
     *
     * @param id
     * @return 返回相应的持久化PO实例
     */
    public T get(Serializable id) {
        return (T) getHibernateTemplate().get(entityClass, id);
    }

    /**
     * 获取PO的所有对象
     *
     * @return
     */
    public List<T> loadAll() {
        return getHibernateTemplate().loadAll(entityClass);
    }

    /**
     * 保存PO
     *
     * @param entity
     */
    public void save(T entity) {
        getHibernateTemplate().save(entity);
    }

    /**
     * 删除PO
     *
     * @param entity
     */
    public void remove(T entity) {
        getHibernateTemplate().delete(entity);
    }

    /**
     * 更改PO
     *
     * @param entity
     */
    public void update(T entity) {
        getHibernateTemplate().update(entity);
    }

    /**
     * 执行HQL查询
     *
     * @param sql
     * @return 查询结果
     */
    public List find(String hql) {
        return this.getHibernateTemplate().find(hql);
    }

    /**
     * 执行带参的HQL查询
     *
     * @param sql
     * @param params
     * @return 查询结果
     */
    public List find(String hql, Object... params) {
        return this.getHibernateTemplate().find(hql,params);
    }

    /**
     * 对延迟加载的实体PO执行初始化
     * @param entity
     */
    public void initialize(Object entity) {
        this.getHibernateTemplate().initialize(entity);
    }
    public HibernateTemplate getHibernateTemplate() {
        return hibernateTemplate;
    }

   
}

UserDao中java代码

package com.sunsharing.springdemo.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Repository;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
/**
 * Created by nyp on 2015/2/5.
 */
@Repository
public class UserDao extends BaseDao<User> {
    private final String GET_USER_BY_USERNAME = "from User u where u.userName = ?";
    private final String QUERY_USER_BY_USERNAME = "from User u where u.userName like ?";
//注意上面的User表示的是User对象
    @Autowired
    private JdbcTemplate jdbcTemplate;
    /**
     * 根据用户名查询User对象
     * @param userName 用户名
     * @return 对应userName的User对象,如果不存在,返回null。
     */
    public User getUserByUserName(String userName){
        List<User> users = (List<User>)find(GET_USER_BY_USERNAME,userName);
        if (users.size() == 0) {
            return null;
        }else{
            return users.get(0);
        }
    }

    /**
     * 根据用户名为模糊查询条件,查询出所有前缀匹配的User对象
     * @param userName 用户名查询条件
     * @return 用户名前缀匹配的所有User对象
     */
    public List<User> queryUserByUserName(String userName){
        return (List<User>)find(QUERY_USER_BY_USERNAME,userName+"%");
    }
 

}

四、junit测试代码

package com.sunsharing.springdemo.dao;
import com.sunsharing.springdemo.domain.User;
import com.sunsharing.component.utils.base.DateUtils;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import static org.testng.Assert.*;
/**
 * Created by nyp on 2015/2/5.
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/viewspace-dao.xml"})
public class UserDaoTest{
    @Autowired
    private UserDao userDao;
   
   @Test
    public void findALLUserByHibernate() {
        List<User> list = userDao.loadAll();
        System.out.println("list="+list);
        Iterator<User> it=list.iterator();
        while(it.hasNext()){
            User u=it.next();
            System.out.println("name="+u.getUserName());
        }     
    }
   @Test
    public void findUserByIdHibernate() {
       User user= userDao.get(70);
       System.out.println("user:"+user.getUserName());
        assertNotNull(user);
        assertEquals(user.getUserName(), "admin");
    }
   @Test
    public void addUserByHibernate(){
        DateUtils.transFormat(new Date(),"yyyyMMddHHmmss");
        System.out.println("date="+DateUtils.transFormat(new Date(), "yyyyMMddHHmmss"));
        User user=new User();
        user.setUserName("HibernateTest15");
        user.setPassword("123456");
        user.setLastVisit(DateUtils.transFormat(new Date(), "yyyyMMddHHmmss"));
        user.setLastIp("255.255.255.255");
        userDao.save(user);
        assertEquals(user.getPassword(),"123456");
    }

}

在此过程中比较头疼的就是Oracle中的date在hibernate中的映射问题

oracle结合hibernate 时日期类型报

java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
at java.sql.Timestamp.valueOf(Timestamp.java:235)
at oracle.jdbc.driver.CharCommonAccessor.getTimestamp(CharCommonAccessor.java:544)
at oracle.jdbc.driver.T4CCharAccessor.getTimestamp(T4CCharAccessor.java:862)
at oracle.jdbc.driver.OracleResultSetImpl.getTimestamp(OracleResultSetImpl.java:1422)
at oracle.jdbc.driver.OracleResultSet.getTimestamp(OracleResultSet.java:516)
at org.apache.commons.dbcp.DelegatingResultSet.getTimestamp(DelegatingResultSet.java:262)
at org.hibernate.type.descriptor.sql.TimestampTypeDescriptor$2.doExtract(TimestampTypeDescriptor.java:62)
at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:64)
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:254)
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:250)
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:230)
at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:331)
at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2283)
at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1527)
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1455)
at org.hibernate.loader.Loader.getRow(Loader.java:1355)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:611)
at org.hibernate.loader.Loader.doQuery(Loader.java:829)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.doList(Loader.java:2542)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
at org.hibernate.loader.Loader.list(Loader.java:2271)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:119)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1716)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:347)
at org.springframework.orm.hibernate3.HibernateTemplate$5.doInHibernate(HibernateTemplate.java:590)
at org.springframework.orm.hibernate3.HibernateTemplate$5.doInHibernate(HibernateTemplate.java:1)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.loadAll(HibernateTemplate.java:584)
at com.sunsharing.springdemo.dao.BaseDao.loadAll(BaseDao.java:56)
at com.sunsharing.springdemo.dao.TesthTest.findUserByHibernate(TesthTest.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)

注解配置那边有加这些:@Temporal(value = TemporalType.TIMESTAMP)
private Date user_date;(Date引的是java.util.date;oracle 数据库那边用的是char(34))

问题解决:此问题是由POJO中对应Oracle 中的char字段导致,把char改为date 即可。

此为一种解决方法,但结合实际开发,并不一定都这么用。另外一种解决方法为就是数据库中的日期用char,而模型层中对应的属性用String类型即可。(上面给出的源码即为次种解决方案)

最后补充下SQL语句:

CREATE SEQUENCE user_id_sequence
INCREMENT BY 1 -- 每次加几个
START WITH 1 -- 从1开始计数
NOMAXVALUE -- 不设置最大值
NOCYCLE -- 一直累加,不循环
NOCACHE;            
--不缓存
--创建用户表
 CREATE TABLE t_user (
   user_id   NUMBER(6) primary key,
   user_name VARCHAR2(30),
   password  VARCHAR2(32),
   last_visit CHAR(28),
   last_ip  VARCHAR2(23)
);
insert into t_user(USER_ID,U_TYPE,LOGIN_ID,NAME,PWD,DEL,CREATE_TIME,UPDATE_TIME)
 values(USER_ID_SEQUENCE.NEXTVAL,1,'admin','管理员','123456',0,sysdate, sysdate);


共有 人打赏支持
粉丝 15
博文 35
码字总数 32773
×
yope
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: