CRM第二篇

检索策略 : 相当于优化查询,主要是分为立即加载和延迟加载.
    当你查询一个对象的时候,要想立马使用这个对象,或者说是立即查询出来,就使用立即加载.
    当你查询这个对象时候不想立马查询出来,而是在使用这个对象的时候再查询出来它,那就用延迟加载.
    
    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属性,可以获得当前遍历的状态.例如 : 遍历的索引,是否为奇偶等.
原文地址:https://www.cnblogs.com/haizai/p/11611705.html