t_address
- CREATE TABLE t_address (
- aid INT AUTO_INCREMENT COMMENT '收货地址id',
- uid INT COMMENT '归属的用户id',
- `name` VARCHAR(20) COMMENT '收货人姓名',
- province_name VARCHAR(15) COMMENT '省-名称',
- province_code CHAR(6) COMMENT '省-行政代号',
- city_name VARCHAR(15) COMMENT '市-名称',
- city_code CHAR(6) COMMENT '市-行政代号',
- area_name VARCHAR(15) COMMENT '区-名称',
- area_code CHAR(6) COMMENT '区-行政代号',
- zip CHAR(6) COMMENT '邮政编码',
- address VARCHAR(50) COMMENT '详细地址',
- phone VARCHAR(20) COMMENT '手机',
- tel VARCHAR(20) COMMENT '固话',
- tag VARCHAR(6) COMMENT '标签',
- is_default INT COMMENT '是否默认:0-不默认,1-默认',
- created_user VARCHAR(20) COMMENT '创建人',
- created_time DATETIME COMMENT '创建时间',
- modified_user VARCHAR(20) COMMENT '修改人',
- modified_time DATETIME COMMENT '修改时间',
- PRIMARY KEY (aid)
- ) ENGINE=INNODB DEFAULT CHARSET=utf8;
注意name是关键字,所以需要用``
在entity包下创建实体类Address继承BaseEntity类
- /**
- * 收货地址的实体类
- */
- @Data
- @AllArgsConstructor
- @NoArgsConstructor
- public class Address extends BaseEntity {
- private Integer aid;//收货地址id
- private Integer uid;//归属用户id
- private String name;//收货人姓名
- private String provinceName;//省
- private String provinceCode;//省行政代号
- private String cityName;//市名
- private String cityCode;//市行政代号
- private String areaName;//区名
- private String areaCode;//区行政代号
- private String zip;//邮政编码
- private String address;//详细地址
- private String phone;//手机
- private String tel;//固话
- private String tag;//标签
- private Integer isDefault;//是否默认 0-不默认,1-默认
- }
当前收货地址功能模块:
开发顺序:新增收货地址->列表的展示->设置默认收货地址->删除收货地址->修改收货地址
insert into t_address (aid以外的所有字段) values (字段值)
2. 大部分平台都会规定一个用户的收货地址数量,这里规定最多20个.那么在插入用户新的地址之前就要先做查询操作.如果查询到的是刚好20,这并不是一个java语法的异常,可以认为是业务控制的异常,这个异常随后在service抛,在controller捕获
select count(*) from t_address where uid=?
创建接口AddressMapper,在这个接口中定义上面两个SQL语句抽象方法定义
- //收货地址持久层接口
- public interface AddressMapper {
- /**
- * 插入用户的收货地址数据
- *
- * @param address 收货地址
- * @return 受影响的行数
- */
- Integer insertAddress(Address address);
-
- /**
- * 获取收货地址的数量(不能超过20),根据用户的uid
- *
- * @param uid 用户uid
- * @return 收货地址数量
- */
- Integer countAddress(Integer uid);
- }
1.在mapper标签中配置Address类属性与数据库中表的字段映射
- <resultMap id="AddressEntityMap" type="com.example.mycomputerstore.entity.Address">
- <id column="aid" property="aid"/>
- <result column="province_code" property="provinceCode"/>
- <result column="province_name" property="provinceName"/>
- <result column="city_code" property="cityCode"/>
- <result column="city_name" property="cityName"/>
- <result column="area_code" property="areaCode"/>
- <result column="area_name" property="areaName"/>
- <result column="is_default" property="isDefault"/>
- <result column="created_user" property="createdUser"/>
- <result column="created_time" property="createdTime"/>
- <result column="modified_user" property="modifiedUser"/>
- <result column="modified_time" property="modifiedTime"/>
- resultMap>
判断该映射是否配置成功:按着ctrl并点击type="com.cy.store.entity.Address"中的Address,如果能跳转到Address类说明映射成功
2.在AddressMapper.xml中配置以上两个抽象方法的映射
- <insert id = "insertAddress" useGeneratedKeys="true" keyProperty="aid">
- INSERT INTO t_address (
- uid, name, province_name, province_code, city_name, city_code, area_name, area_code, zip,
- address, phone, tel, tag, is_default, created_user, created_time, modified_user, modified_time)
- VALUES (
- #{uid}, #{name}, #{provinceName}, #{provinceCode}, #{cityName}, #{cityCode},
- #{areaName}, #{areaCode}, #{zip}, #{address}, #{phone}, #{tel}, #{tag},
- #{isDefault}, #{createdUser},#{createdTime}, #{modifiedUser}, #{modifiedTime})
-
-
-
- SELECT count(*) FROM t_address WHERE uid = #{uid}
-
- @SpringBootTest
- @RunWith(SpringRunner.class)
- public class AddressMapperTests {
-
- @Autowired
- private AddressMapper addressMapper;
-
- @Test
- public void insert() {
- Address address = new Address();
- address.setUid(11);
- address.setPhone("133336");
- address.setName("女朋友");
- addressMapper.insert(address);
- }
-
- @Test
- public void countByUid() {
- Integer count = addressMapper.countByUid(11);
- System.out.println(count);
- }
- }
- /**收货地址总数超出限制的异常(20条)*/
- public class AddressCountLimitException extends ServiceException {
- /**重写ServiceException的所有构造方法*/
- }
插入数据时产生未知的异常InsertException(已经有了,不需要重复创建)
1.创建一个IAddressService接口,在接口中定义业务的抽象方法
因为mapper层接口该功能模块定义了两个抽象方法,所以就要在service层接口该功能模块也定义两个抽象方法?不是这样的,要看mapper层的这两个方法是依赖关系还是独立关系,如果某一个抽象方法依赖于另一个抽象方法,那就需要在业务层将这两个方法整合到一个方法中.一句话来说就是:一个功能模块可能需要多条sql语句
- //收货地址业务层接口
- public interface IAddressService {
- /**
- *这三个参数的由来:
- * 1.首先肯定要有address
- * 2.业务层需要根据uid查询该用户收货地址总数及新建地址时给字段uid赋值
- * 但新建收货地址的表单中并没有哪个控件让输入用户uid,所以需要控制层将uid传给业务层
- * 3.业务层在创建/修改收货地址时需要同时修改数据库中创建人/修改人的字段
- * 但新建收货地址的表单中并没有哪个控件让输入用户username,所以需要控制层将username传给业务层
- * 注意:> 可以用HttpSession session代替Integer uid, String username,但
- * 这样写的话就需要把BaseController类下获取uid,username的方法重新封装到一个
- * 类中并让IAddressServiceImp实现类继承该类,这样就需要微调一下代码逻辑,太麻
- * 烦,并且,最好每一层只处理该层需要做的事情,session对象是控制层传递的,所以就
- * 把session对象定义封装在控制层中,不需要在业务层中额外处理以降低耦合
- */
- void addAddress(Integer uid, String username, Address address);
- }
可以用HttpSession session代替Integer uid, String username,但这样写的话就需要把BaseController类下获取uid,username的方法重新封装到一个类中并让AddressServiceImpl实现类继承该类,这样就需要微调一下代码逻辑,太麻烦,并且,最好每一层只处理该层需要做的事情,session对象是控制层传递的,所以就把session对象定义封装在控制层中,不需要在业务层中额外处理,这样可以降低耦合
2.创建一个AddressServiceImpl类实现接口中抽象方法
- @Service
- public class IAddressServiceImpl implements IAddressService {
-
- @Autowired
- private AddressMapper addressMapper;
-
-
- //在添加用户的收货地址的业务层依赖于DistrictService的业务层接口
- @Autowired
- private IDistrictService districtService;
-
- /**
- * 为了方便日后修改最大收货地址数量,可以在配置文件
- * application.properties中定义user.address.max-count=20
- */
- @Value("${user.address.max-count}")
- private Integer MaxAddress ;
-
-
- @Override
- public void addAddress(Integer uid, String username, Address address) {
- //查询收货地址信息是否大于20
- Integer count = addressMapper.countAddress(uid);
- if(count >= MaxAddress) {
- throw new AddressCountLimitException("收货地址不能超过20条");
- }
-
- //设置信息
- address.setUid(uid);
- Integer isDelete = count == 0 ? 1 : 0;//1表示默认收货地址,0反之
- address.setIsDefault(isDelete);
- address.setCreatedTime(new Date());
- address.setCreatedUser(username);
- address.setModifiedTime(new Date());
- address.setModifiedUser(username);
-
- //对address对象中的数据进行补全:省市区
- String provinceName = districtService.getNameByCode(address.getProvinceCode());
- String cityName = districtService.getNameByCode(address.getCityCode());
- String areaName = districtService.getNameByCode(address.getAreaCode());
- address.setProvinceName(provinceName);
- address.setCityName(cityName);
- address.setAreaName(areaName);
-
-
- //插入收货地址
- Integer row = addressMapper.insertAddress(address);
- if(row != 1) {
- throw new InsertException("未知错误 在 新建收货地址");
- }
- }
- }
别忘了在配置文件application.properties中定义user.address.max-count=20
在test下的service文件夹下创建AddressServiceTests测试类
- @SpringBootTest
- @RunWith(SpringRunner.class)
- public class AddressServiceTests {
- @Autowired
- private IAddressService addressService;
-
- @Test
- public void addNewAddress() {
- Address address = new Address();
- address.setPhone("175726");
- address.setName("男朋友");
- addressService.addNewAddress(11,"mxy",address);
- }
- }
义务层抛出了收货地址总数超出上限的异常,在BaseController中进行捕获处理
- else if (e instanceof AddressCountLimitException) {
- result.setState(4003);
- result.setMessage("用户的收货地址超出上限的异常");
- }
- /addresses/add_new_address
- post
- Address address,HttpSession session
- JsonResult
在controller包下创建AddressController并继承BaseController,该类用来处理用户收货地址的请求和响应
- /**
- * 用户收货地址
- */
- @RestController
- @RequestMapping("/address")
- public class AddressController extends BaseController {
-
- @Autowired
- private IAddressService addressService;
-
-
- /**
- * 新增用户收货地址
- *
- * @param address
- * @param session:这里使用session 是为了获取用户的uid和username
- * @return
- */
- @PostMapping("/add_new_address")
- public JsonResult
addAddress(Address address, HttpSession session) { - //先获取用户uid和username
- Integer uid = getuidFromSession(session);
- String username = getUsernameFromSession(session);
- addressService.addAddress(uid, username, address);
- return new JsonResult<>(OK);
- }
- }
- $("#btn-add-new-address").click(function (){
- $.ajax({
- url:"/address/add_new_address",
- type:"POST",
- data:$("#form-add-new-address").serialize(),
- dataType:"JSON",
- success(e){
- if(e.state==200){
- alert("新增收货地址成功")
- }else{
- alert("新增收货地址失败")
- }
- },
- error(xhr){
- alert("新增收货地址产生未知的异常"+xhr.status)
- }
- })
- })