检索策略 : 相当于优化查询,主要是分为立即加载和延迟加载. 当你查询一个对象的时候,要想立马使用这个对象,或者说是立即查询出来,就使用立即加载. 当你查询这个对象时候不想立马查询出来,而是在使用这个对象的时候再查询出来它,那就用延迟加载. 1.1 字典表和客户表的关系映射: 当在CRM中,可以有客户源字典表,客户级别字典表,客户规模字典表.如果这些表独立出来,维护起来不是很方便,所以我可以把它建立成一张表, 用一列来区分是客户来源,还是客户级别,还是客户规范的字典数据. 表的SQL语句如下: /*创建数据字典表*/ /*创建客户表*/ CREATE TABLE `cst_customer` ( `cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)', `cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)', `cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源', `cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业', `cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别', `cust_address` varchar(128) DEFAULT NULL COMMENT '客户联系地址', `cust_phone` varchar(64) DEFAULT NULL COMMENT '客户联系电话', PRIMARY KEY (`cust_id`) ) ENGINE=InnoDB AUTO_INCREMENT=94 DEFAULT CHARSET=utf8; /*创建联系人表*/ CREATE TABLE `cst_linkman` ( `lkm_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '联系人编号(主键)', `lkm_name` varchar(16) DEFAULT NULL COMMENT '联系人姓名', `lkm_gender` char(1) DEFAULT NULL COMMENT '联系人性别', `lkm_phone` varchar(16) DEFAULT NULL COMMENT '联系人办公电话', `lkm_mobile` varchar(16) DEFAULT NULL COMMENT '联系人手机', `lkm_email` varchar(64) DEFAULT NULL COMMENT '联系人邮箱', `lkm_position` varchar(16) DEFAULT NULL COMMENT '联系人职位', `lkm_memo` varchar(512) DEFAULT NULL COMMENT '联系人备注', `lkm_cust_id` bigint(32) NOT NULL COMMENT '客户id(外键)', PRIMARY KEY (`lkm_id`), KEY `FK_cst_linkman_lkm_cust_id` (`lkm_cust_id`), CONSTRAINT `FK_cst_linkman_lkm_cust_id` FOREIGN KEY (`lkm_cust_id`) REFERENCES `cst_customer` (`cust_id`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; /*创建数据字典表*/ CREATE TABLE `base_dict` ( `dict_id` varchar(32) NOT NULL COMMENT '数据字典id(主键)', `dict_type_code` varchar(10) NOT NULL COMMENT '数据字典类别代码', `dict_type_name` varchar(64) NOT NULL COMMENT '数据字典类别名称', `dict_item_name` varchar(64) NOT NULL COMMENT '数据字典项目名称', `dict_item_code` varchar(10) DEFAULT NULL COMMENT '数据字典项目(可为空)', `dict_sort` int(10) DEFAULT NULL COMMENT '排序字段', `dict_enable` char(1) NOT NULL COMMENT '1:使用 0:停用', `dict_memo` varchar(64) DEFAULT NULL COMMENT '备注', PRIMARY KEY (`dict_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*为字典表插入数据:Data for the table `base_dict` */ LOCK TABLES `base_dict` WRITE; insert into `base_dict`(`dict_id`,`dict_type_code`,`dict_type_name`,`dict_item_name`,`dict_item_code`,`dict_sort`,`dict_enable`,`dict_memo`) values ('1','001','客户行业','教育培训 ',NULL,1,'1',NULL), ('10','003','公司性质','民企',NULL,3,'1',NULL), ('12','004','年营业额','1-10万',NULL,1,'1',NULL), ('13','004','年营业额','10-20万',NULL,2,'1',NULL), ('14','004','年营业额','20-50万',NULL,3,'1',NULL), ('15','004','年营业额','50-100万',NULL,4,'1',NULL), ('16','004','年营业额','100-500万',NULL,5,'1',NULL), ('17','004','年营业额','500-1000万',NULL,6,'1',NULL), ('18','005','客户状态','基础客户',NULL,1,'1',NULL), ('19','005','客户状态','潜在客户',NULL,2,'1',NULL), ('2','001','客户行业','电子商务',NULL,2,'1',NULL), ('20','005','客户状态','成功客户',NULL,3,'1',NULL), ('21','005','客户状态','无效客户',NULL,4,'1',NULL), ('22','006','客户级别','普通客户',NULL,1,'1',NULL), ('23','006','客户级别','VIP客户',NULL,2,'1',NULL), ('24','007','商机状态','意向客户',NULL,1,'1',NULL), ('25','007','商机状态','初步沟通',NULL,2,'1',NULL), ('26','007','商机状态','深度沟通',NULL,3,'1',NULL), ('27','007','商机状态','签订合同',NULL,4,'1',NULL), ('3','001','客户行业','对外贸易',NULL,3,'1',NULL), ('30','008','商机类型','新业务',NULL,1,'1',NULL), ('31','008','商机类型','现有业务',NULL,2,'1',NULL), ('32','009','商机来源','电话营销',NULL,1,'1',NULL), ('33','009','商机来源','网络营销',NULL,2,'1',NULL), ('34','009','商机来源','推广活动',NULL,3,'1',NULL), ('4','001','客户行业','酒店旅游',NULL,4,'1',NULL), ('5','001','客户行业','房地产',NULL,5,'1',NULL), ('6','002','客户信息来源','电话营销',NULL,1,'1',NULL), ('7','002','客户信息来源','网络营销',NULL,2,'1',NULL), ('8','003','公司性质','合资',NULL,1,'1',NULL), ('9','003','公司性质','国企',NULL,2,'1',NULL); UNLOCK TABLES; 1.2 字典表和客户表的关系分析: 通过上图我们可以的知 : 一个客户只能有一个来源(级别).多个客户可能有同一个来源(级别). 所以客户表和字典表的之间的关系是多对一.在数据库中都是依靠外键约束来实现的. 1.3 字典表和客户表的实现类映射配置 /* 客户的实体类 明确使用的注解都是JPA规范的. 所以导包都要导入javax.persistence包下的. /* @Entity //表示当前类是一个实体类 @Table(name="cst_customer") //建立当前实体类和表之间的对应关系 public class Customer implements Serializable { @Id //表名当前有属性是主键 @GeneratedValue(strategy=GenerationType.IDENTITY) //指定主键的生成策略 @Column(name="cust_id") //指定和数据库表中的cust_id列对应 private Long custId; @Column(name="cust_name")//指定和数据库表中的cust_name列对应 private String custName; @Column(name="cust_industry")//指定和数据库表中的cust_industry列对应 private String custIndustry; @Column(name="cust_address")//指定和数据库表中的cust_address列对应 private String custAddress; @Column(name="cust_phone")//指定和数据库表中的cust_phone列对应 private String custPhone; @ManyToOne(targetEntity=BaseDict.class) @JoinColumn(name="cust_source",referencedColumnName="dict_id") private BaseDict custSource; @ManyToOne(targetEntity=BaseDict.class) @JoinColumn(name="cust_level",referencedColumnName="dict_id") private BaseDict custLevel; <!-- Struts2框架提供的下拉选择框的标签,做修改的时候,可以帮你自动选中 <s:select> list 要遍历集合,编写的OGNL的表达式 name 提供表单有关,强调. headerKey 请选择选项值 headerValue 请选择选项文字, -请选择- listKey 生成option下拉选择框的值 listValue 生成option下拉选择框的文字 --> <s:select list="#sourceList" name="source.dictId" headerKey="" headerValue="-请选择-" listKey="dictId" listValue="dictItemName"></s:select> /** * 字典表的数据模型 * */ @Entity @Table(name="base_dict") public class BaseDict implements Serializable { @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="dict_id") private String dictId; @Column(name="dict_type_code") private String dictTypeCode; @Column(name="dict_type_name") private String dictTypeName; @Column(name="dict_item_name") private String dictItemName; @Column(name="dict_item_code") private String dictItemCode; @Column(name="dict_sort") private Integer dictSort; @Column(name="dict_enable") private String dictEnable; @Column(name="dict_memo") private String dictMemo; public String getDictId() { return dictId; } public void setDictId(String dictId) { this.dictId = dictId; } public String getDictTypeCode() { return dictTypeCode; } public void setDictTypeCode(String dictTypeCode) { this.dictTypeCode = dictTypeCode; } public String getDictTypeName() { return dictTypeName; } public void setDictTypeName(String dictTypeName) { this.dictTypeName = dictTypeName; } public String getDictItemName() { return dictItemName; } public void setDictItemName(String dictItemName) { this.dictItemName = dictItemName; } public String getDictItemCode() { return dictItemCode; } public void setDictItemCode(String dictItemCode) { this.dictItemCode = dictItemCode; } public Integer getDictSort() { return dictSort; } public void setDictSort(Integer dictSort) { this.dictSort = dictSort; } public String getDictEnable() { return dictEnable; } public void setDictEnable(String dictEnable) { this.dictEnable = dictEnable; } public String getDictMemo() { return dictMemo; } public void setDictMemo(String dictMemo) { this.dictMemo = dictMemo; } @Override public String toString() { return "BaseDict [dictId=" + dictId + ", dictTypeCode=" + dictTypeCode + ", dictTypeName=" + dictTypeName + ", dictItemName=" + dictItemName + ", dictItemCode=" + dictItemCode + ", dictSort=" + dictSort + ", dictEnable=" + dictEnable + ", dictMemo=" + dictMemo + "]"; } } 第2章客户的增删改查操作 2.1写在最前 本章节提供的是客户增删改查的代码实现。 下面出现的Action指的的是:CustomerAction 出现的Service指的是:ICustomerService和CustomerServiceImpl 出现的Dao指的是:CustomerDao和CustomerDaoImpl。 这些类都需要交给spring来管理。 在没有提供新的类(或接口)时,从2.2章节开始的Action,Service和Dao的代码都是出现在以下的类中。 Action /** * 客户的动作类 * * */ @Controller("customerAction") @Scope("prototype") @ParentPackage("struts-default") @Namespace("/customer") public class CustomerAction extends ActionSupport implements ModelDriven<Customer> { private Customer customer = new Customer(); @Autowired private ICustomerService customerService ; @Override public Customer getModel() { return customer; } } Service /** * 客户的业务层接口 * */ public interface ICustomerService { } /** * 客户的业务层实现类 * */ @Service("customerService") @Transactional(propagation=Propagation.SUPPORTS,readOnly=true) public class CustomerServiceImpl implements ICustomerService { @Autowired private ICustomerDao customerDao; } Dao /** * 客户的持久层接口 * */ public interface ICustomerDao { } /** * 客户的持久层实现类 * */ @Repository("customerDao") public class CustomerDaoImpl implements ICustomerDao { @Autowired private HibernateTemplate hibernateTemplate; } 2.2显示添加客户页面 2.2.1menu.jsp页面 <A href="${pageContext.request.contextPath}/customer/addUICustomer.action" class=style2 target=main> - 新增客户 </A> 2.2.2Action /** * 获取添加客户页面 * @return */ private List<BaseDict> custSources; private List<BaseDict> custLevels; @Action(value="addUICustomer",results={ @Result(name="addUICustomer",type="dispatcher",location="/jsp/customer/add.jsp") }) public String addUICustomer(){ //1.查询所有客户来源 custSources = customerService.findAllCustomerSource(); //2.查询所有客户级别 custLevels = customerService.findAllCustomerLevel(); return "addUICustomer"; } public List<BaseDict> getCustLevels() { return custLevels; } public void setCustLevels(List<BaseDict> custLevels) { this.custLevels = custLevels; } public List<BaseDict> getCustSources() { return custSources; } public void setCustSources(List<BaseDict> custSources) { this.custSources = custSources; } 2.2.3Service /** * 查询所有客户来源 * @return */ List<BaseDict> findAllCustomerSource(); /** * 查询所有客户级别 * @return */ List<BaseDict> findAllCustomerLevel(); @Override @Transactional(propagation=Propagation.SUPPORTS,readOnly=true) public List<BaseDict> findAllCustomerSource() { return baseDictDao.findBaseDictByTypeCode("002"); } @Override @Transactional(propagation=Propagation.SUPPORTS,readOnly=true) public List<BaseDict> findAllCustomerLevel() { return baseDictDao.findBaseDictByTypeCode("006"); } 2.2.4Dao /** * 数据字典实体的持久层接口 * * */ public interface IBaseDictDao { /** * 根据字典类型查询字典表数据 * @param typeCode 字典类型编码 * @return */ List<BaseDict> findBaseDictByTypeCode(String typeCode); } /** * 数据字典实体的持久层实现类 * */ @Repository("baseDictDao") public class BaseDictDaoImpl implements IBaseDictDao { @Autowired private HibernateTemplate hibernateTemplate; @Override public List<BaseDict> findBaseDictByTypeCode(String typeCode) { return (List<BaseDict>) hibernateTemplate.find("from BaseDict where dictTypeCode = ? ", typeCode); } } 1.使用了Struts2框架的select标签,默认含有样色的。不想使用样式,在strts.xml配置文件中添加常量 <constant name="struts.ui.theme" value="simple"/> 2.3保存客户 2.3.1add.jsp <s:form action="addCustomer" namespace="/customer"> <TABLE cellSpacing=0 cellPadding=5 border=0> <TR> <td>客户名称:</td> <td> <s:textfield name="custName" class="textbox" id="sChannel2" style="WIDTH: 180px" maxLength="50" /> </td> <td>所属行业 :</td> <td> <s:textfield name="custIndustry" class="textbox" id="sChannel2" style="WIDTH: 180px" maxLength="50" /> </td> </TR> <TR> td>信息来源 :</td> <td> <s:select list="custSources" name="custSource.dictId" listKey="dictId" listValue="dictItemName" headerKey="" headerValue="---请选择---" class="textbox" id="sChannel2" style="WIDTH: 180px"></s:select> </td> <td>客户级别:</td> <td> <s:select list="custLevels" name="custLevel.dictId" listKey="dictId" listValue="dictItemName" headerKey="" headerValue="---请选择---" class="textbox" id="sChannel2" style="WIDTH: 180px"></s:select> </td> </TR> <TR> <td>联系地址 :</td> <td> <s:textfield name="custAddress" class="textbox" id="sChannel2" style="WIDTH: 180px" maxLength="50" /> </td> <td>联系电话 :</td> <td> <s:textfield name="custPhone" class="textbox" id="sChannel2" style="WIDTH: 180px" maxLength="50" /> </td> </TR> <tr> <td rowspan=2> <s:submit value="保存"/> </td> </tr> </TABLE> </s:form> 2.3.2Action @Action(value="addCustomer",results={ @Result(name="addCustomer",type="redirect",location="/jsp/success.jsp") }) public String addCustomer(){ customerService.saveCustomer(customer); return "addCustomer"; } 2.3.3Service /** * 保存客户 * @param customer */ void saveCustomer(Customer customer); @Override public void saveCustomer(Customer customer) { customerDao.save(customer); } 2.3.4Dao /** * 保存客户 * @param customer */ void save(Customer customer); @Override public void save(Customer customer) { hibernateTemplate.save(customer); } 2.4客户列表展示 2.4.1menu.jsp <A href="${pageContext.request.contextPath}/customer/findAllCustomer.action" class=style2 target=main> - 客户列表 </A> 2.4.2Action /** * 查询所有客户 * @return */ private List<Customer> customers; @Action(value="findAllCustomer",results={ Result(name="findAllCustomer",location="/jsp/cusotmer/list.jsp") }) public String findAllCustomer(){ //1.查询所有客户 customers = customerService.findAllCustomer(); return "findAllCustomer"; } public List<Customer> getCustomers() { return customers; } public void setCustomers(List<Customer> customers) { this.customers = customers; } 2.4.3Service /** * 查询所有客户信息 * @return */ List<Customer> findAllCustomer(); @Override @Transactional(propagation=Propagation.SUPPORTS,readOnly=true) public List<Customer> findAllCustomer() { return customerDao.findAllCustomer(); } 2.4.4Dao /** *查询所有客户 * @return */ List<Customer> findAllCustomer(); @Override public List<Customer> findAllCustomer() { return (List<Customer>) hibernateTemplate.find("from Customer "); } 2.5客户删除 2.5.1list.jsp <s:a href="javascript:delOne('%{custId}')">删除</s:a> <SCRIPT language=javascript> function delOne(custId){ var sure = window.confirm("确定删除吗?"); if(sure){ window.location.href="${pageContext.request.contextPath}/customer/removeCustomer.action?custId="+custId; } } </SCRIPT> 2.5.2Action /** * 删除客户 * @return */ @Action(value="removeCustomer",results={ @Result(name="removeCustomer",type="redirect",location="/jsp/success.jsp") }) public String removeCustomer(){ customerService.removeCustomer(customer); return "removeCustomer"; } 2.5.3Service /** * 删除客户 * @param customer */ void removeCustomer(Customer customer); @Override public void removeCustomer(Customer customer) { customerDao.delete(customer); } 2.5.4Dao /** * 删除客户 * @param customer */ void delete(Customer customer); @Override public void delete(Customer customer) { hibernateTemplate.delete(customer); } 2.6显示客户修改页面 2.6.1list.jsp <s:a action="editUICustomer" namespace="/customer"> <s:param name="custId" value="%{custId}"></s:param> 修改 </s:a> 2.6.2Action /** * 获取编辑客户页面 * @return */ @Action(value="editUICustomer",results={ @Result(name="editUICustomer",type="dispatcher",location="/jsp/customer/edit.jsp") }) public String editUICustomer(){ //1.根据id查询要编辑的客户对象 Customer dbCustomer = customerService.findCustomerById(customer.getCustId()); //2.获取值栈对象 ValueStack vs = ActionContext.getContext().getValueStack(); //3.把查询出来的客户对象压入栈顶 vs.push(dbCustomer); //4.查询所有客户来源和客户级别 custSources = customerService.findAllCustomerSource(); custLevels = customerService.findAllCustomerLevel(); return "editUICustomer"; } 2.6.3Service /** * 根据id查询客户信息 * @param custId * @return */ Customer findCustomerById(Long custId); @Override @Transactional(propagation=Propagation.SUPPORTS,readOnly=true) public Customer findCustomerById(Long custId) { return customerDao.findById(custId); } 2.6.4Dao /** * 根据id查询客户 * @param customer */ void findById(Long custId); @Override public void findById (Long custId) { hibernateTemplate.get(Customer.class,custId); } 2.7客户修改 2.7.1edit.jsp <s:form action="editCustomer" namespace="/customer"> <s:hidden name="custId" value="%{custId}"></s:hidden> <TABLE cellSpacing=0 cellPadding=5 border=0> <TR> <td>客户名称:</td> <td> <s:textfield name="custName" class="textbox" id="sChannel2" style="WIDTH: 180px" maxLength="50" /> </td> <td>所属行业 :</td> <td> <s:textfield name="custIndustry" class="textbox" id="sChannel2" style="WIDTH: 180px" maxLength="50" /> </td> </TR> <TR> td>信息来源 :</td> <td> <s:select list="custSources" name="custSource.dictId" listKey="dictId" listValue="dictItemName" headerKey="" headerValue="---请选择---" class="textbox" id="sChannel2" style="WIDTH: 180px"></s:select> </td> <td>客户级别:</td> <td> <s:select list="custLevels" name="custLevel.dictId" listKey="dictId" listValue="dictItemName" headerKey="" headerValue="---请选择---" class="textbox" id="sChannel2" style="WIDTH: 180px"></s:select> </td> </TR> <TR> <td>联系地址 :</td> <td> <s:textfield name="custAddress" class="textbox" id="sChannel2" style="WIDTH: 180px" maxLength="50" /> </td> <td>联系电话 :</td> <td> <s:textfield name="custPhone" class="textbox" id="sChannel2" style="WIDTH: 180px" maxLength="50" /> </td> </TR> <tr> <td rowspan=2> <s:submit value="保存"/> </td> </tr> </TABLE> </s:form> 2.7.2Action /** * 编辑客户 * @return */ @Action(value="editCustomer",results={ @Result(name="editCustomer",type="redirect",location="/jsp/success.jsp") }) public String editCustomer(){ customerService.updateCustomer(customer); return "editCustomer"; } 2.7.3Service /** * 编辑客户 * @param customer */ void updateCustomer(Customer customer); @Override public void updateCustomer(Customer customer) { customerDao.update(customer); } 2.7.4Dao /** * 更新客户 * @param customer */ void update(Customer customer); @Override public void delete(Customer customer) { hibernateTemplate.update(customer); } 2.8客户的列表条件查询 2.8.1list.jsp <s:form action="findAllCustomer" namespace="/customer"> <TR> <td>客户名称:</td> <td> <s:textfield name="custName" class="textbox" id="sChannel2" style="WIDTH: 80px" maxLength="50" /> </td> <td>所属行业 :</td> <td> <s:textfield name="custIndustry" class="textbox" id="sChannel2" style="WIDTH: 80px" maxLength="50" /> </td> <td>信息来源 :</td> <td> <s:select list="custSources" name="custSourceId" listKey="dictId" listValue="dictItemName" headerKey="" headerValue="---请选择---" class="textbox" id="sChannel2" style="WIDTH: 80px"></s:select> </td> <td>客户级别:</td> <td> <s:select list="custLevels" name="custLevelId" listKey="dictId" listValue="dictItemName" headerKey="" headerValue="---请选择---" class="textbox" id="sChannel2" style="WIDTH: 80px"></s:select> </td> <TD> <s:submit value=" 筛选 "></s:submit> </TD> </TR> </s:form> 2.8.2Action /** * 查询所有客户 * @return */ @Action(value="findAllCustomer",results={ @Result(name="findAllCustomer",type="dispatcher",location="/jsp/customer/list.jsp") }) public String findAllCustomer(){ //1.创建离线查询对象 DetachedCriteria dCriteria = DetachedCriteria.forClass(Customer.class);//就相当于查询所有 from Customer; //2.拼装查询条件 //判断是否提供了客户名称 if(StringUtils.isNotBlank(customer.getCustName())){ //添加条件:模糊查询客户名称 dCriteria.add(Restrictions.like("custName","%"+customer.getCustName()+"%")); } //判断是否提供了客户行业 if(StringUtils.isNotBlank(customer.getCustIndustry())){ //添加条件:模糊查询客户行业 dCriteria.add(Restrictions.like("custIndustry","%"+customer.getCustIndustry()+"%")); } //判断是否提供了客户来源 if(StringUtils.isNotBlank(custSourceId)){ //添加条件:精确查询客户来源 dCriteria.add(Restrictions.eq("custSource.dictId", custSourceId)); } //判断是否提供了客户来源 if(StringUtils.isNotBlank(custLevelId)){ //添加条件:精确查询客户来源 dCriteria.add(Restrictions.eq("custLevel.dictId", custLevelId)); } //3.查询所有客户 customers = customerService.findAllCustomer(dCriteria); //4.查询所有客户来源和所有客户级别 custSources = customerService.findAllCustomerSource(); custLevels = customerService.findAllCustomerLevel(); return "findAllCustomer"; } 2.8.3Service /** * 查询所有客户,带条件 * @param dCriteria 查询条件 * @return */ List<Customer> findAllCustomer(DetachedCriteria dCriteria); @Override @Transactional(propagation=Propagation.SUPPORTS,readOnly=true) public Page findAllCustomer(DetachedCriteria dCriteria) { return customerDao.findAllCustomer(dCriteria); } 2.8.4Dao /** * 查询所有客户 * @param dCriteria 查询条件 * @return */ List<Customer> findAllCustomer(DetachedCriteria dCriteria); Jsp页面: <%-- 页面自带的 <select name="custSource" class=textbox id=sChannel2 style="WIDTH: 180px"> <option value="non">---请选择---</option> <option value="6">电话营销</option> <option value="7">网络营销</option> </select> --%> <%-- 默认选中比较麻烦 <select name="custSource" class=textbox id=sChannel2 style="WIDTH: 180px"> <c:forEach var="dict" items="${ sourceList }"> <option value="${ dict.dictId }">${ dict.dictItemName }</option> </c:forEach> </select> --%> <%-- Struts2框架提供的下拉选择框的标签,做修改的时候,可以帮你自动选中 <s:select> list 要遍历集合,编写的OGNL的表达式 name 提供表单有关,强调。 headerKey 请选择选项值 headerValue 请选择选项文字 -请选择- listKey 生成option下啦选择框的值 listValue 生成option下啦选择框的文字 --%> <s:select list="#sourceList" name="source.dictId" headerKey="" headerValue="-请选择-" listKey="dictId" listValue="dictItemName"/> <%-- <select name="custSource" class=textbox id=sChannel2 style="WIDTH: 180px"> <c:forEach items="${ sourc3eList }" var="dict"> <c:choose> <c:when test="${ dict.dictId == source.dictId }"> <option value="${ dict.dictId }" selected>${ dict.dictItemName }</option> </c:when> <c:otherwise> <option value="${ dict.dictId }">${ dict.dictItemName }</option> </c:otherwise> </c:choose> </c:forEach> </select> --%> <%-- 下拉选择框,Struts2标签可以使用name属性获取值栈中的值。 name="source.dictId" 获取的model对象的source属性,source对象的dictId属性 <s:textfield name="custName" /> --%> <s:select list="#sourceList" name="source.dictId" listKey="dictId" listValue="dictItemName"/> Action package com.baidu.customer.action; import java.util.List; import javax.annotation.Resource; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Restrictions; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller; import com.baidu.base.action.BaseAction; import com.baidu.customer.domain.Customer; import com.baidu.customer.service.CustomerService; import com.baidu.dict.domain.Dict; import com.baidu.dict.service.DictService; import com.opensymphony.xwork2.ModelDriven; /** * 客户模块 * @author Administrator */ @Controller("customerAction") @Scope("prototype") public class CustomerAction extends BaseAction implements ModelDriven<Customer>{ private static final long serialVersionUID = 4683080283444298532L; private Customer model = new Customer(); // ${model.custName} model调用getModel()方法 public Customer getModel() { return model; } @Resource(name="customerService") private CustomerService customerService; @Resource(name="dictService") private DictService dictService; /** * 跳转到新增页面 * @return * @throws Exception */ public String initSave() throws Exception { // 查询来源 SELECT * FROM base_dict WHERE dict_type_code = '002' List<Dict> sourceList = dictService.findByWhere("002"); // 查询级别 List<Dict> levelList = dictService.findByWhere("006"); // 查询行业 List<Dict> industryList = dictService.findByWhere("001"); /* // 压栈 ActionContext context = ActionContext.getContext(); // put方法 context.put("sourceList", sourceList); context.put("levelList", levelList); context.put("industryList", industryList); */ // 调用父类的方法 super.put("sourceList", sourceList); super.put("levelList", levelList); super.put("industryList", industryList); // ValueStack vs = context.getValueStack(); // vs.push(xxx); return "initSave"; } /** * 保存客户 * @return * @throws Exception */ public String save() throws Exception { customerService.save(model); return SUCCESS; } /** * 查询所有的客户 * @return * @throws Exception public String list() throws Exception { // 使用service查询 List<Customer> list = customerService.findAll(); // 压栈 // ActionContext.getContext().put("list", list); super.put("list", list); return "list"; } */ /** * 添加查询条件 * @return * @throws Exception */ public String list() throws Exception { /* // 使用service查询 List<Customer> list = customerService.findAll(); // 压栈 // ActionContext.getContext().put("list", list); super.put("list", list); */ // 推荐,带条件的查询,使用离线查询方式 // 创建离线条件的对象 DetachedCriteria criteria = DetachedCriteria.forClass(Customer.class); // model已经封装了custName属性 String custName = model.getCustName(); // 判断 if(custName != null && !custName.trim().isEmpty()){ // 说明,填入了值,拼接查询条件 criteria.add(Restrictions.like("custName", "%"+custName+"%")); } // 调用业务层 List<Customer> list = customerService.findAll(criteria); super.put("list", list); return "list"; } /** * 跳转到修改的页面 * @return * @throws Exception */ public String initUpdate() throws Exception { // 接收id值 ,model已经封装 model = customerService.findById(model.getCustId()); // 压栈 super.push(model); // 查询来源 行业 级别 List<Dict> sourceList = dictService.findByWhere("002"); // 查询级别 List<Dict> levelList = dictService.findByWhere("006"); // 查询行业 List<Dict> industryList = dictService.findByWhere("001"); // 调用父类的方法 super.put("sourceList", sourceList); super.put("levelList", levelList); super.put("industryList", industryList); return "initUpdate"; } /** * 修改客户 * @return * @throws Exception */ public String update() throws Exception { // 先通过id查询,从数据库中查询的,数据没有改变的数据 Customer customer = customerService.findById(model.getCustId()); // model封装了主键 名称 所有的属性,只会封装7个属性,model封装的是页面提交的数据,修改后的数据 // 把model的数据设置到customer对象中 customer.setCustName(model.getCustName()); customer.setIndustry(model.getIndustry()); customer.setSource(model.getSource()); customer.setLevel(model.getLevel()); customer.setCustAddress(model.getCustAddress()); customer.setCustPhone(model.getCustPhone()); // 更新 customerService.update(customer); return SUCCESS; } /** * 删除 * @return * @throws Exception */ public String delete() throws Exception { // model封装了dictId属性 Customer customer = customerService.findById(model.getCustId()); // 删除功能的时候,为了级联删除做准备工作,先查询,再删除 customerService.delete(customer); return SUCCESS; } } 持久层 : package com.baidu.customer.dao.impl; import java.util.List; import javax.annotation.Resource; import org.hibernate.criterion.DetachedCriteria; import org.springframework.orm.hibernate5.HibernateTemplate; import org.springframework.stereotype.Repository; import com.baidu.customer.dao.CustomerDao; import com.baidu.customer.domain.Customer; /** * 持久层 * @author Administrator */ @Repository("customerDao") public class CustomerDaoImpl implements CustomerDao { @Resource(name="hibernateTemplate") private HibernateTemplate hibernateTemplate; /** * 保存 */ public void save(Customer customer) { hibernateTemplate.save(customer); } /** * 查询所有 */ public List<Customer> findAll() { return (List<Customer>) hibernateTemplate.find("from Customer"); } /** * 通过主键查询一个对象 */ public Customer findById(Long custId) { // session.get() return hibernateTemplate.get(Customer.class, custId); } public void update(Customer customer) { hibernateTemplate.update(customer); } public void delete(Customer customer) { hibernateTemplate.delete(customer); } /** * 离线条件查询 */ public List<Customer> findAll(DetachedCriteria criteria) { return (List<Customer>) hibernateTemplate.findByCriteria(criteria); } } 离线查询的好处:在任意位置不需要session可以创建对象. 字典表代码 : package com.baidu.dict.domain; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; /** * 客户字典表 * @author Administrator */ @Entity @Table(name="base_dict") public class Dict { /** * 主键的类型是String,不能使用自动递增。学习过hibernate框架,提供主键生成策略。 * * native 整形 * * uuid 字符串 * * 在JPA中使用hibernate框架的策略,uuid的策略 * @GenericGenerator(name="sysUUID",strategy="uuid") @GeneratedValue(generator="sysUUID") // 引入其他的策略 */ @Id // @GeneratedValue(strategy=GenerationType.AUTO) 使用JPA的策略 // 自定义sysUUID的策略,使用的hibernate框架的uuid策略 @GenericGenerator(name="sysUUID",strategy="uuid") @GeneratedValue(generator="sysUUID") // 引入其他的策略 @Column(name="dict_id") private String dictId; @Column(name="dict_type_code") private String dictTypeCode; @Column(name="dict_type_name") private String dictTypeName; @Column(name="dict_item_name") private String dictItemName; @Column(name="dict_item_code") private String dictItemCode; @Column(name="dict_sort") private Integer dictSort; @Column(name="dict_enable") private String dictEnable; @Column(name="dict_memo") private String dictMemo; public String getDictId() { return dictId; } public void setDictId(String dictId) { this.dictId = dictId; } public String getDictTypeCode() { return dictTypeCode; } public void setDictTypeCode(String dictTypeCode) { this.dictTypeCode = dictTypeCode; } public String getDictTypeName() { return dictTypeName; } public void setDictTypeName(String dictTypeName) { this.dictTypeName = dictTypeName; } public String getDictItemName() { return dictItemName; } public void setDictItemName(String dictItemName) { this.dictItemName = dictItemName; } public String getDictItemCode() { return dictItemCode; } public void setDictItemCode(String dictItemCode) { this.dictItemCode = dictItemCode; } public Integer getDictSort() { return dictSort; } public void setDictSort(Integer dictSort) { this.dictSort = dictSort; } public String getDictEnable() { return dictEnable; } public void setDictEnable(String dictEnable) { this.dictEnable = dictEnable; } public String getDictMemo() { return dictMemo; } public void setDictMemo(String dictMemo) { this.dictMemo = dictMemo; } } package com.baidu.dict.service.impl; import java.util.List; import javax.annotation.Resource; import org.springframework.stereotype.Service; import com.baidu.dict.dao.DictDao; import com.baidu.dict.domain.Dict; import com.baidu.dict.service.DictService; @Service("dictService") public class DictServiceImpl implements DictService { @Resource(name="dictDao") private DictDao dictDao; /** * 按条件查询 */ public List<Dict> findByWhere(String string) { return dictDao.findByWhere(string); } } 2package com.baidu.dict.dao.impl; import java.util.List; import javax.annotation.Resource; import org.springframework.orm.hibernate5.HibernateTemplate; import org.springframework.stereotype.Repository; import com.baidu.dict.dao.DictDao; import com.baidu.dict.domain.Dict; @Repository("dictDao") public class DictDaoImpl implements DictDao { @Resource(name="hibernateTemplate") private HibernateTemplate hibernateTemplate; /** * 条件查询 */ public List<Dict> findByWhere(String string) { // 使用HQL的查询 return (List<Dict>) hibernateTemplate.find("from Dict where dictTypeCode = ?", string); } } 配置文件: <?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" 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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 开启注解的扫描 --> <context:component-scan base-package="com.baidu"/> <!-- 配置C3P0的连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql:///crm"/> <property name="user" value="root"/> <property name="password" value="root"/> </bean> <!-- Spring整合hibernate框架 --> <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <!-- 注入连接池 --> <property name="dataSource" ref="dataSource"/> <!-- 注入属性 --> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">none</prop> <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate5.SpringSessionContext</prop> </props> </property> <!-- 注入扫描entity注解 --> <property name="packagesToScan"> <array> <value>com.baidu.*.domain</value> </array> </property> </bean> <!-- 先配置模板 --> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <!-- 配置事务 --> <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <!-- 配置事务通知 --> <tx:advice id="myAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED"/> <tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED"/> <tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED"/> <tx:method name="find*" read-only="true"/> <tx:method name="*" isolation="DEFAULT" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 配置AOP增强 --> <aop:config> <aop:advisor advice-ref="myAdvice" pointcut="execution(* com.baidu.*.service.impl.*ServiceImpl.*(..))"/> </aop:config> </beans> <?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> <!-- 使用Struts2框架标签的时候,使用简单的样式 --> <constant name="struts.ui.theme" value="simple"/> <package name="crm" extends="struts-default" namespace="/"> <!-- 配置客户模块 --> <action name="customerAction_*" class="customerAction" method="{1}"> <result name="initSave">/jsp/customer/add.jsp</result> <result name="list">/jsp/customer/list.jsp</result> <result name="initUpdate">/jsp/customer/edit.jsp</result> <result name="success" type="redirect">customerAction_list</result> </action> </package> </struts> 离线查询的好处:在任意位置不需要session可以创建对象 在Struts2框架中,先后在struts.xml中,struts.properties中和web.xml中来修改struts的同一个常量.在web.xml配置文件中的修改会最终生效.web.xml是倒数第二个执行的. 通过构造函数依赖注入,使用,其中index="1" 表示 : 按照参数的顺序,其中1表示第二个参数. 有关一级缓存和快照描述 : A: 快照区保存了与一级缓存相对应的数据,但是并不是真正的对象. B: 刷新一级缓存时,执行SQL语句的判定标准为数据区与快照区的数据是否相同. D: 执行查询时,查询数据封装为对象保存在一级缓存区,同时将查询数据快照信息保存到快照区. 值栈root对象栈数据描述: A: valueStack.push(obj)将指定的对象压入到值栈. B: 在jsp页面,可以使用defs:property/> 获得栈顶的数据 D: 在jsp页面,可以使用defs:property value="name"/> 获得对象栈中name属性的值 struts访问servlet的api: A: 可以通过ActionContext解耦合的方式,间接的操作servlet的三个作用域. B: ServletActionContext提供了访问servlet常用对象的方法.例如 : getServletContext()等. C: struts提供若干接口直接给action注入相应的对象.例如 : ServletContextAware可以给当前action注入ServletContext对象. D: ServletActionContext.getRequest()可以获得HttpServletRequest对象. 以下描述是正确的: A: value属性的值对应值栈中的相关的数据. C: 如果使用var属性,在值栈的context中存放一个键值对. D: 如果使用status属性,可以获得当前遍历的状态.例如 : 遍历的索引,是否为奇偶等.