首页 > 代码库 > hibernate4无法保存数据
hibernate4无法保存数据
hibernate4无法保存数据
author: hiu
以后都发文章我都备注一下作者了,hiu就是我了
红色字体更新日期:2014-07-08
初次使用hibernate4,使用getCurrentSession保存对象时无法将对象的数据保存进数据库,经过一番试验后,发现原来要配置事务才干保存数据。
保存数据失败原因:
没有配置事务,通过手动写一个事务,才干提交数据。手动写一个事务,用getCurrentSession也无法保存数据,仅仅能使用openSession才干保存数据。
解决的方法:
配置spring声明式事务,不建议使用注解来配置事务,注解配置事务,仅仅在xml配置切面事务失败时,才用来測试。一般xml配置切面事务失败原因,找不到包,还有切面路径找不到类。今天(2014-07-08)在保存数据时发现,假设做一对多的表保存数据的话,即使xml配置切面事务的切面不对,也能使用getCurrentSession保存数据,但事务就无法回滚了:
spring-hibernate.xml
<aop:config> <!--我在Service前面加了1234,目的:不让匹配到相应的类开启事务--> <aop:pointcut id="transactionPointcut" expression="execution(* com..service.*1234Service.*(..))" /> <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" /> </aop:config>
service层代码:
public EmployeeVo save(EmployeeVo employeeVo, Map<String, String> pageParam) throws SQLException { Employee employee =new Employee(); String keyjobno=employeeVo.getCompany().trim()+employeeVo.getJobno().trim(); //employee表 employeeVo.setKeyjobno(keyjobno.trim());//主键,公司+工号 employeeVo.setIfout("在会"); BeanUtils.copyProperties(employeeVo, employee); //in_union_his表 InUnionHis inunion=new InUnionHis(); BeanUtils.copyProperties(employeeVo, inunion); inunion.setEmployee(employee); Set<InUnionHis> inUnionHises = new HashSet<InUnionHis>(); inUnionHises.add(inunion); employee.setInUnionHises(inUnionHises); employeeDao.save(employee); return employeeVo; }
以上是用来做插入的,在保存主表employee表(一方)数据时,也将从表in_union_his(多方)的数据保存,控制台打印出来的sql语句:
2014-07-08 18:33:46 [org.hibernate.SQL]-[DEBUG] insert into union_ssh.employee (bornboon, borndate, company, createdate, dept, getborndate, getmarrydate, id, identitycard, ifout, interest, jobno, lodging, marry, marryboon, name, nativename, operator, phone, politicsface, sex, keyjobno) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) Hibernate: insert into union_ssh.employee (bornboon, borndate, company, createdate, dept, getborndate, getmarrydate, id, identitycard, ifout, interest, jobno, lodging, marry, marryboon, name, nativename, operator, phone, politicsface, sex, keyjobno) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 2014-07-08 18:33:46 [org.hibernate.engine.spi.ActionQueue]-[DEBUG] Executing identity-insert immediately 2014-07-08 18:33:46 [org.hibernate.SQL]-[DEBUG] insert into union_ssh.in_union_his (createdate, keyjobno, inuniondate, operator) values (?, ?, ?, ?) Hibernate: insert into union_ssh.in_union_his (createdate, keyjobno, inuniondate, operator) values (?, ?, ?, ?) 2014-07-08 18:33:46 [org.hibernate.id.IdentifierGeneratorHelper]-[DEBUG] Natively generated identity: 81 2014-07-08 18:33:46 [org.springframework.security.web.context.HttpSessionSecurityContextRepository]-[DEB
能够看到sql语句插入了两张表的数据,这就说明了在没有配置相应的事务切面时,依旧能够使用getCurrentSession保存数据,只是这样的前提是一定要在一对多的表关系中进行才干够的,假设我将上面service层//in_union_his表以下的代码去掉,仅仅做保存employee表,这时使用
getCurrentSession保存数据是无法运行的,在控制台也没有不论什么的sql语句打印出来的。
说明 :
1、要注意,在web.xml配置openSessionInViewFilter用来启动hibernate,在经过url请求后,这里就会开启hibernate的session,假设不配置,就无法使用getCurrentSession了,具体配置,请看以下web.xml的配置,
2、以下的代码是用AOP配置的事务,注解方式的事务我已经凝视掉了,请看UserService里面凝视掉的事务注解
3、dao和service我都是用注解注入的
4、以下的几个xml文件除了applicationContext-security.xml这个配置文件外,其他的几个xml文件都是參照easyUI教程中的孙宇老师的视频配置的,有兴趣的朋友可下载下来看看,比較适合刚入门的朋友
5、项目是用maven搭建的,比較方便的,不用再去找jar包,仅仅要在pom.xml文件配置,在连接网络的前提下就能够自己主动下载jar包了,能够看看以下的pom.xml文件里,我下载了那些jar包
6、由于我在spring-hibernate.xml文件配置了<prop key="hibernate.show_sql">${hibernate.show_sql}</prop> ,这个值为true时,假设运行了sql语句,就会在控制台打印出sql语句的,我在測试时,假设数据没保存进数据库,控制台是不会打印出sql语句的,成功保存数据后,打印出的信息:
2014-06-28 16:40:10 [org.hibernate.SQL]-[DEBUG] insert into union_ssh.pub_users (enabled, issys, user_account, user_desc, user_name, user_password, user_id) values (?, ?, ?, ?, ?, ?, ?) Hibernate: insert into union_ssh.pub_users (enabled, issys, user_account, user_desc, user_name, user_password, user_id) values (?, ?, ?, ?, ?, ?, ?)
以下贴出代码:
UserService:
package com.user.service; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.user.dao.UserDaoI; import com.user.model.PubUsers; import com.user.pageModel.UsersPageModel; import framework.base.dao.BaseDaoI; import framework.base.model.DataGrid; import framework.base.model.GridModel; import framework.base.model.User; @Service("userService")
@Transactional 使用注解配置事务 public class UserService { private UserDaoI userDaoi; //以下3个注解都是用来配置事务的,仅仅要在这个类的头部加上事务注解,就能保存数据进数据库,不管使用那个,都不会影响数据是提交 /* * 假设有事务, 那么增加事务, 没有的话新建一个(默认情况下) * @Transactional(propagation=Propagation.REQUIRED) */ /*不管是否存在事务,都创建一个新的事务,原来的挂起,新的运行完成,继续运行老的事务 * @Transactional(propagation=Propagation.REQUIRES_NEW) */ /*容器不为这种方法开启事务 * @Transactional(propagation=Propagation.NOT_SUPPORTED) */ public User save(User user) throws Exception { PubUsers t = new PubUsers(); BeanUtils.copyProperties(user, t); t.setUserId(88); t.setEnabled(1); t.setIssys(1); userDaoi.save(t); //throw new RuntimeException();//用来測试事务回滚 return user; } public BaseDaoI<PubUsers> getUserDao() { return userDao; } public UserDaoI getUserDaoi() { return userDaoi; } @Autowired public void setUserDaoi(UserDaoI userDaoi) { this.userDaoi = userDaoi; } }
UserDaoI:
package com.user.dao; import java.util.List; import com.user.model.PubUsers; public interface UserDaoI { public void save(PubUsers t); }
UserDaoImpl:
package com.user.dao.impl; import java.util.Iterator; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import com.user.dao.UserDaoI; import com.user.model.PubUsers; @Repository(value=http://www.mamicode.com/"userDao")>
spring-hibernate.xml,主要配置了数据库连接,和事务:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <!-- JNDI方式配置数据源 --> <!-- <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value=http://www.mamicode.com/"${jndiName}"> -->>
spring.xml<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 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 "> <!-- 引入属性文件 <bean id="propertyConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location"> <value>classpath:jdbc.properties</value> </property> </bean> --> <context:property-placeholder location="classpath:config.properties" /> <!-- 自己主动扫描包 ,主要为了使用注解注入,假设不扫描,就无法使用注解注入了,只是这里扫不扫描和事务配置无关--> <context:component-scan base-package="com.*.dao.impl,com.*.service,framework.base.dao.impl"/> </beans>
web.xml<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <display-name></display-name> <!-- spring配置文件位置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring.xml,classpath:spring-hibernate.xml,classpath:applicationContext-security.xml</param-value> </context-param> <!-- spring security 过滤器, 这个的位置顺序和spring的监听器启动位置没有什么关系,能够放在spring监听器的前面,也能够放置在后面。 但一定要放在struts的过滤器前面,由于假设有自己定义的登录页面,当登录时,就会跳转到了struts相应的action中, 导致无法使用spring security的验证登录了,正常情况下,应该登录时,会经过自己定义的MyUsernamePasswordAuthenticationFilter类的attemptAuthentication方法进行验证。 假设验证成功,则登录成功,不再运行相应的action验证登录 ;spring security验证失败,则跳回指定登录失败的页面。 --> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- spring监听器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- hibernate配置 --> <filter> <filter-name>openSessionInViewFilter</filter-name> <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class> <init-param> <param-name>singleSession</param-name> <param-value>true</param-value> </init-param> </filter> <!-- Struts2配置 --> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <!-- hibernate的session启动过滤器,在url请求action时启动 ,不配置这个,url请求时无法启动hibernate的session--> <filter-mapping> <filter-name>openSessionInViewFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- struts拦截的url后缀 --> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*.action</url-pattern> <url-pattern>*.jsp</url-pattern> </filter-mapping> <!-- 修复数据库监听器 <listener> <listener-class>com.menu.listener.RepairListener</listener-class> </listener> --> <!-- 登录验证码的servlet --> <servlet> <servlet-name>CheckCode</servlet-name> <servlet-class>framework.util.CheckCode</servlet-class> </servlet> <servlet-mapping> <servlet-name>CheckCode</servlet-name> <url-pattern>/servlet/CheckCode</url-pattern> </servlet-mapping> <!-- log4j ,用来启动log4j --> <servlet> <servlet-name>Log4jInitServlet</servlet-name> <servlet-class> framework.util.Log4jInitServlet </servlet-class> <init-param> <param-name>log4jLocation</param-name> <param-value>WEB-INF/classes/log4j.properties</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet> <welcome-file-list> <welcome-file>/login.jsp</welcome-file> </welcome-file-list> </web-app>applicationContext-security.xml,这个本来不打算贴出来的,由于这是spring security权限管理的配置文件,仅仅供大家參考一下,以后有时间,再发一下这个配置的文章
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> <!-- No bean named 'springSecurityFilterChain' is defined 1、 这时公布一下你的项目,查看tomcat的webapps目录下,找到你的项目目录的classes目录有没有相关的spring.xml文件存在,不存在就会报错 2、查看web.xml文件<param-value>标签有没有引入applicationContext-security.xml这个文件 --> <!-- 不用经过spring security过滤,一般js、css都不须要过滤 --> <http pattern="/*/js/**" security="none"/> <http pattern="/common/js/**" security="none"/> <http pattern="/login.jsp" security="none"/> <!-- auto-config="true" --> <http use-expressions="true" entry-point-ref="authenticationProcessingFilterEntryPoint" > <!-- 不再在这里对url进行权限拦截,在数据库中取出url中相应的权限 <intercept-url pattern="/**" access="ROLE_USER" /> --> <!-- 单用户登陆 --> <session-management> <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" /> </session-management> <!-- 这样的自己定义的登录页面,不能经过security的用户信息验证,也就等于不能取出用户的权限 <form-login login-page='/login.jsp' default-target-url="/index.jsp"/> --> <!-- 尝试訪问没有权限的页面时跳转的页面 --> <access-denied-handler error-page="/403.jsp"/> <custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER" /> <custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/> <!-- 检測失效的sessionId,session超时时,定位到另外一个URL --> <session-management invalid-session-url="/sessionTimeOut.jsp" /> <!-- <custom-filter ref="logoutFilter" before="LOGOUT_FILTER"/> --> <logout invalidate-session="true" logout-success-url="/" logout-url="/logout"/> </http> <!-- 登录验证器 --> <beans:bean id="loginFilter" class="framework.security.login.MyUsernamePasswordAuthenticationFilter"> <!-- value=http://www.mamicode.com/"/loginUser.action"处理登录表单的action ,value值要以“/”开关,否则会报错 :>
pom.xml<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>SSHMS</groupId> <artifactId>SSHMS</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name/> <description/> <!-- 指定Maven仓库 --> <repositories> <repository> <id>maven</id> <name>Maven Repository Switchboard</name> <layout>default</layout> <url>http://repo1.maven.org/maven2</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> <repository> <id>alibaba-opensource</id> <name>alibaba-opensource</name> <url>http://code.alibabatech.com/mvn/releases/</url> <layout>default</layout> </repository> <repository> <id>alibaba-opensource-snapshot</id> <name>alibaba-opensource-snapshot</name> <url>http://code.alibabatech.com/mvn/snapshots/</url> <layout>default</layout> </repository> </repositories> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <!-- JUnit4 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11-beta-1</version> <scope>test</scope> </dependency> <!-- log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!-- fastJson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.1.24</version> </dependency> <!-- spring3 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>3.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>3.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>3.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>3.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>3.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>3.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>3.1.2.RELEASE</version> </dependency> <!-- struts2 --> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>2.3.16.3</version> <!-- 假设有hibernate时要去除这个,由于hibernate也有这个类,不能以这个取代hibernate的那个,否则会出错 --> <exclusions> <exclusion> <groupId>javassist</groupId> <artifactId>javassist</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-spring-plugin</artifactId> <version>2.3.16.3</version> </dependency> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-convention-plugin</artifactId> <version>2.3.16.3</version> </dependency> <!-- 增加mysql驱动依赖包 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.27</version> </dependency> <!-- 增加druid数据源依赖包 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.0</version> </dependency> <!-- spring事务切面的包 --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.7.4</version> </dependency> <!-- hibernate4 --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.1.7.Final</version> </dependency> <!-- spring security --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>3.2.4.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>3.2.4.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>3.2.4.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>3.2.8.RELEASE</version> <scope>compile</scope> </dependency> <!-- org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.filterChains': Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/web/context/request/async/CallableProcessingInterceptor --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>3.2.8.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.1</version> <scope>compile</scope> <optional>true</optional> </dependency><!--注解事务要引入的包--> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-war-plugin</artifactId> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> </build> </project>也贴上一张项目的架构图吧
hibernate4无法保存数据