【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().flush(); 这个flush方法,如果不加这个方法,也是存不进数据库的。 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、让我奇怪的是,我另外一个实体这样保存是可以的, 另外一个实体与这个实体唯一不同的是,那个实体,主键是(id),Integer类型,而这个实体则是String(versionSequence),类型,(存放uuid类型) |
|
5分 |
看后台打印sql
目测应该是执行了update了 |
后台啥都木有打印啊。 |
|
我写save() 咋会执行uodate()方法呢 |
|
5分 |
|
5分 |
我我可以把我的经验跟你讲一下,哈,经验如下:
如果如果实体的主键已经注解为自动生成,那么这个时候你在save之前再去设置这个主键,那么保存就会失败,如果需要主动设置,则把实体里自动生成主键的注解去掉。 |
谢谢,我换成save()方法也是无效啊。这个不是单主键的问题啊、 让我奇怪的是,我另外一个实体这样保存是可以的, 另外一个实体与这个实体唯一不同的是,那个实体,主键是(id),Integer类型,而这个实体则是String(versionSequence),类型,(存放uuid类型) |
|
1、我是主键自动生成uuid类型的, 另外一个实体与这个实体唯一不同的是,那个实体,主键是(id),Integer类型,而这个实体则是String(versionSequence),类型,(存放uuid类型) |
|
85分 |
1.flush的问题
如果主键生成策略是uuid等不是由数据库生成的,则session.save()时并不会发出SQL语句,只有flush时才会发出SQL语句,但如果主键生成策略是native由数据库生成的,则session.save的同时就发出SQL语句。 2.saveorupdate的问题 在执行的时候hibernate会检查,如果对象在数据库中已经有对应的记录(是指主键),则会更新update,否则会添加数据save 你看下每次生成的主键是不是一样的,把表数据清空,重新试下saveorupdate方法是否能保存到库表 |
确实是第一条,如果主键生成策略是uuid等不是由数据库生成的,则session.save()时并不会发出SQL语句,只有flush时才会发出SQL语句,但如果主键生成策略是native由数据库生成的,则session.save的同时就发出SQL语句。 这个问题。3Q |