当前位置: 代码迷 >> J2EE >> 【100分】请问关于hibernate的save方法无效的有关问题
  详细解决方案

【100分】请问关于hibernate的save方法无效的有关问题

热度:39   发布时间:2016-04-17 23:36:44.0
【100分】请教关于hibernate的save方法无效的问题
本帖最后由 Javainging 于 2014-10-16 18:43:31 编辑
【100分】请教关于hibernate的save方法无效的问题

1、serviceImpl方法如下:

@Repository
public class VersionControlServiceImpl  extends BaseHibernateDAO<Versioncontrol, String> implements VersionControlService{

private Logger log = Logger.getLogger(VersionControlServiceImpl.class);


@Override
public void saveOrUpDate(Versioncontrol versionControl) {
log.debug("saving Userinfo instance");
try {
Session session = this.getSession();

super.saveOrUpDate(versionControl);
// this.getSession().save(versionControl);
// this.getSession().flush();
log.debug("save successful");
} catch (RuntimeException re) {
log.error("save failed", re);
throw re;
}
}

}


代码如上所示,如果用super.saveOrUpDate(versionControl); 这个方法来保存的话,根本值就没存进数据库,感觉像是事物没开启一样。
但是,用下面的两行
// this.getSession().save(versionControl);
// this.getSession().flush();

就是这注释掉的两行,则是可以存进数据库的。起关键作用的是this.getSession().flush(); 这个flush方法,如果不加这个方法,也是存不进数据库的。

2、BaseHibernateDAO如下:

package com.example.basedao;

import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import com.example.util.GenericsUtils;

public class BaseHibernateDAO<E extends java.io.Serializable, PK extends java.io.Serializable>
implements IBaseHibernateDAO<E, PK> {
@Autowired
@Qualifier("sessionFactory")
private SessionFactory sessionFactory;


private Class<E> entityClass;


@SuppressWarnings("unchecked")
public BaseHibernateDAO() {

this.entityClass = GenericsUtils.getSuperClassGenricType(getClass());
}

public void delete(PK id) {
getSession().delete(this.get(id));
getSession().flush();
}

@SuppressWarnings("unchecked")
public E get(PK id) {

return (E) getSession().get(entityClass, id);
}

public Session getSession() {

return sessionFactory.getCurrentSession();
}

@SuppressWarnings("unchecked")
public List<E> listAll(){

return getSession().createQuery("from "+entityClass.getName()).list();
}

public void save(E entity) {

getSession().save(entity);

}

public void update(E entity) {

getSession().update(entity);
getSession().flush();
}

public void saveOrUpDate(E entity) {

getSession().saveOrUpdate(entity);

}

}





3、Spring关于事务的配置文件如下:

<!-- 配置文件 数据库配置文件或其他配置文件 -->
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:jdbc.properties</value>
                <value>classpath:config.properties</value>
            </list>
        </property>
    </bean>

<!-- 数据库连接池配置 -->
   <bean id="dataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">
<property name="alias" value="proxoolDataSource"/>
<property name="driver" value="${connection.driver_class}" />
<property name="driverUrl" value="${connection.url}" />
<property name="user" value="${connection.username}" />
<property name="password" value="${connection.password}" />
<property name="maximumConnectionCount" value="${proxool.maximum.connection.count}"/>
<property name="minimumConnectionCount" value="${proxool.minimum.connection.count}" />
<property name="statistics" value="${proxool.statistics}" />
<property name="simultaneousBuildThrottle" value="${proxool.simultaneous.build.throttle}"/>
</bean>

<!-- SessionFactory配置 -->
   <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
     <property name="dataSource" ref="dataSource"/>
     <property name="packagesToScan">
<list>
<value>com.example.*</value>
</list>
</property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <prop key="hibernate.format_sql">false</prop>
                <prop key="hibernate.query.substitutions">${hibernate.query.substitutions}</prop>
                <prop key="hibernate.default_batch_fetch_size">${hibernate.default_batch_fetch_size}</prop>
                <prop key="hibernate.max_fetch_depth">${hibernate.max_fetch_depth}</prop>
                <prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
                <prop key="hibernate.bytecode.use_reflection_optimizer">${hibernate.bytecode.use_reflection_optimizer}</prop>
                
                <!-- 缓存Cache配置 -->
                <prop key="hibernate.cache.provider_class">${hibernate.cache.provider_class}</prop>
                <prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
                <prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
                <prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
                <prop key="net.sf.ehcache.configurationResourceName">${net.sf.ehcache.configurationResourceName}</prop>
                <prop key="hibernate.cache.use_structured_entries">${hibernate.cache.use_structured_entries}</prop>
            </props>
        </property>
   </bean>

<!-- 开启AOP监听 只对当前配置文件有效 -->
<aop:aspectj-autoproxy expose-proxy="true"/>

<!-- 开启注解事务 只对当前配置文件有效 -->
   <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>  

<!-- 事务处理 -->
    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

<!-- 事物传播属性配置 -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="create*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="merge*" propagation="REQUIRED" />
            <tx:method name="del*" propagation="REQUIRED" />
            <tx:method name="remove*" propagation="REQUIRED" />
            <tx:method name="put*" propagation="REQUIRED" />
            <tx:method name="use*" propagation="REQUIRED"/>
            <tx:method name="sessionDestroyed*" propagation="REQUIRED"/>
            <tx:method name="get*" propagation="REQUIRED" read-only="true" />
            <tx:method name="count*" propagation="REQUIRED" read-only="true" />
            <tx:method name="find*" propagation="REQUIRED" read-only="true" />
            <tx:method name="list*" propagation="REQUIRED" read-only="true" />
            <tx:method name="*"  propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

<!-- 事务拦截配置 -->
    <aop:config expose-proxy="true" >
        <aop:pointcut id="txPointcut" expression="execution(* com.example..*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
    </aop:config>



4、让我奇怪的是,我另外一个实体这样保存是可以的,
而且不需要flush方法也是可以保存进数据库的。

另外一个实体与这个实体唯一不同的是,那个实体,主键是(id),Integer类型,而这个实体则是String(versionSequence),类型,(存放uuid类型)



------解决思路----------------------
看后台打印sql
目测应该是执行了update了
------解决思路----------------------
saveOrUpdate(单主键情况)
楼主你看看这个就明白了
一般来说如果你能确定你即将操作对象的状态,则不需要用saveOrUpdate
------解决思路----------------------
我我可以把我的经验跟你讲一下,哈,经验如下:
如果如果实体的主键已经注解为自动生成,那么这个时候你在save之前再去设置这个主键,那么保存就会失败,如果需要主动设置,则把实体里自动生成主键的注解去掉。
------解决思路----------------------
1.flush的问题
  如果主键生成策略是uuid等不是由数据库生成的,则session.save()时并不会发出SQL语句,只有flush时才会发出SQL语句,但如果主键生成策略是native由数据库生成的,则session.save的同时就发出SQL语句。
2.saveorupdate的问题
在执行的时候hibernate会检查,如果对象在数据库中已经有对应的记录(是指主键),则会更新update,否则会添加数据save
你看下每次生成的主键是不是一样的,把表数据清空,重新试下saveorupdate方法是否能保存到库表
  相关解决方案