【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方法是否能保存到库表