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