SSH整合:No object in the CompoundRoot has a publicly accessible property named 'x'

在运行SSH项目时,调用dept_list.action和调用dept_delete.action时控制台并未打印异常。而调用add.action和edit.action却在控制台打印如下异常:

Developer Notification (set struts.devMode to false to disable this message):
Unexpected Exception caught setting 'x' on 'class com.zeng.ssh.oa.view.DepartmentAction: Error setting expression 'x' with value ['30', ]
Error setting expression 'x' with value ['30', ] - [unknown location]
	at com.opensymphony.xwork2.ognl.OgnlValueStack.handleRuntimeException(OgnlValueStack.java:197)
	at com.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:174)
	at com.opensymphony.xwork2.ognl.OgnlValueStack.setParameter(OgnlValueStack.java:148)
	at com.opensymphony.xwork2.interceptor.ParametersInterceptor.setParameters(ParametersInterceptor.java:318)
	at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:231)
	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:239)
	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:191)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:73)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:91)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:252)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:161)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:193)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:189)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)
	at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:563)
	at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
	at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:149)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:962)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1115)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Unknown Source)
Caused by: No object in the CompoundRoot has a publicly accessible property named 'x' (no setter could be found). - [unknown location]
	at com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor.setProperty(CompoundRootAccessor.java:106)
	at ognl.OgnlRuntime.setProperty(OgnlRuntime.java:2332)
	at ognl.ASTProperty.setValueBody(ASTProperty.java:127)
	at ognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:220)
	at ognl.SimpleNode.setValue(SimpleNode.java:301)
	at ognl.Ognl.setValue(Ognl.java:737)
	at com.opensymphony.xwork2.ognl.OgnlUtil.setValue(OgnlUtil.java:234)
	at com.opensymphony.xwork2.ognl.OgnlValueStack.trySetValue(OgnlValueStack.java:183)
	at com.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:170)
	... 62 more
Developer Notification (set struts.devMode to false to disable this message):
Unexpected Exception caught setting 'y' on 'class com.zeng.ssh.oa.view.DepartmentAction: Error setting expression 'y' with value ['17', ]
Error setting expression 'y' with value ['17', ] - [unknown location]
	at com.opensymphony.xwork2.ognl.OgnlValueStack.handleRuntimeException(OgnlValueStack.java:197)
	at com.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:174)
	at com.opensymphony.xwork2.ognl.OgnlValueStack.setParameter(OgnlValueStack.java:148)
	at com.opensymphony.xwork2.interceptor.ParametersInterceptor.setParameters(ParametersInterceptor.java:318)
	at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:231)
	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:239)
	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:191)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:73)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:91)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:252)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:161)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:193)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:189)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
	at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)
	at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:563)
	at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
	at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:149)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:962)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1115)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Unknown Source)
Caused by: No object in the CompoundRoot has a publicly accessible property named 'y' (no setter could be found). - [unknown location]
	at com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor.setProperty(CompoundRootAccessor.java:106)
	at ognl.OgnlRuntime.setProperty(OgnlRuntime.java:2332)
	at ognl.ASTProperty.setValueBody(ASTProperty.java:127)
	at ognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:220)
	at ognl.SimpleNode.setValue(SimpleNode.java:301)
	at ognl.Ognl.setValue(Ognl.java:737)
	at com.opensymphony.xwork2.ognl.OgnlUtil.setValue(OgnlUtil.java:234)
	at com.opensymphony.xwork2.ognl.OgnlValueStack.trySetValue(OgnlValueStack.java:183)
	at com.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:170)
	... 62 more

departmentAction 代码:

package com.zeng.ssh.oa.view;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.zeng.ssh.oa.domain.Department;
import com.zeng.ssh.oa.service.DepartmentService;
import com.zeng.ssh.oa.util.DepartmentUtils;

@Controller
@Scope("prototype")
public class DepartmentAction extends ActionSupport implements ModelDriven<Department> {

	@Autowired
	private DepartmentService departmentService;

	/*
	 * 表单上有parentId这个name属性,实体类中并未封装这个parentId属性,而是封装Department parent属性,
	 * 在有些时候不希望在实体类中加入此属性. 此时,可以直接在Action中定义一个属性,并为之设置SET(修改)/GET(取值)方法
	 */
	private Long parentId;

	private Department model = new Department();

	@Override
	public Department getModel() {
		return model;
	}

	/** 查询所有 */
	public String list() throws Exception {
		// 0-1.查询所有部门
		// List<Department> deptList = departmentService.findAll();

		// 1-1.部门列表清单上查询顶级部门操作
		List<Department> deptList = null;
		if (parentId == null) {// 查询顶级部门
			deptList = departmentService.findTopList();
		} else {// 查询子级部门
			// 开启了OpenInViewFilter懒加载过滤器,可以获取到关联对象的属性值。
			deptList = departmentService.findChildList(parentId);

			// 部门清单页面的【返回到上一级】 按钮的操作
			// 当前是通过传递的parentId,查询到其对应的子级部门,再通过此parentId查询此对象的父级部门
			Department parent = departmentService.getById(parentId);
			ActionContext.getContext().put("parent", parent);
		}

		ActionContext.getContext().put("deptList", deptList);
		return "list";
	}

	/** 根据ID删除 */
	public String delete() throws Exception {
		departmentService.delete(model.getId());
		return "toList";
	}

	/** 添加页面 */
	public String addUI() throws Exception {
		// 1-1.取得部门列表,用于展示上级部门列表
		List<Department> deptList = departmentService.findAll();
		
		// 1-2.取得顶级部门列表,用于展示上级部门列表
//		List<Department> topList = departmentService.findTopList();
//		List<Department> deptList = DepartmentUtils.getAllDepartments(topList);
		
		ActionContext.getContext().put("deptList", deptList);

		return "saveUI";
	}

	/** 添加 */
	public String add() throws Exception {
		// 上级部门通过页面parentId值,查询到对应的Department对象,再把它设置到model中
		System.out.println("--->	save:parentId = " + parentId);
		// 1-1.保存时设置部门值,部门值有可能为null,统一在baseDao中判断
		Department parent = departmentService.getById(parentId);
		model.setParent(parent);

		// 0-1.保存model数据
		departmentService.save(model);
		return "toList";
	}

	/** 修改页面 */
	public String editUI() throws Exception {
		// 1-1.取得部门列表,用于展示上级部门
		List<Department> deptList = departmentService.findAll();
		
		// 1-2.取得顶级部门列表,用于展示上级部门列表
//		List<Department> topList = departmentService.findTopList();
//		List<Department> deptList = DepartmentUtils.getAllDepartments(topList);
//				
		ActionContext.getContext().put("deptList", deptList);

		// 0-1.获取回显数据
		Department department = departmentService.getById(model.getId());
		System.out.println("id = " + model.getId());
		System.out.println(department.getName());

		// 0-2.把回显数据设置到栈顶
		ActionContext.getContext().getValueStack().push(department);
		
		// 1-2.设置当前的上级部门:上级部门有可能为null,代码必须要严谨
		if (department.getParent() != null) {
			// setParentId(department.getParent().getId());
			// 数据回显,只要相对应的值有值即可回显
			parentId = department.getParent().getId();
		}

		return "saveUI";
	}

	/** 修改 */
	public String edit() throws Exception {
		// 0-1.获取修改数据
		Department department = departmentService.getById(model.getId());

		// 0-2.设置修改数据
		department.setName(model.getName());
		department.setDescription(model.getDescription());

		// 1-1.设置上级部门的所属部门
		System.out.println("--->	edit:parentId" + parentId);
		department.setParent(departmentService.getById(parentId));// 设置所属的上级部门

		// 0-3.保存修改数据
		departmentService.update(department);
		return "toList";
	}

	// -----
	public Long getParentId() {
		return parentId;
	}

	public void setParentId(Long parentId) {
		this.parentId = parentId;
	}
}

DepartmentServiceImpl代码:

package com.zeng.ssh.oa.service.impl;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.zeng.ssh.oa.dao.DepartmentDao;
import com.zeng.ssh.oa.domain.Department;
import com.zeng.ssh.oa.service.DepartmentService;

@Service
@Transactional
@SuppressWarnings("unchecked")
public class DepartmentServiceImpl implements DepartmentService {

	@Autowired
	private DepartmentDao departmentDao;

	@Autowired
	private SessionFactory SessionFactory;
	
	/**
	 * 查询顶级部门
	 * */
	@Override
	public List<Department> findTopList() {
		return this.SessionFactory.getCurrentSession().createQuery(
				"FROM Department d WHERE d.parent IS NULL")
				.list();
	}

	/**
	 * 查询子级部门
	 * */
	@Override
	public List<Department> findChildList(Long parentId) {
		return this.SessionFactory.getCurrentSession()
				.createQuery(
						"FROM Department d WHERE d.parent.id = ?")
				.setParameter(0, parentId)
				.list();
	}
	
	@Override
	public List<Department> findAll() {
		List<Department> deptList = departmentDao.findAll();
		return deptList;
	}

	@Override
	public void delete(Long id) {
		departmentDao.delete(id);
	}

	@Override
	public void save(Department model) {
		departmentDao.save(model);
	}

	@Override
	public Department getById(Long id) {
		Department dept = departmentDao.getById(id);
		return dept;
	}

	@Override
	public void update(Department department) {
		departmentDao.update(department);
	}

}

BaseDaoImpl代码:

package com.zeng.ssh.oa.dao.impl;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.zeng.ssh.oa.dao.BaseDao;

@SuppressWarnings("unchecked")
public abstract class BaseDaoImpl<T> implements BaseDao<T> {

	/* 使用session时,不再需要开事务,关事务。因为配置了事务 */

	@Autowired
	// 当子类使用组件注解,父类的属性也可以通过注入方式注入。
	public SessionFactory sessionFactory;

	public Class<T> clazz;// 在构造方法中初始化,泛型类

	public BaseDaoImpl() {
		// 使用反射技术得到T的真实类型
		// 得到一个包含泛型信息的对象
		ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();// 获取当前new的对象的泛型父类类型
		this.clazz = (Class<T>) pt.getActualTypeArguments()[0];// 获取第一个类型参数的真实类型,像Map<K,V>就有两个泛型参数。
		System.out.println("clazz -----> " + clazz);
	}

	/**
	 * 获取当前可用的session
	 * 
	 * @return
	 */
	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	@Override
	public void save(T entity) {
		getSession().save(entity);
	}

	@Override
	public void delete(Long id) {
		Object obj = getById(id);
		// System.out.println("public method of delete: " + obj);
		if (obj != null) {
			// 这里要删除对象,传入对象的参数.
			// 如果传入对象的ID(假如ID的数据类型是Long的话),则会报错.
			// unknown entity: java.lang.Long(程序虽未报异常,但页面显示异常)
			getSession().delete(obj);
		}
	}

	@Override
	public void update(T entity) {
		getSession().update(entity);
	}

	@Override
	public T getById(Long id) {
		if (id == null) {
			return null;
		} else {
			return (T) getSession().get(clazz, id);
		}
	}

	/*
	 * HQL占位符可以使用?或使用:字符形式,?使用数字来定位,:字符使用字符来定位。
	 * 
	 * @see com.zeng.ssh.oa.dao.BaseDao#getByIds(java.lang.Long[])
	 */
	@Override
	public List<T> getByIds(Long[] ids) {
		return getSession()//
				.createQuery("FROM " + clazz.getSimpleName() + " WHERE id in (:ids)")//
				.setParameterList("ids", ids).list();
	}

	@Override
	public List<T> findAll() {
		return getSession()//
				.createCriteria(clazz)//
				.list();

		// clazz.getSimpleName()获取类的全限定名,包括包名
		// return getSession().createQuery("FROM " +
		// clazz.getSimpleName()).list();
	}

}

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>

	<!-- 配置为开发模式:true为开发模式 -->
	<constant name="struts.devMode" value="true" />
	<!-- 
		目前的请求是URL-pattern=/*的模式,通过xx或xx.action或别的都可以访问
		以下配置把扩展名配置为action,当请求是以.action时进行拦截,也为后续的过滤器做准备.
	-->
	<constant name="struts.action.extension" value="action"></constant>
	<!-- 把主题配置为simple: -->
	<constant name="struts.ui.theme" value="simple"></constant>

	<package name="default" namespace="/" extends="struts-default">
		<!-- 
			method未写,使用默认的execute()方法
			name:test(请求)
			配置测试用的action,
			当spring未与spring整合,class属性写类的全路径限定名
				class="com.zeng.ssh.oa.test.TestAction"
			当spring与struts2整合后,class直接写bean名
				class="testAction"
		-->
		<action name="test" class="testAction">
			<result name="success">/test_hello.jsp</result>
		</action>
		
		
		<!-- 岗位管理:RoleAction -->
		<!-- 
			action	属性
			method	属性:	使用指定的[class=action]中对应的方法,也可以使用通配符“*”:{1}表示匹配name中的第一个“*”通配符。
			name	属性: 	表示请求,如果使用了通配如name=role_*,而method={1},使用role_list表示list方法,role_add表示add方法
			class	属性:	表示Action。使用全路径限定名,如果与spring整合后,则可直接使用bean名
		-->
		<action name="role_*" class="roleAction" method="{1}">
			<!-- 
				result	属性
				name	属性: 表示action返回的字符。
				type	属性:指定redirect[重定向,也可以使用redirectAction],默认是转发,如果是返回JSON,则type=JSON。
			-->
			<result name="list">/WEB-INF/page/roleAction/list.jsp</result>
			<result name="toList" type="redirectAction">role_list</result>
			<result name="saveUI">/WEB-INF/page/roleAction/saveUI.jsp</result>
			<!-- <result name="addUI">/WEB-INF/page/roleAction/addUI.jsp</result>
			<result name="editUI">/WEB-INF/page/roleAction/editUI.jsp</result> -->
		</action>
		
		<!-- 部门信息 -->
		<action name="dept_*" class="departmentAction" method="{1}">
			<result name="list">/WEB-INF/page/deptAction/list.jsp</result>
			<result name="saveUI">/WEB-INF/page/deptAction/saveUI.jsp</result>
			<!-- 在add保存后跳转回当前页面,取得parentId值 -->
			<result name="toList" type="redirectAction">dept_list?parentId=${parentId}</result>
		</action>
		
		
	</package>
</struts>

list.jsp代码:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <title>部门列表</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script language="javascript" src="${pageContext.request.contextPath }/script/jquery.js"></script>
    <script language="javascript" src="${pageContext.request.contextPath }/script/pageCommon.js" charset="utf-8"></script>
    <script language="javascript" src="${pageContext.request.contextPath }/script/PageUtils.js" charset="utf-8"></script>
    <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath }/style/blue/pageCommon.css" />
    <script type="text/javascript">
    </script>
</head>
<body>
 
<div id="Title_bar">
    <div id="Title_bar_Head">
        <div id="Title_Head"></div>
        <div id="Title"><!--页面标题-->
            <img border="0" width="13" height="13" src="${pageContext.request.contextPath }/style/images/title_arrow.gif"/> 部门管理
        </div>
        <div id="Title_End"></div>
    </div>
</div>

<div id="MainArea">
	    <table cellspacing="0" cellpadding="0" class="TableStyle">
	       
	        <!-- 表头-->
	        <thead>
	            <tr align=center valign=middle id=TableTitle>
	            	<td width="150px">部门名称</td>
					<td width="150px">上级部门名称</td>
					<td width="200px">职能说明</td>
					<td>相关操作</td>
	            </tr>
	        </thead>
	
			<!--显示数据列表-->
	        <tbody id="TableData" class="dataContainer" datakey="departmentList">
		        <s:iterator value="#deptList" var="dept">
					<tr class="TableDetail1 template">
						<!-- 通过s:property标签中的value可以取到值,通过s:a中的value却无法取到值 -->
						<%-- <td><s:property value="%{#dept.name}"/></td> --%> 
						<%-- <td><s:a action="dept_list?parentId=%{id}">${name }</s:a> </td> --%>
						<!-- 通过这个嵌入s:property中就可以显示值 -->
						<td>
							<s:a action="dept_list?parentId=%{id}">
								<s:property value="%{name}"/>
							</s:a> 
						</td>
						<td><s:property value="%{#parent.name}"/> </td><!-- 需要获取关联对象的属性值,需要开启懒加载 -->
						<%-- <td>${parent.name } </td> --%>
						<td>${description} </td>
						<td><s:a action="dept_delete?id=%{id}&parentId=%{parentId}" onClick="return window.confirm('这将删除所有的下级部门,您确定要删除吗?')">删除</s:a>
							<s:a action="dept_editUI?id=%{id}">修改</s:a>
						</td>
					</tr>
				</s:iterator>
	        </tbody>
	    </table>
    
    <!-- 其他功能超链接 -->
    <div id="TableTail">
        <div id="TableTail_inside">
            <s:a action="dept_addUI?parentId=%{parentId}"><img src="${pageContext.request.contextPath }/style/images/createNew.png" /></s:a>
            <!-- 【返回到上一级】部门操作:当前的子级列表是在父级部门列表下,要显示父级部门列表要找到父级的父级的部门ID, 储存值栈MAP中的值通过#parent.parent.id找到 -->
            <s:if test="%{parentId != null}">
            <%-- <s:if test="%{#parent != null}"> --%>
            	<s:a action="dept_list?parentId=%{#parent.parent.id}"><img src="${pageContext.request.contextPath }/style/blue/images/button/ReturnToPrevLevel.png" /></s:a>
            </s:if>
        </div>
    </div>
</div>

<!--说明-->	
<div id="Description"> 
	说明:<br />
	1,列表页面只显示一层的(同级的)部门数据,默认显示最顶级的部门列表。<br />
	2,点击部门名称,可以查看此部门相应的下级部门列表。<br />
	3,删除部门时,同时删除此部门的所有下级部门。
</div>

</body>
</html>

saveUI.jsp代码:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<title>部门设置</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script language="javascript" src="${pageContext.request.contextPath }/script/jquery.js"></script>
    <script language="javascript" src="${pageContext.request.contextPath }/script/pageCommon.js" charset="utf-8"></script>
    <script language="javascript" src="${pageContext.request.contextPath }/script/PageUtils.js" charset="utf-8"></script>
    <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath }/style/blue/pageCommon.css" />
</head>
<body>

<!-- 标题显示 --> 
<div id="Title_bar">
    <div id="Title_bar_Head">
        <div id="Title_Head"></div>
        <div id="Title"><!--页面标题-->
            <img border="0" width="13" height="13" src="${pageContext.request.contextPath }/style/images/title_arrow.gif"/> 部门信息
        </div>
        <div id="Title_End"></div>
    </div>
</div>

<!--显示表单内容-->
<div id=MainArea>
    <s:form action="dept_%{id == null ? 'add' : 'edit'}">
    	<s:hidden name="id"></s:hidden>
        <div class="ItemBlock_Title1"><!-- 信息说明<DIV CLASS="ItemBlock_Title1">
        	<IMG BORDER="0" WIDTH="4" HEIGHT="7" SRC="${pageContext.request.contextPath }/style/blue/images/item_point.gif" /> 部门信息 </DIV>  -->
        </div>
        
        <!-- 表单内容显示 -->
        <div class="ItemBlockBorder">
            <div class="ItemBlock">
                <table cellpadding="0" cellspacing="0" class="mainForm">
                    <tr><td width="100">上级部门</td>
                        <td>
                        	<s:select name="parentId" cssClass="SelectStyle"
                        		list="#deptList" listKey="id" listValue="name" 
                        		headerKey="" headerValue="== 请选择部门 ==">
                        	</s:select>
                        	<%-- <select name="parentId" class="SelectStyle">
                                <option value="0" selected="selected">请选择部门</option>
                                <option value="7">┠总经理室</option>
                                <option value="1">┠市场部</option>
                                <option value="2"> ┠咨询部</option>
                                <option value="3"> ┠招生部</option>
                                <option value="4">┠教学部</option>
                                <option value="5">┠后勤部</option>
                            </select> --%>
                        </td>
                    </tr>
                    <tr><td>部门名称</td>
                        <td><s:textfield type="text" name="name" cssClass="InputStyle"/> *</td>
                    </tr>
                    <tr><td>职能说明</td>
                        <td><s:textarea name="description" cssClass="TextareaStyle"></s:textarea></td>
                    </tr>
                </table>
            </div>
        </div>
        
        <!-- 表单操作 -->
        <div id="InputDetailBar">
            <input type="image" src="${pageContext.request.contextPath }/style/images/save.png"/>
            <a href="javascript:history.go(-1);"><img src="${pageContext.request.contextPath }/style/images/goBack.png"/></a>
        </div>
    </s:form>
</div>

<div class="Description">
	说明:<br />
	1,上级部门的列表是有层次结构的(树形)。<br/>
	2,如果是修改:上级部门列表中不能显示当前修改的部门及其子孙部门。因为不能选择自已或自已的子部门作为上级部门。<br />
</div>

</body>
</html>

异常引起原因 :
Caused by: No object in the CompoundRoot has a publicly accessible property named 'x' (no setter could be found). - [unknown location]


引起原因:

struts.xml配置中设置devMode=true时,会出现如上述异常。


当devMode=true时,配置为开发者模式。表单所有input标签中的name属性在action中都必须有对应的set/get方法,

无论是input为hidden设置的隐藏域 或者 通过URL传的参数值 。


解决方法:

1、配置<constant name="struts.devMode" value="false" />

2、为各个涉及到的参数设置set/get方法


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值