总结
面试建议是,一定要自信,敢于表达,面试的时候我们对知识的掌握有时候很难面面俱到,把自己的思路说出来,而不是直接告诉面试官自己不懂,这也是可以加分的。
以上就是蚂蚁技术四面和HR面试题目,以下最新总结的最全,范围包含最全MySQL、Spring、Redis、JVM等最全面试题和答案,仅用于参考
<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<!--jsp相关-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--整合日志-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.10</version>
</dependency>
<!--common工具-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
</dependencies>
```
- 创建webapp目录
2.2 导入jsp页面
2.3 配置类
- 拷贝配置类
2.3.1 MyBatis 配置
- 拷贝:MyBatisConfiguration3,修改mapper所在包,并创建对应的包
package com.czxy.crm.config;
import com.github.pagehelper.PageHelper;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import tk.mybatis.spring.mapper.MapperScannerConfigurer;
import javax.sql.DataSource;
import java.util.Properties;
/\*\*
\* @author 桐叔
\* @email liangtong@itcast.cn
\*/
public class MyBatisConfiguration3 {
/\*\*
\* 配置session工厂
\* @param dataSource
\* @return
\* @throws Exception
\*/
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception{
//1 创建 factoryBean
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
//2 设置数据
// 2.1 数据源
factoryBean.setDataSource(dataSource);
// 2.2 驼峰命名
Configuration configuration = new Configuration();
configuration.setMapUnderscoreToCamelCase(true);
factoryBean.setConfiguration(configuration);
// 2.3 分页插件
Properties props = new Properties();
// 设置方言
props.setProperty("dialect", "mysql");
// 分页的同时进行count查询
props.setProperty("rowBoundsWithCount", "true");
// 分页合理化参数,pageNum<=0 时会查询第一页,pageNum>pages (超过总数时),会查询最后一页
props.setProperty("reasonable", "true");
// PageInterceptor pageInterceptor = new PageInterceptor();
// pageInterceptor.setProperties(props);
PageHelper pageHelper = new PageHelper();
pageHelper.setProperties(props);
factoryBean.setPlugins(new Interceptor\[\] {pageHelper});
//3 通过factorybean获得对应
return factoryBean.getObject();
}
/\*\*
\* 映射扫描器
\* @return
\*/
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
//1 创建
MapperScannerConfigurer mapperScanner = new MapperScannerConfigurer();
//2设置包
mapperScanner.setBasePackage("com.czxy.crm.mapper");
return mapperScanner;
}
}
2.3.2 Spring 配置
-
拷贝:SpringConfiguration3
-
修改service所在包,并创建对应的包
-
创建 db.properties
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/ssm\_crm jdbc.username=root jdbc.password=1234
-
package com.czxy.crm.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@ComponentScan(basePackages="com.czxy.crm.service")
@PropertySource("classpath:db.properties")
@EnableTransactionManagement
public class SpringConfiguration3 {
/\*\*
\* 获得properties文件中内容,并注入对应变量
\*/
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
/\*\*
\* 配置数据源
\* @return
\*/
@Bean
public DataSource dataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driver);
druidDataSource.setUrl(url);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
return druidDataSource;
}
/\*\*
\* 事务管理器
\* @param dataSource
\* @return
\*/
@Bean
public DataSourceTransactionManager txManager(DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
}
2.3.3 Spring MVC 配置
-
拷贝:MvcConfiguration3
-
修改controller所在包,并创建对应的包
-
修改视图解析器的前后缀
-
package com.czxy.crm.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@ComponentScan(basePackages="com.czxy.crm.controller")
@EnableWebMvc
public class MvcConfiguration3 implements WebMvcConfigurer {
/\*\*
\* 视图解析器
\* @return
\*/
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/jsp/",".jsp");
}
}
2.3.4 Web 配置
- 拷贝:WebInitializer3
package com.czxy.crm.config;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
public class WebInitializer3 implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
//1 配置spring工厂
AnnotationConfigWebApplicationContext application = new AnnotationConfigWebApplicationContext();
// 注册所有的配置类
application.register(MyBatisConfiguration3.class);
application.register(SpringConfiguration3.class);
application.register(MvcConfiguration3.class);
//2 post中文乱码
FilterRegistration.Dynamic encodingFilter = servletContext.addFilter("encoding", new CharacterEncodingFilter("UTF-8"));
encodingFilter.addMappingForUrlPatterns(null, true, "/\*");
//3 核心控制器
ServletRegistration.Dynamic mvcServlet = servletContext.addServlet("springmvc", new DispatcherServlet(application));
mvcServlet.addMapping("\*.action"); //普通项目
//mvcServlet.addMapping("/"); //RESTFul项目
mvcServlet.setLoadOnStartup(2); //tomcat启动时,执行servlet的初始化方法
}
}
2.4 数据库初始化
2.4.1 建表语句
CREATE DATABASE ssm\_crm;
USE ssm\_crm;
/\*创建客户表\*/
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 VARCHAR(10) 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;
/\*为字典表插入数据 \*/
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),
('2','001','客户行业','电子商务',NULL,2,'1',NULL),
('3','001','客户行业','医药',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),
('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),
('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),
('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);
/\*客户表数据\*/
INSERT INTO cst\_customer VALUES ('1', '传智教育', '6', '1', '23', '北京市昌平区建材城西路金燕龙办公楼一层', '010-66668888');
INSERT INTO cst\_customer VALUES ('2', '传智专修学院', '6', '1', '23', '江苏省宿迁市沭阳县北京南路999号', '0527-80961111');
INSERT INTO cst\_customer VALUES ('3', '京西集团', '7', '2', '23', '京西玉泉山', '010-65085588');
INSERT INTO cst\_customer VALUES ('4', '修正药业', '7', '3', '22', '北京市昌平区北七家镇', '010-68909090');
/\*联系人表数据\*/
INSERT INTO cst\_linkman VALUES ('1', '梁老师', 'male', '0527-82930000', '1388888888', 'zzz@czxy.com', '宣传部负责人', '很负责', '1');
INSERT INTO cst\_linkman VALUES ('2', '汪老师', 'female', '0527-8290000', '1377777777', 'lll@czxy.com', '全国统一咨询中心', '很负责', '1');
INSERT INTO cst\_linkman VALUES ('3', '高工', 'male', '010-82930000', '1399999999', 'bggg@163.com', '传智专修学院宣传中心', '宣传责任人', '2');
INSERT INTO cst\_linkman VALUES ('4', '刘管', 'female', '0527-82935100', '1366666666', 'gg@czxy.com', '管理专员', '管理', '2');
INSERT INTO cst\_linkman VALUES ('5', '李总', 'male', '021-89986886', '1355555555', 'lz@zongli.com', '总经理', '企划负责人', '3');
INSERT INTO cst\_linkman VALUES ('6', '王董', 'male', '021-80980990', '1333333333', 'wd@zongli.com', '董事长', '企业老大', '3');
INSERT INTO cst\_linkman VALUES ('7', '孙老板', 'male', '010-80980990', '1322222222', 'slb@xunta.com', '老板', '一把手', '4');
INSERT INTO cst\_linkman VALUES ('8', '陈秘书', 'female', '010-80980990', '1311111111', 'cms@xunta.com', '秘书', '二把手', '4');
2.4.2 字典表
-
开发过程中,页面中会出现
固定值
。例如:客户来源、客户所属行业、客户级别 等。 -
存在的问题?随着项目的不断壮大,此类数据的维护难度,将几何倍的增长。
-
解决方案:项目开发中,我们一般采用字典表进行处理。
-
什么是字典表?
-
用于存放系统基本参数的表。也就是将
客户来源
等信息抽取到表中。 -
例如:客户来源、客户所属行业、客户级别 等。
-
问题:独立的表越多,维护成本也将大大提升。
-
优化:创建数据字典表base_dict,用于存放此类所有数据。
-
2.4.3 客户表与字典表的关系
- 根据图片分析,字典表和客户表之间关系是
一对多
关系。
2.5 JavaBean
2.5.1 BaseDict
@Table(name="base\_dict")
public class BaseDict {
// 编号
@Id
private String dictId;
//数据字典类别代码
private String dictTypeCode;
//数据字典类别名称
private String dictTypeName;
//数据字典项目名称
private String dictItemName;
//数据字典项目
private String dictItemCode;
//排序字段
private String dictSort;
//状态 0 停用 1 启用
private String dictEnable;
// 备注
private String dictMemo;
//getter和setter
}
2.5.2 Customer
@Table(name="cst\_customer")
public class Customer {
// 主键
@Id
private Long custId;
// 客户名称
private String custName;
// 客户来源
private String custSource;
// 客户行业
private String custIndustry;
// 客户级别
private String custLevel;
// 客户地址
private String custAddress;
// 客户电话
private String custPhone;
// 客户来源数据字典对象(typeCode=002)
private BaseDict custSourceBaseDict;
// 客户行业数据字典对象(typeCode=001)
private BaseDict custIndustryBaseDict;
// 客户级别数据字典对象(typeCode=006)
private BaseDict custLevelBaseDict;
//getter 和 setter
}
2.5.3 LinkMan
@Table(name="cst\_linkman")
public class LinkMan {
// 主键
@Id
private Long lkmId;
// 名称
private String lkmName;
// 性别
private String lkmGender;
// 电话
private String lkmPhone;
// 移动电话
private String lkmMobile;
// 邮箱
private String lkmEmail;
// 职位
private String lkmPosition;
// 备注
private String lkmMemo;
// 客户的对象
private Customer customer;
@Column(name="lkm\_cust\_id")
private Long custId; //所属客户主键信息(及联系人的外键)
//getter 和 setter
}
2.6 Mapper
2.6.1 BaseDictMapper
package com.czxy.crm.mapper;
import com.czxy.crm.domain.BaseDict;
import tk.mybatis.mapper.common.Mapper;
/\*\*
\* @author 桐叔
\* @email liangtong@itcast.cn
\*/
public interface BaseDictMapper extends Mapper<BaseDict> {
}
2.6.2 CustomerMapper
package com.czxy.crm.mapper;
import com.czxy.crm.domain.Customer;
import tk.mybatis.mapper.common.Mapper;
/\*\*
\* @author 桐叔
\* @email liangtong@itcast.cn
\*/
public interface CustomerMapper extends Mapper<Customer> {
}
2.6.3 LinkManMapper
package com.czxy.crm.mapper;
import com.czxy.crm.domain.LinkMan;
import tk.mybatis.mapper.common.Mapper;
/\*\*
\* @author 桐叔
\* @email liangtong@itcast.cn
\*/
public interface LinkManMapper extends Mapper<LinkMan> {
}
3. 客户管理
========
3.1 查询所有客户
3.1.1 查询所有
-
需求:查询所有客户
-
步骤:
-
步骤1:入口
-
步骤2:编写Controller
-
步骤3:编写Service 接口、实现类
-
步骤4:修改 list.jsp展示数据
-
-
步骤1:入口
-
步骤2:编写Controller
package com.czxy.crm.controller; import com.czxy.crm.domain.Customer; import com.czxy.crm.service.CustomerService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import javax.annotation.Resource; import java.util.List; /\*\* \* @author 桐叔 \* @email liangtong@itcast.cn \*/ @Controller @RequestMapping("/customer") public class CustomerController { @Resource private CustomerService customerService; @RequestMapping("/findAll") public String findAll( Model model){ List<Customer> allCustomer = customerService.findAll(); model.addAttribute("allCustomer", allCustomer); return "customer/list"; } }
-
步骤3:编写Service 接口、实现类
-
接口
package com.czxy.crm.service; import com.czxy.crm.domain.Customer; import java.util.List; /\*\* \* @author 桐叔 \* @email liangtong@itcast.cn \*/ public interface CustomerService { /\*\* \* 查询所有 \* @return \*/ List<Customer> findAll(); }
-
实现类
package com.czxy.crm.service.impl; import com.czxy.crm.domain.BaseDict; import com.czxy.crm.domain.Customer; import com.czxy.crm.mapper.BaseDictMapper; import com.czxy.crm.mapper.CustomerMapper; import com.czxy.crm.service.CustomerService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.List; /\*\* \* @author 桐叔 \* @email liangtong@itcast.cn \*/ @Service @Transactional public class CustomerServiceImpl implements CustomerService { @Resource private CustomerMapper customerMapper; @Resource private BaseDictMapper baseDictMapper; @Override public List<Customer> findAll() { // 查询所有 List<Customer> list = customerMapper.selectAll(); // 关联查询 list.forEach(customer -> { // 客户来源 BaseDict custSourceBaseDict = baseDictMapper.selectByPrimaryKey(customer.getCustSource()); customer.setCustSourceBaseDict(custSourceBaseDict); //客户行业 BaseDict custIndustryBaseDict = baseDictMapper.selectByPrimaryKey(customer.getCustIndustry()); customer.setCustIndustryBaseDict(custIndustryBaseDict); //客户级别 BaseDict custLevelBaseDict = baseDictMapper.selectByPrimaryKey(customer.getCustLevel()); customer.setCustLevelBaseDict(custLevelBaseDict); }); return list; } }
-
-
步骤4:修改 list.jsp展示数据
<c:forEach items="${allCustomer}" var="customer"> <TR style="FONT-WEIGHT: normal; FONT-STYLE: normal; BACKGROUND-COLOR: white; TEXT-DECORATION: none"> <TD>${customer.custName }</TD> <TD>${customer.custLevelBaseDict.dictItemName }</TD> <TD>${customer.custSourceBaseDict.dictItemName }</TD> <TD>${customer.custIndustryBaseDict.dictItemName }</TD> <TD>${customer.custAddress }</TD> <TD>${customer.custPhone }</TD> <TD> <a href="${pageContext.request.contextPath }/customer/editUI.action?custId=${customer.custId}">修改</a> <a href="${pageContext.request.contextPath }/customer/delete.action?custId=${customer.custId}" οnclick="return confirm('您确定要删除【${customer.custName }】吗?')">删除</a> </TD> </TR> </c:forEach>
3.1.2 条件查询
-
需求:
-
步骤
-
步骤1:入口,确定查询表单
-
步骤2:创建CustomerVo,用于封装查询条件
-
步骤3:修改controller,获得查询条件
-
步骤4:修改service,使用查询条件
-
-
步骤1:入口,确定查询表单
-
步骤2:创建CustomerVo,用于封装查询条件
package com.czxy.crm.vo; /\*\* \* @author 桐叔 \* @email liangtong@itcast.cn \*/ public class CustomerVo { private String custName; public String getCustName() { return custName; } public void setCustName(String custName) { this.custName = custName; } }
-
步骤3:修改controller,获得查询条件
package com.czxy.crm.controller; import com.czxy.crm.domain.Customer; import com.czxy.crm.service.CustomerService; import com.czxy.crm.vo.CustomerVo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import javax.annotation.Resource; import java.util.List; /\*\* \* @author 桐叔 \* @email liangtong@itcast.cn \*/ @Controller @RequestMapping("/customer") public class CustomerController { @Resource private CustomerService customerService; @RequestMapping("/findAll") public String findAll(CustomerVo customerVo, Model model){ List<Customer> allCustomer = customerService.findAll(customerVo); model.addAttribute("allCustomer", allCustomer); return "customer/list"; } }
-
步骤4:修改service,使用查询条件
-
接口
-
实现类
package com.czxy.crm.service.impl; import com.czxy.crm.domain.BaseDict; import com.czxy.crm.domain.Customer; import com.czxy.crm.mapper.BaseDictMapper; import com.czxy.crm.mapper.CustomerMapper; import com.czxy.crm.service.CustomerService; import com.czxy.crm.vo.CustomerVo; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import tk.mybatis.mapper.entity.Example; import javax.annotation.Resource; import java.util.List; /\*\* \* @author 桐叔 \* @email liangtong@itcast.cn \*/ @Service @Transactional public class CustomerServiceImpl implements CustomerService { @Resource private CustomerMapper customerMapper; @Resource private BaseDictMapper baseDictMapper; @Override public List<Customer> findAll(CustomerVo customerVo) { // 1 条件查询 Example example = new Example(Customer.class); Example.Criteria criteria = example.createCriteria(); if(StringUtils.isNotBlank(customerVo.getCustName())) { criteria.andLike("custName", "%"+customerVo.getCustName()+"%"); } // 2 分页查询 // 3 查询所有 List<Customer> list = customerMapper.selectByExample(example); // 4 关联查询 list.forEach(customer -> { // 客户来源 BaseDict custSourceBaseDict = baseDictMapper.selectByPrimaryKey(customer.getCustSource()); customer.setCustSourceBaseDict(custSourceBaseDict); //客户行业 BaseDict custIndustryBaseDict = baseDictMapper.selectByPrimaryKey(customer.getCustIndustry()); customer.setCustIndustryBaseDict(custIndustryBaseDict); //客户级别 BaseDict custLevelBaseDict = baseDictMapper.selectByPrimaryKey(customer.getCustLevel()); customer.setCustLevelBaseDict(custLevelBaseDict); }); // 5 封装分页 return list; } }
-
3.1.3 分页查询
-
需求
-
步骤:
-
步骤1:修改CustomerVo,获得分页参数
-
步骤2:修改controller,返回pageInfo
-
步骤3:修改service,封装PageInfo
-
步骤4:修改jsp,展示列表数据
-
步骤5:修改jsp,展示分页条
-
-
步骤1:修改CustomerVo,获得分页参数
package com.czxy.crm.vo; /\*\* \* @author 桐叔 \* @email liangtong@itcast.cn \*/ public class CustomerVo { private String custName; private Integer pageNum = 1; private Integer pageSize = 2; // getter和setter }
-
步骤2:修改controller,返回pageInfo
-
步骤3:修改service,封装PageInfo
-
接口
-
实现类
package com.czxy.crm.service.impl; import com.czxy.crm.domain.BaseDict; import com.czxy.crm.domain.Customer; import com.czxy.crm.mapper.BaseDictMapper; import com.czxy.crm.mapper.CustomerMapper; import com.czxy.crm.service.CustomerService; import com.czxy.crm.vo.CustomerVo; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import tk.mybatis.mapper.entity.Example; import javax.annotation.Resource; import java.util.List; /\*\* \* @author 桐叔 \* @email liangtong@itcast.cn \*/ @Service @Transactional public class CustomerServiceImpl implements CustomerService { @Resource private CustomerMapper customerMapper; @Resource private BaseDictMapper baseDictMapper; @Override public PageInfo<Customer> findAll(CustomerVo customerVo) { // 1 条件查询 Example example = new Example(Customer.class); Example.Criteria criteria = example.createCriteria(); if(StringUtils.isNotBlank(customerVo.getCustName())) { criteria.andLike("custName", "%"+customerVo.getCustName()+"%"); } // 2 分页查询 PageHelper.startPage(customerVo.getPageNum(),customerVo.getPageSize()); // 3 查询所有 List<Customer> list = customerMapper.selectByExample(example); // 4 关联查询 list.forEach(customer -> { // 客户来源 BaseDict custSourceBaseDict = baseDictMapper.selectByPrimaryKey(customer.getCustSource()); customer.setCustSourceBaseDict(custSourceBaseDict); //客户行业 BaseDict custIndustryBaseDict = baseDictMapper.selectByPrimaryKey(customer.getCustIndustry()); customer.setCustIndustryBaseDict(custIndustryBaseDict); //客户级别 BaseDict custLevelBaseDict = baseDictMapper.selectByPrimaryKey(customer.getCustLevel()); customer.setCustLevelBaseDict(custLevelBaseDict); }); // 5 封装分页 return new PageInfo<>(list); } }
-
-
步骤4:修改jsp,展示列表数据
-
步骤5:修改jsp,展示分页条
-
查询表单
-
分页条
当前第\[<B>${pageInfo.pageNum}</B>\]页,共\[<B>${pageInfo.total}</B>\]条 ,每页显示 <select οnchange="change(this)"> <option value="1" ${pageInfo.pageSize == 1 ? 'selected' : ''}>1</option> <option value="2" ${pageInfo.pageSize == 2 ? 'selected' : ''}>2</option> <option value="3" ${pageInfo.pageSize == 3 ? 'selected' : ''}>3</option> <option value="5" ${pageInfo.pageSize == 5 ? 'selected' : ''}>5</option> <option value="10" ${pageInfo.pageSize == 10 ? 'selected' : ''}>10</option> </select> 条 <c:if test="${pageInfo.pageNum > 1}"> \[<a href="javascript:void(0)" οnclick="page(1)">首页</a>\] \[<a href="javascript:void(0)" οnclick="page(${pageInfo.pageNum - 1})">上一页</a>\] </c:if> <c:forEach begin="1" end="${pageInfo.pages}" var="num"> <b><a href="javascript:void(0)" οnclick="page(${num})">${num}</a></b> </c:forEach> <c:if test="${pageInfo.pageNum < pageInfo.pages}"> \[<a href="javascript:void(0)" οnclick="page(${pageInfo.pageNum + 1})">下一页</a>\] \[<a href="javascript:void(0)" οnclick="page(${pageInfo.pages})">尾页</a>\] </c:if> 到 <input type="number" style="width: 35px;" value="${customerVo.pageNum}" id="goId"/> 页 <input type="button" value="Go" οnclick="page(goId.value)"/>
-
js函数
function change(obj) { // 重置,如果修改了pageSize,从1开始 pageNumId.value = 1 // 修改隐藏字段 pageSize pageSizeId.value = obj.value // 提交表单 customerFormId.submit() } function page(pageNum) { // 修改pageNum的值 pageNumId.value = pageNum // 提交表单 customerFormId.submit() }
-
3.2 添加客户
3.2.1 需求
3.2.2 显示表单
-
步骤:
-
步骤1:入口
-
步骤2:修改CustomerController,用于显示
customer/add.jsp
页面-
查询数据字典:客户来源(typeCode=002)
-
查询数据字典:客户行业(typeCode=001)
-
查询数据字典:客户级别(typeCode=006)
-
-
步骤3:编写BaseDictService,通过typeCode查询所有数据字典信息。
-
步骤4:修改add.jsp,显示字典相关信息
-
-
步骤1:入口
-
步骤2:修改CustomerController,用于显示
customer/add.jsp
页面-
查询数据字典:客户来源(typeCode=002)
-
查询数据字典:客户行业(typeCode=001)
-
查询数据字典:客户级别(typeCode=006)
package com.czxy.crm.controller; import com.czxy.crm.domain.BaseDict; import com.czxy.crm.domain.Customer; import com.czxy.crm.service.BaseDictService; import com.czxy.crm.service.CustomerService; import com.czxy.crm.vo.CustomerVo; import com.github.pagehelper.PageInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import javax.annotation.Resource; import java.util.List; /\*\* \* @author 桐叔 \* @email liangtong@itcast.cn \*/ @Controller @RequestMapping("/customer") public class CustomerController { @Resource private CustomerService customerService; @Resource private BaseDictService baseDictService; /\*\* \* 添加页面 \* @return \*/ @RequestMapping("/addUI") public String addUI(Model model) { // 客户行业 (typeCode=001) List<BaseDict> custIndustryBaseDictList = baseDictService.selectAllByTypeCode("001"); model.addAttribute("custIndustryBaseDictList",custIndustryBaseDictList); // 客户来源(typeCode=002) List<BaseDict> custSourceBaseDictList = baseDictService.selectAllByTypeCode("002"); model.addAttribute("custSourceBaseDictList",custSourceBaseDictList); // 客户级别(typeCode=006) List<BaseDict> custLevelBaseDictList = baseDictService.selectAllByTypeCode("006"); model.addAttribute("custLevelBaseDictList",custLevelBaseDictList); return "customer/add"; } }
-
-
步骤3:编写BaseDictService,通过typeCode查询所有数据字典信息。
-
接口
package com.czxy.crm.service; import com.czxy.crm.domain.BaseDict; import java.util.List; /\*\* \* @author 桐叔 \* @email liangtong@itcast.cn \*/ public interface BaseDictService { /\*\* \* 通过类别代码查询数据字典信息 \* @param dictTypeCode \* @return \*/ List<BaseDict> selectAllByTypeCode(String dictTypeCode); }
-
实现类
package com.czxy.crm.service.impl; import com.czxy.crm.domain.BaseDict; import com.czxy.crm.mapper.BaseDictMapper; import com.czxy.crm.service.BaseDictService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import tk.mybatis.mapper.entity.Example; import javax.annotation.Resource; import java.util.List; /\*\* \* @author 桐叔 \* @email liangtong@itcast.cn \*/ @Service @Transactional public class BaseDictServiceImpl implements BaseDictService { @Resource private BaseDictMapper baseDictMapper; @Override public List<BaseDict> selectAllByTypeCode(String dictTypeCode) { // 条件 Example example = Example.builder(BaseDict.class).build(); example.createCriteria().andEqualTo("dictTypeCode",dictTypeCode); // 查询 return baseDictMapper.selectByExample(example); } }
-
-
步骤4:修改add.jsp,显示字典相关信息
<td>所属行业 :</td> <td> <select name="custIndustry" class=textbox style="WIDTH: 180px"> <option value="">---请选择---</option> <c:forEach items="${custIndustryBaseDictList}" var="industry"> <option value="${industry.dictId}">${industry.dictItemName}</option> </c:forEach> </select> </td>
<td>信息来源 :</td> <td> <select name="custSource" class=textbox style="WIDTH: 180px"> <option value="non">---请选择---</option> <c:forEach items="${custSourceBaseDictList}" var="source"> <option value="${source.dictId}">${source.dictItemName}</option> </c:forEach> </select> </td> <td>客户级别:</td> <td> <select name="custLevel" class=textbox style="WIDTH: 180px"> <option value="non">---请选择---</option> <c:forEach items="${custLevelBaseDictList}" var="level"> <option value="${level.dictId}">${level.dictItemName}</option> </c:forEach> </select> </td>
3.2.3 添加
-
步骤:
-
步骤1:修改add.jsp页面,确定表单提交路径
/customer/add.action
-
步骤2:修改CustomerController,添加add方法,并处理成功和失败。
-
步骤3:修改CustomerService,添加add方法
-
步骤4:修改add.jsp,显示错误信息
-
-
步骤1:修改add.jsp页面,确定表单提交路径
/customer/add.action
-
步骤2:修改CustomerController,添加add方法,并处理成功和失败。
/\*\* \* 添加 \* @param customer \* @return \*/ @RequestMapping("/add") public String add(Customer customer, Model model) { try { // 添加 boolean result = customerService.add(customer); if(result) { // 成功 return "redirect:/customer/findAll.action"; } else { // 失败 model.addAttribute("error","添加客户失败"); return "customer/add"; } } catch (Exception e) { e.printStackTrace(); model.addAttribute("error",e.getMessage()); return "customer/add"; } }
-
步骤3:修改CustomerService,添加add方法
-
接口
/\*\* \* 添加客户 \* @param customer \* @return \*/ boolean add(Customer customer);
-
实现类
@Override public boolean add(Customer customer) { int insert = customerMapper.insertSelective(customer); return insert == 1; }
-
-
步骤4:修改add.jsp,显示错误信息
<%-- 显示错误信息--%> <span style="color:red">${error}</span>
3.3 修改客户
3.3.1 需求
3.3.2 显示表单,回显数据
-
步骤:
-
步骤1:入口
/customer/editUI.action?custId=1
-
步骤2:修改CustomerController,用于显示
customer/edit.jsp
页面-
查询数据字典:客户来源(typeCode=002)
-
查询数据字典:客户行业(typeCode=001)
-
查询数据字典:客户级别(typeCode=006)
-
通过custId查询客户详情
-
-
步骤3:编写CustomerService,查询客户详情。
-
步骤4:修改edit.jsp,显示字典相关信息,回显客户信息。
-
-
步骤1:入口
/customer/editUI.action?custId=1
-
步骤2:修改CustomerController,用于显示
customer/edit.jsp
页面-
查询数据字典:客户来源(typeCode=002)
-
查询数据字典:客户行业(typeCode=001)
-
查询数据字典:客户级别(typeCode=006)
-
通过custId查询客户详情
/\*\* \* 修改页面 \* @return \*/ @RequestMapping("/editUI") public String editUI(Long custId, Model model) { // 客户行业 (typeCode=001) List<BaseDict> custIndustryBaseDictList = baseDictService.selectAllByTypeCode("001"); model.addAttribute("custIndustryBaseDictList",custIndustryBaseDictList); // 客户来源(typeCode=002) List<BaseDict> custSourceBaseDictList = baseDictService.selectAllByTypeCode("002"); model.addAttribute("custSourceBaseDictList",custSourceBaseDictList); // 客户级别(typeCode=006) List<BaseDict> custLevelBaseDictList = baseDictService.selectAllByTypeCode("006"); model.addAttribute("custLevelBaseDictList",custLevelBaseDictList); // 查询客户项 Customer customer = customerService.selectById(custId); model.addAttribute("customer",customer); return "customer/edit"; }
-
-
步骤3:编写CustomerService,查询客户详情。
-
接口
/\*\* \* 通过id查询详情 \* @param custId \* @return \*/ Customer selectById(Long custId);
-
实现类
@Override public Customer selectById(Long custId) { return customerMapper.selectByPrimaryKey(custId); }
-
-
步骤4:修改edit.jsp,显示字典相关信息,回显客户信息。
<select name="custIndustry" class=textbox style="WIDTH: 180px"> <option value="">---请选择---</option> <c:forEach items="${custIndustryBaseDictList}" var="industry"> <option value="${industry.dictId}" ${customer.custIndustry== industry.dictId?"selected":""}>${industry.dictItemName}</option> </c:forEach> </select>
<td>信息来源 :</td> <td> <select name="custSource" class=textbox style="WIDTH: 180px"> <option value="non">---请选择---</option> <c:forEach items="${custSourceBaseDictList}" var="source"> <option value="${source.dictId}" ${customer.custSource== source.dictId?"selected":""}>${source.dictItemName}</option> </c:forEach> </select> </td> <td>客户级别:</td> <td> <select name="custLevel" class=textbox style="WIDTH: 180px"> <option value="non">---请选择---</option> <c:forEach items="${custLevelBaseDictList}" var="level"> <option value="${level.dictId}" ${customer.custLevel==level.dictId?"selected":""}>${level.dictItemName}</option> </c:forEach> </select> </td>
3.3.3 修改
-
步骤:
-
步骤1:修改edit.jsp页面,确定表单提交路径
/customer/edit.action
-
步骤2:修改CustomerController,添加edit方法,并处理成功和失败。
-
步骤3:修改CustomerService,添加edit方法
-
步骤4:修改edit.jsp,显示错误信息
-
-
步骤1:修改edit.jsp页面,确定表单提交路径
/customer/edit.action
-
步骤2:修改CustomerController,添加edit方法,并处理成功和失败。
/\*\* \* 修改 \* @param customer \* @return \*/ @RequestMapping("/edit") public String edit(Customer customer, Model model) { try { // 修改 boolean result = customerService.update(customer); if(result) { // 成功 return "redirect:/customer/findAll.action"; } else { // 失败 model.addAttribute("error","修改客户失败"); return "customer/edit"; } } catch (Exception e) { e.printStackTrace(); model.addAttribute("error",e.getMessage()); return "customer/edit"; }
-
步骤3:修改CustomerService,添加edit方法
-
接口
/\*\* \* 修改 \* @param customer \* @return \*/ boolean update(Customer customer);
-
实现类
@Override public boolean update(Customer customer) { int update = customerMapper.updateByPrimaryKeySelective(customer); return update == 1; }
-
-
步骤4:修改edit.jsp,显示错误信息
3.4 删除客户
-
步骤:
-
步骤1:入口
customer/delete.action?custId=1
-
步骤2:修改CustomerController,添加delete方法,删除成功重定向到列表页。
-
步骤3:修改CustomerService,添加delete方法
-
-
步骤1:入口
customer/delete.action?custId=1
<a href="${pageContext.request.contextPath }/customer/delete.action?custId=${customer.custId}" οnclick="return confirm('您确定要删除【${customer.custName }】吗?')">删除</a>
-
步骤2:修改CustomerController,添加delete方法,删除成功重定向到列表页。
/\*\* \* 通过id删除客户 \* @param custId \* @return \*/ @RequestMapping("/delete") public String delete(Long custId) { // 删除 customerService.deleteById(custId); // 重定向列表页 return "redirect:/customer/findAll.action"; }
-
步骤3:修改CustomerService,添加delete方法
-
接口
/\*\* \* 通过id删除 \* @param custId \*/ void deleteById(Long custId);
-
实现类
@Override public void deleteById(Long custId) { customerMapper.deleteByPrimaryKey(custId); }
-
4. 联系人管理
=========
4.1 联系人与客户关系分析
-
客户:指的是有很多员工的公司、组织、企业或类似机构。
- 例如:传智学院
-
联系人:与某公司(客户)进行对接时,所需要找该公司具体的员工。
- 例如:教学-梁老师、就业-刘老师、后勤-唐老师
-
根据分析,在CRM系统中,客户和联系人的关系是
一对多
,一个公司有多个对接人。
4.2 查询所有联系人
4.2.1 查询所有
-
需求:
-
步骤:
-
步骤1:入口
-
步骤2:编写LinkManController
-
步骤3:编写LinkManService 接口、实现类
-
步骤4:修改 linkman/list.jsp 展示数据
-
-
步骤1:入口
-
步骤2:编写LinkManController
package com.czxy.crm.controller; import com.czxy.crm.domain.LinkMan; import com.czxy.crm.service.LinkManService; import com.czxy.crm.vo.LinkManVo; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import javax.annotation.Resource;
总结
本文从基础到高级再到实战,由浅入深,把MySQL讲的清清楚楚,明明白白,这应该是我目前为止看到过最好的有关MySQL的学习笔记了,我相信如果你把这份笔记认真看完后,无论是工作中碰到的问题还是被面试官问到的问题都能迎刃而解!
MySQL50道高频面试题整理:
```
* 实现类
```
@Override
public boolean update(Customer customer) {
int update = customerMapper.updateByPrimaryKeySelective(customer);
return update == 1;
}
```
- 步骤4:修改edit.jsp,显示错误信息
3.4 删除客户
-
步骤:
-
步骤1:入口
customer/delete.action?custId=1
-
步骤2:修改CustomerController,添加delete方法,删除成功重定向到列表页。
-
步骤3:修改CustomerService,添加delete方法
-
-
步骤1:入口
customer/delete.action?custId=1
<a href="${pageContext.request.contextPath }/customer/delete.action?custId=${customer.custId}" οnclick="return confirm('您确定要删除【${customer.custName }】吗?')">删除</a>
-
步骤2:修改CustomerController,添加delete方法,删除成功重定向到列表页。
/\*\* \* 通过id删除客户 \* @param custId \* @return \*/ @RequestMapping("/delete") public String delete(Long custId) { // 删除 customerService.deleteById(custId); // 重定向列表页 return "redirect:/customer/findAll.action"; }
-
步骤3:修改CustomerService,添加delete方法
-
接口
/\*\* \* 通过id删除 \* @param custId \*/ void deleteById(Long custId);
-
实现类
@Override public void deleteById(Long custId) { customerMapper.deleteByPrimaryKey(custId); }
-
4. 联系人管理
=========
4.1 联系人与客户关系分析
-
客户:指的是有很多员工的公司、组织、企业或类似机构。
- 例如:传智学院
-
联系人:与某公司(客户)进行对接时,所需要找该公司具体的员工。
- 例如:教学-梁老师、就业-刘老师、后勤-唐老师
-
根据分析,在CRM系统中,客户和联系人的关系是
一对多
,一个公司有多个对接人。
4.2 查询所有联系人
4.2.1 查询所有
-
需求:
-
步骤:
-
步骤1:入口
-
步骤2:编写LinkManController
-
步骤3:编写LinkManService 接口、实现类
-
步骤4:修改 linkman/list.jsp 展示数据
-
-
步骤1:入口
-
步骤2:编写LinkManController
package com.czxy.crm.controller; import com.czxy.crm.domain.LinkMan; import com.czxy.crm.service.LinkManService; import com.czxy.crm.vo.LinkManVo; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import javax.annotation.Resource;
总结
本文从基础到高级再到实战,由浅入深,把MySQL讲的清清楚楚,明明白白,这应该是我目前为止看到过最好的有关MySQL的学习笔记了,我相信如果你把这份笔记认真看完后,无论是工作中碰到的问题还是被面试官问到的问题都能迎刃而解!
MySQL50道高频面试题整理:
[外链图片转存中…(img-11HWDSjh-1715454631852)]