做一下笔记(参考Spring 事务管理高级应用难点剖析: 第 2 部分):
调用私有方法:下面的私有方法test出现异常,会受到事务控制
package com.tch.test.template.service;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.tch.test.template.dao.QQServiceGroupDao;
import com.tch.test.template.po.QQServiceGroup;
@Service("xxService")
public class QQServiceGroupServiceImpl implements QQServiceGroupService {
@Resource(name="QQServiceGroupDao")
private QQServiceGroupDao QQServiceGroupDao;
@Override
@Transactional(rollbackFor=Exception.class)
public void addQQServiceGroup(LBQQServiceGroup group) throws Exception {
test(group);
}
private void test(QQServiceGroup group) throws Exception {
QQServiceGroupDao.saveEntity(group);
throw new Exception("私有方法异常");
}
}
1.private 方法上面使用spring注解事物能起作用吗?
不能,因为spring的事务无非是通过两种方式:一种是JDK的Proxy代理(实现相同接口),另一种是使用cglib(通过继承该类,并重写方法),无论哪种,对于私有方法都不能实现代理,也就不能实现事务管理了。
2.既使用了hibernate又使用了ibatis或者jdbc的话,使用spring配置事物该怎么配置?
3.有三个方法 a,b,c
a调用b,
c也调用b,
现在要求a调用b的时候,b的事务传播特性是required(也就是共用一个事物)
并且c调用b的时候,b的事务传播特性是独立的(也就是b单独使用一个事物)
4.没有实现接口的类,配置注解事务能起作用吗?
可以;
这时候的事务是通过cglib扩展字节码的方式实现的(也就是上面说到的继承并重写方法的方式),
如果是实现了接口的类,它的事务是通过JDK自带的Proxy实现同样的接口的代理类实现的,
平时我们使用接口的方式的好处是方便以后扩展实现类
5.不能受到spring事务管理的方法:
如果是 基于接口的动态代理:除 public 外的其它所有的方法都不能使用spring事务,此外 public static 也不能被增强
如果是 基于 CGLib 的动态代理:private、static、final 的方法不能受到spring事务管理
Maven依赖:
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.tch.test</groupId> <artifactId>template</artifactId> <packaging>war</packaging> <version>1.0.0</version> <name>template Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <!-- junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit-version}</version> <scope>test</scope> </dependency> <!-- spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-version}</version> </dependency> <!-- spring-orm --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring-version}</version> </dependency> <!-- hibernate --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hiberante-version}</version> </dependency> <!-- hibernate-proxool --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-proxool</artifactId> <version>${hiberante-version}</version> </dependency> <!-- struts2 --> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>${struts2-version}</version> </dependency> <!-- struts2-spring-plugin --> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-spring-plugin</artifactId> <version>${struts2-version}</version> </dependency> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql-version}</version> </dependency> <!-- log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j-version}</version> </dependency> <!-- slf4j-log4j --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j-version}</version> </dependency> <!-- aspectjrt --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectj-version}</version> </dependency> <!-- aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectj-version}</version> </dependency> </dependencies> <build> <finalName>template</finalName> </build> <properties> <junit-version>4.11</junit-version> <spring-version>3.2.6.RELEASE</spring-version> <hiberante-version>3.6.10.Final</hiberante-version> <struts2-version>2.3.16</struts2-version> <mysql-version>5.1.28</mysql-version> <log4j-version>1.2.17</log4j-version> <slf4j-version>1.7.5</slf4j-version> <aspectj-version>1.7.4</aspectj-version> </properties> </project>
如果要修改struts2的拦截地址后缀为 *.htm和 *.action则需要在struts.xml或者struts.properties中配置:
在struts.xml中配置的话:
<constant name="struts.action.extension" value=",htm,action"></constant>或则在struts.properties中配置:
struts.action.extension=,htm,action
前面的逗号是为了可以拦截不加后缀的请求,例如: http://localhost:8080/ssh/show.htm 、 http://localhost:8080/ssh/show.action 、 http://localhost:8080/ssh/show 三种方式
这里的hibernate功能没有真正的使用
首先当然是jar包了:
struts2里面的Jar包:下载的struts2压缩包里面的struts-2.3.15.1\apps\struts2-blank,直接引入,另外就是struts2-spring-plugin-2.3.15.1.jar这个struts2和spring整合的jar
hibernate: hibernate3.jar是肯定的,另外就是hibernate-distribution-3.6.10.Final\lib\required下面的必须的包,以及jpa下面的hibernate-jpa-2.0-api-1.0.1.Final.jar
spring: spring.jar
cglib-nodep-2.1_3.jar
slf4j-api-1.5.0.jar
slf4j-log4j12-1.5.0.jar
还有就是连接数据库的(mysql为例:)mysql-connector-java-5.0.8-bin.jar
所有的包在图片里面有汇总
好了,下面开始进入正题:
web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Struts Blank</display-name> <!-- 指定spring配置文件applicationContext.xml(可以多个)的位置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:applicationContext.xml</param-value> </context-param> <!-- 服务器启动的时候加载spring --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 配置struts2的filter --> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> <!-- 配置字符编码过滤器 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
applicationContext.xml:注解事务管理,需要在方法上加@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
<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" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- 启动注入功能 --> <context:annotation-config /> <!-- 启动扫描component功能 --> <context:component-scan base-package="com.tch.test" /> <!-- 启动注解实物配置功能 --> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> <!-- 数据源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/test"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> <!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 使用xml和注解同时来映射实体类 --> <bean class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" id="sessionFactory"> <property name="dataSource" ref="dataSource"></property> <property name="packagesToScan"> <list> <value>com.tch.test.ssh.entity.annotation</value><!-- 注解的实体类所在的包,例如下面的Student.class --> </list> </property> <property name="mappingLocations"> <list> <value>classpath*:com/tch/test/ssh/entity/*.hbm.xml</value><!-- 指定xml格式的映射文件位置 --> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> </bean> <!--读取数据库配置文件 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mappingLocations"> <value>classpath:com/tch/test/ssh/entity/*.hbm.xml</value> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean> --> </beans>
xml文件配置的事务管理方式:这种方式不需要在方法上加@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
<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" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- 启动注入功能 --> <context:annotation-config /> <!-- 启动扫描component功能 --> <context:component-scan base-package="test,com.tch.test" /> <!-- 不启动注解实物配置功能 <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="get*" read-only="true"/> <tx:method name="select*" read-only="true"/> <tx:method name="*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut expression="execution(* com.tch.test.ssh..*.*(..))" id="testpointcut"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="testpointcut"/> </aop:config> <!-- 数据源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/test"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> <!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!--读取数据库配置文件 --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mappingLocations"> <value>classpath:com/tch/test/ssh/entity/*.hbm.xml</value> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean> <!-- 使用xml和注解同时来映射实体类 --> <!-- <bean class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" id="sessionFactory"> <property name="dataSource" ref="dataSource"></property> <property name="packagesToScan"> <list> <value>com.tch.test.ssh.entity.annotation</value><!-- 注解的实体类所在的包,例如下面的Student.class --> </list> </property> <property name="mappingLocations"> <list> <value>classpath*:com/tch/test/ssh/entity/*.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> </bean> --> </beans>
struts.xml:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <constant name="struts.enable.DynamicMethodInvocation" value="true" /> <constant name="struts.devMode" value="true" /> <!-- 自定义package,在里面加入拦截器栈,注意最后要加上默认拦截器栈,并将自定义的拦截器栈作为默认的拦截器栈,后面的package直接继承该package即可实现所有action加入拦截功能 --> <package name="mypackage" extends="struts-default"> <interceptors> <interceptor name="checkLogin" class="checkLogin"></interceptor> <interceptor-stack name="myStack"> <interceptor-ref name="checkLogin"/> <interceptor-ref name="defaultStack"/> </interceptor-stack> </interceptors> <default-interceptor-ref name="myStack"/> </package> <package name="default" namespace="/" extends="mypackage"> <default-action-ref name="index" /> <global-results> <result name="error">/error.jsp</result> </global-results> <global-exception-mappings> <exception-mapping exception="java.lang.Exception" result="error" /> </global-exception-mappings> <action name="show" class="userAction" method="select"> <result>/WEB-INF/pages/User.jsp</result> </action> <action name="goEdit" class="userAction" method="goEdit"> <result>/WEB-INF/pages/editUser.jsp</result> </action> <!-- 使用通配符 --> <action name="*User" class="userAction" method="{1}User"> <result type="redirectAction"> <param name="actionName">show</param> <param name="namespace">/</param> </result> </action> </package> </struts>
拦截器:
package com.tch.test.ssh.interceptor;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts2.StrutsStatics;
import org.springframework.stereotype.Component;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.tch.test.ssh.entity.User;
import com.tch.test.ssh.info.LoginInfo;
import com.tch.test.ssh.info.UserInfo;
@Component("checkLogin")
public class CheckLoginInterceptor implements Interceptor {
private static final long serialVersionUID = 1L;
public CheckLoginInterceptor(){
System.out.println("CheckLoginInterceptor拦截器创建");
}
@Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("interceptor............................");
HttpServletRequest request = (HttpServletRequest) invocation.getInvocationContext().get(StrutsStatics.HTTP_REQUEST);
String url = request.getRequestURI();
if(url.contains("/ssh/login.action")){
//登陆
return invocation.invoke();
}
//已经登陆
HttpSession session = request.getSession();
Date current_login_time = (Date) session.getAttribute("login_time");
User user = (User) session.getAttribute("login_user");
if(user == null || user.getId() == null || current_login_time == null){
//session中没有相关信息,则重新登录
return "login";
}
LoginInfo info = (LoginInfo)UserInfo.LOGIN_USERS.get(user.getId());
if(info != null && info.getLoginTime() != null){
Date latest_login_time = info.getLoginTime();
if(latest_login_time.getTime() > current_login_time.getTime()){
ActionContext.getContext().put("errorMessage", "账号在别处登录,当前用户被强制退出 !");
session.invalidate();
System.out.println("*****************删除session*************");
return "error";
}
}
return invocation.invoke();
}
@Override
public void destroy() {
}
@Override
public void init() {
}
}
action:
package com.tch.test.ssh.web.action;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.opensymphony.xwork2.ActionSupport;
import com.tch.test.ssh.entity.Priority;
import com.tch.test.ssh.entity.User;
import com.tch.test.ssh.service.IPriorityService;
import com.tch.test.ssh.service.IUserService;
@Component("userAction")
@Scope("prototype")
public class UserAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private User user;
private List<Priority> priorities;
@Resource(name="userService")
private IUserService userService;
@Resource(name="priorityService")
private IPriorityService priorityService;
private List<User> users;
private List<String> priorityName;
public List<String> getPriorityName() {
return priorityName;
}
public void setPriorityName(List<String> priorityName) {
this.priorityName = priorityName;
}
public String select() throws Exception{
users = userService.select();
System.out.println("所有用户数:"+users.size());
return "success";
}
public String addUser() throws Exception{
System.out.println("add .. "+user);
userService.add(user);
return "success";
}
public String goEdit() throws Exception{
user = userService.getUserById(user.getId());
priorities = priorityService.getPriorityByUserId(user.getId());
System.out.println(user);
return "success";
}
/**
* 删除用户
* @return
* @throws Exception
*/
public String deleteUser() throws Exception{
userService.deleteUser(user.getId());
return "success";
}
/**
* 修改用户信息
* @return
* @throws Exception
*/
public String editUser() throws Exception{
try {
Set<Priority> priorities = priorityService.getPrioritiesByNames(priorityName);
user.setPriorities(priorities);
userService.editUser(user);
} catch (Exception e) {
e.printStackTrace();
}
return "success";
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<Priority> getPriorities() {
return priorities;
}
public void setPriorities(List<Priority> priorities) {
this.priorities = priorities;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
service接口:
package com.tch.test.ssh.service;
import java.util.List;
import java.util.Set;
import com.tch.test.ssh.entity.Priority;
public interface IPriorityService {
/**
* 根据id获取user对象
* @param id
* @return
*/
List<Priority> getPriorityByUserId(Integer id) throws Exception;
/**
* 根据id获取实体对象
* @param id
* @return
*/
Priority getEntity(Integer id) throws Exception;
/**
* 根据name获取实体对象
* @param id
* @return
*/
Set<Priority> getPrioritiesByNames(List<String> names) throws Exception;
/**
* 测试事务
* @throws Exception
*/
void testTransaction() throws Exception;
}
package com.tch.test.ssh.service;
import java.util.List;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.tch.test.ssh.entity.User;
public interface IUserService {
/**
* 测试事务特性
*/
@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
void testTransaction() throws Exception;
/**
* 添加user对象
* @param id
* @return
*/
void add(User user) throws Exception;
/**
* 查询所有user对象
* @param id
* @return
*/
List<User> select() throws Exception;
/**
* 根据id获取user对象
* @param id
* @return
*/
User getUserById(Integer id) throws Exception;
/**
* 根据id获取user对象
* @param id
* @return
*/
void editUser(Integer id, List<String> priorities) throws Exception;
/**
* 根据id获取实体对象
* @param id
* @return
*/
User getEntity(Integer id) throws Exception;
}
service实现类:
package com.tch.test.ssh.service;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.tch.test.ssh.dao.IPriorityDao;
import com.tch.test.ssh.entity.Priority;
@Service("priorityService")
public class PriorityServiceImpl implements IPriorityService {
@Resource(name="priorityDao")
private IPriorityDao priorityDao;
@Override
@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
public List<Priority> getPriorityByUserId(Integer id) throws Exception{
return priorityDao.getPriorityByUserId(id);
}
@Override
@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
public void testTransaction() throws Exception {
Priority p = new Priority();
p.setName("测试");
priorityDao.save(p);
boolean b=true;
if(b){
throw new Exception("priority 抛出异常。。。。");
}
}
}
package com.tch.test.ssh.service;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.tch.test.ssh.dao.IUserDao;
import com.tch.test.ssh.entity.User;
@Service("userService")
@Transactional(propagation=Propagation.REQUIRED)
public class UserServiceImpl implements IUserService {
@Resource(name="userDao")
private IUserDao userDao;
@Override
@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
public void add(User user) throws Exception {
userDao.save(user);
}
@Override
@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
public void editUser(Integer id, List<String> priorities) throws Exception{
userDao.editUser(id, priorities);
}
@Override
@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
public User getUserById(Integer id) throws Exception {
return userDao.get(id);
}
@Override
@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
public List<User> select() throws Exception {
return userDao.getAll();
}
@Override
@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
public User getEntity(Integer id) throws Exception {
return userDao.get(id);
}
@Override
@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
public void testTransaction() throws Exception {
User user = new User();
user.setName("service");
user.setPassword("service");
add(user);
userDao.testTransaction();
}
}
dao:
首先是dao基础接口
package com.tch.test.ssh.dao;
import java.io.Serializable;
import java.util.List;
public interface BaseDao<E, PK extends Serializable> {
/**
* CreaEed on 2013-9-16
* <p>DiscripEion:保存对象</p>
* @reEurn void
*/
void save(E entity);
/**
* CreaEed on 2013-9-16
* <p>DiscripEion:更新对象</p>
* @reEurn void
*/
void update(E entity);
/**
* CreaEed on 2013-9-16
* <p>DiscripEion:删除对象</p>
* @reEurn void
*/
void delete(E entity);
/**
* CreaEed on 2013-9-16
* <p>DiscripEion:根据id查询对象</p>
* @reEurn void
*/
E get(PK id);
/**
* CreaEed on 2013-9-16
* <p>DiscripEion:查询全部对象</p>
* @reEurn void
*/
List<E> getAll();
/**
* Created on: 2013-12-4
* <p>Discription: 保存全部</p>
* @param entities
* @return void
*/
void saveAll(List<E> entities);
}
dao基础实现类:
package com.tch.test.ssh.dao;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
public class BaseDaoImpl<E, PK extends Serializable> extends CommomDao implements BaseDao<E,PK>{
private Class<E> clazz;
@SuppressWarnings("unchecked")
public BaseDaoImpl(){
this.clazz = (Class<E>)((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
@Override
public void delete(E entity) {
getHibernateTemplate().delete(entity);
}
@SuppressWarnings("unchecked")
@Override
public E get(PK id) {
return (E)getHibernateTemplate().get(clazz, id);
}
@SuppressWarnings("unchecked")
@Override
public List<E> getAll() {
return getHibernateTemplate().loadAll(clazz);
/*String hql = "from "+clazz.getName();
System.out.println("hql: "+hql);
return getSession().createQuery(hql).list();*/
}
@Override
public void save(E entity) {
getHibernateTemplate().save(entity);
}
@Override
public void update(E entity) {
getHibernateTemplate().update(entity);
}
@Override
public void saveAll(List<E> entities) {
getHibernateTemplate().saveOrUpdateAll(entities);
}
}
dao接口的demo:
package com.tch.test.ssh.dao;
import com.tch.test.ssh.entity.MyTime;
public interface TimeDao extends BaseDao<MyTime, Integer>{
}
dao实现类的demo:
package com.tch.test.ssh.dao;
import org.springframework.stereotype.Repository;
import com.tch.test.ssh.entity.MyTime;
@Repository("TimeDao")
public class TimerDaoImpl extends BaseDaoImpl<MyTime, Integer> implements TimeDao{
}
package com.tch.test.ssh.dao;
import javax.annotation.Resource;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
public class CommomDao extends HibernateDaoSupport{
@Resource(name="sessionFactory")
public void setSuperSessionFactory(SessionFactory sessionFactory){
this.setSessionFactory(sessionFactory);
}
}
package com.tch.test.ssh.dao;
import java.util.List;
import com.tch.test.ssh.entity.Priority;
public interface IPriorityDao extends BaseDao<Priority,Integer>{
/**
* 根据id获取user对象
* @param id
* @return
*/
List<Priority> getPriorityByUserId(Integer id) throws Exception;
}
package com.tch.test.ssh.dao;
import java.util.List;
import com.tch.test.ssh.entity.User;
public interface IUserDao extends BaseDao<User,Integer> {
/**
* 根据id获取user对象
* @param id
* @return
*/
void editUser(Integer id, List<String> priorities) throws Exception;
/**
* 测试事务
*/
void testTransaction() throws Exception;
}
package com.tch.test.ssh.dao;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.tch.test.ssh.entity.Priority;
@Repository("priorityDao")
public class PriorityDaoImpl extends BaseDaoImpl<Priority,Integer> implements IPriorityDao {
/**
* 根据用户id查询用户权限
* @param id
* @return
*/
@SuppressWarnings("unchecked")
@Override
public List<Priority> getPriorityByUserId(Integer id) throws Exception {
List<Priority> priorities = new ArrayList<Priority>();
String sql = " select p.id,p.name from User u , Priority p , User_Priority up where u.id = :id and u.id = up.userId and p.id = up.priorityId ";
List<Object[]> result = getSession().createSQLQuery(sql).setInteger("id", id).list();
if(result != null && result.size()>0){
Priority temp = null;
for(Object[] obj:result){
temp = new Priority();
temp.setId(Integer.parseInt(obj[0].toString()));
temp.setName(obj[1].toString());
priorities.add(temp);
}
}
return priorities;
}
}
package com.tch.test.ssh.dao;
import java.util.List;
import org.hibernate.Session;
import org.springframework.stereotype.Repository;
import com.tch.test.ssh.entity.User;
@Repository("userDao")
public class UserDaoImpl extends BaseDaoImpl<User,Integer> implements IUserDao{
@Override
public void testTransaction() throws Exception {
User user = new User();
user.setName("test");
user.setPassword("password");
getHibernateTemplate().save(user);
boolean b=true;
if(b){
throw new Exception("priority 抛出异常。。。。");
}
}
/**
* 修改用户权限
* @param id
* @param priorities
*/
@Override
public void editUser(Integer id, List<String> priorities) throws Exception{
//删除已有的
Session session = getSessionFactory().openSession();
String sql = " delete up from User_Priority up where up.userId = :userId ";
session.createSQLQuery(sql).setInteger("userId", id).executeUpdate();
//再重新插入
sql = " insert into User_Priority(userId,priorityId) values(:userId,:priorityId) ";
String sql2 = " select id from priority where name = :name ";
for(String p:priorities){
Integer pId = (Integer) session.createSQLQuery(sql2).setString("name", p).uniqueResult();
session.createSQLQuery(sql).setInteger("userId", id).setInteger("priorityId", pId).executeUpdate();
}
}
}
实体类:Priority.java
package com.tch.test.ssh.entity;
import java.util.Set;
/**
* Priority entity. @author MyEclipse Persistence Tools
*/
public class Priority implements java.io.Serializable {
// Fields
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private Set<User> users;
// Constructors
/** default constructor */
public Priority() {
}
@Override
public String toString() {
return "Priority [id=" + id + ", name=" + name + "]";
}
/** full constructor */
public Priority(String name) {
this.name = name;
}
// Property accessors
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
public void setName(String name) {
this.name = name;
}
}
User.java
package com.tch.test.ssh.entity;
import java.util.Set;
/**
* User entity. @author MyEclipse Persistence Tools
*/
public class User implements java.io.Serializable {
// Fields
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private String password;
private Set<Priority> priorities;
// Constructors
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", password=" + password
+ ", priorities=" + priorities + "]";
}
/** default constructor */
public User() {
}
/** full constructor */
public User(String name, String password) {
this.name = name;
this.password = password;
}
// Property accessors
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Set<Priority> getPriorities() {
return priorities;
}
public void setPriorities(Set<Priority> priorities) {
this.priorities = priorities;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
}
映射文件:(没有配置表关联关系):
注解的实体映射文件:
package com.tch.test.ssh.entity.annotation;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="student")
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
private String name;
private int age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
User.hbm.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.tch.test.ssh.entity.User" table="user" catalog="test"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="identity" /> </id> <property name="name" type="java.lang.String"> <column name="name" length="20"> <comment>姓名</comment> </column> </property> <property name="password" type="java.lang.String"> <column name="password" length="20"> <comment>密码</comment> </column> </property> <set name="priorities" table="User_Priority" inverse="false"> <key column="userId"></key> <many-to-many class="com.tch.test.ssh.entity.Priority" column="priorityId"></many-to-many> </set> </class> </hibernate-mapping>
Priority.hbm.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.tch.test.ssh.entity.Priority" table="priority" catalog="test"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="identity" /> </id> <property name="name" type="java.lang.String"> <column name="name" length="20"> <comment>模块名</comment> </column> </property> <set name="users" table="User_Priority" inverse="true"> <key column="priorityId"></key> <many-to-many class="com.tch.test.ssh.entity.User" column="userId"></many-to-many> </set> </class> </hibernate-mapping>
页面:User.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'User.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<style type="text/css">
*{
margin:0;
padding:0;
color:#666;
}
body{
background-color: #fff;
}
table{
margin:20px auto;
}
a{
text-decoration: none;
color:red;
}
tr{
height:35px;
cursor:pointer;
}
#_table2{
margin-top: 20px;
}
.detail ._mouseover{
background-color:#eee;
}
input[type='text'],input[type='password']{
height:30px;
border:1px solid black;
background-color: #fff;
}
._eventr{
background-color:#eee;
}
</style>
<script type="text/javascript" src="<%=request.getContextPath()%>/common/js/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$("tbody tr").hover(function(){
$(this).addClass('_mouseover');
},function(){
$(this).removeClass('_mouseover');
});
});
//添加用户
function addUser(){
var f = document.forms[0];
f.action = "addUser.action";
f.submit();
}
function deleteUser(id,name){
var result = confirm("确认删除"+name+"?");
if(result){
window.location.href='deleteUser.action?user.id='+id;
}
}
</script>
</head>
<body>
<form action="" method="post">
<table cellpadding="0" cellspacing="0" border="1" width="60%" align="center" class="detail">
<thead>
<tr>
<th width="15%" align="center">id</th>
<th width="15%" align="center">用户名</th>
<th width="15%" align="center">密码</th>
<th width="15%" align="center">操作</th>
</tr>
</thead>
<tbody>
<s:iterator value="users" status="user">
<tr <s:if test="#user.even">class='_eventr'</s:if>>
<td width="15%" align="center"><s:property value="id"/></td>
<td width="15%" align="center"><s:property value="name"/></td>
<td width="15%" align="center"><s:property value="password"/></td>
<td width="15%" align="center">
<a href="javascript:window.location.href='goEdit.action?user.id=<s:property value='id'/>'">编辑</a>
<a href="javascript:deleteUser(<s:property value='id'/>,'<s:property value='name'/>')">删除</a>
</td>
</tr>
</s:iterator>
</tbody>
</table>
<table cellpadding="0" cellspacing="0" border="0" width="60%" align="center" id="_table2">
<tr>
<td colspan="3">用户名:<input type="text" name="user.name">密码:<input type="text" name="user.password"></td>
<td><input type="button" οnclick="addUser()" value="添加用户"></td>
</tr>
</table>
</form>
</body>
</html>
editUser.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'User.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<style type="text/css">
*{
margin:0;
padding:0;
color:#666;
line-height:30px;
}
#content{
width:500px;
margin:30px auto;
}
input[type='checkbox']{
margin-top: 2px;
margin-left: 10px;
margin-right: 10px;
}
input[type='text'],input[type='password']{
height:30px;
border:1px solid black;
background-color: #fff;
}
form .priority{
float:left
margin-left: 20px;
}
</style>
</head>
<body>
<div id="content">
<form action="editUser.action" method="post" name="myform">
用户名:<input type="text" value="<s:property value='user.name'/>" name="user.name">
密码:<input type="text" value="<s:property value='user.password'/>" name="user.password"><br/>
<span class="priority">权限:</span><br/>
<input type="checkbox" name="priorityName" value="管理员" <s:if test="'管理员' in priorities.{name}">checked='checked'</s:if>>管理员<br/>
<input type="checkbox" name="priorityName" value="程序员"<s:if test="'程序员' in priorities.{name}">checked='checked'</s:if>>程序员<br/>
<input type="checkbox" name="priorityName" value="测试员"<s:if test="'测试员' in priorities.{name}">checked='checked'</s:if>>测试员<br/>
<input type="checkbox" name="priorityName" value="运维人员"<s:if test="'运维人员' in priorities.{name}">checked='checked'</s:if>>运维人员<br/>
<input type="hidden" name="user.id" value="${user.id}">
<input type="submit" value="确认修改">
</form>
</div>
</body>
</html>
log4j.properties:
# # Log4J Settings for log4j 1.2.x (via jakarta-commons-logging) # # The five logging levels used by Log are (in order): # # 1. DEBUG (the least serious) # 2. INFO # 3. WARN # 4. ERROR # 5. FATAL (the most serious) # Set root logger level to WARN and append to stdout log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout # Pattern to output the caller's file name and line number. log4j.appender.stdout.layout.ConversionPattern=%d %5p (%c:%L) - %m%n # Print only messages of level ERROR or above in the package noModule. log4j.logger.noModule=FATAL log4j.logger.com.opensymphony.xwork2=info log4j.logger.org.apache.struts2=info
测试类:
package com.tch.test.ssh.test;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.tch.test.ssh.entity.Priority;
import com.tch.test.ssh.entity.User;
public class SpringTest {
@Test
public void testHibernate(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
SessionFactory sessionFactory = (SessionFactory)context.getBean("sessionFactory");
Session session = sessionFactory.openSession();
session.beginTransaction();
User u = new User();
u.setId(1);
u = (User)session.get(User.class, 1);
System.out.println(u.getPriorities());
Priority p = (Priority) session.load(Priority.class, 3);
u.getPriorities().add(p);
// u.getPriorities().remove(p);
// Priority p = new Priority();
// p.setId(3);
// u.setPriorities(null);
session.update(u);
System.out.println(u.getPriorities());
session.getTransaction().commit();
session.close();
}
}
完整代码:网盘下载