4个技术点

点一

阿里云配置放入配置文件统一管理

1.注入外部配置文件中的配置项的两种方式?

@Value  //一个属性一个属性的注入
@ConfigurationProperties //批量将多个属性注入bean对象中

2.两种方式各自的使用场景?

​ 如果属性较少,建议@Value注入

​ 如果属性较多,考虑复用,建议使用
以上是该功能需要背过记住的两个注解★★★

代码如下:

#阿里云OSS                                                 //配置文件application.yml
aliyun:
  oss:
    endpoint: https://oss-cn-beijing.aliyuncs.com
    bucketName: java-426-ai
    region: cn-beijing
@Component         //配置阿里云,后面上传图片放在阿里云OSS上存储   //工具类AliyunOSSOperator
public class AliyunOSSOperator {
    @Autowired
    private OperatorPropertie operatorPropertie;
    //修改一:改成自己的OSS服务器中的bucket对应的域名中
    //private String endpoint = "https://oss-cn-beijing.aliyuncs.com";
    //修改二:改成自己的OSS服务器中的bucket名称
    //private String bucketName = "java-426-ai";
    //修改三:改成自己的OSS服务器所属区域
    //private String region = "cn-beijing";

    /*优化
        为了方便统一管理   配置少的时候可以用@Value来读取配置文件中的值
        @Value("${aliyun.oss.endpoint}")
        private String endpoint;
        @Value("${aliyun.oss.bucketName}")
        private String bucketName;
        @Value("${aliyun.oss.region}")
        private String region;
     */

    /*  用@configpro注解
        需要单独来一个配置类,然后使用get方法获取配置文件中的值
     */
    public String upload(byte[] content, String originalFilename) throws Exception {

        String endpoint = operatorPropertie.getEndpoint();
        String bucketName = operatorPropertie.getBucketName();
        String region = operatorPropertie.getRegion();

        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        // 填写Object完整路径,例如202406/1.png。Object完整路径中不能包含Bucket名称。
        //获取当前系统日期的字符串,格式为 yyyy/MM
        String dir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM"));  //2025/04
        //生成一个新的不重复的文件名
        String newFileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
        String objectName = dir + "/" + newFileName;

        // 创建OSSClient实例。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        try {
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content));
        } finally {
            ossClient.shutdown();
        }

        return endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;
    }

}
@Data                                           //处理读取方式的前缀的工具类 OperatorPropertie
@ConfigurationProperties(prefix = "aliyun.oss")//prefix 前缀
@Component
//@ConfigurationProperties 读取方式
public class OperatorPropertie {
    private String endpoint;
    private String bucketName;
    private String region;
}

点二

删除员工数据的功能

1.@RequestParam("形参变量")  //只要有参数,就必须加在Controller请求方法的参数上加上这个
2.@Transactional("rollbackFor = Exception.class") //service方法上开启事务管理,一起成功一起失败
3.@Param("形参变量")            //只要有参数,就必须在Mapper方法参数上加这个
4. <delete id="deleteByIds">
        delete from emp where id in
        <foreach collection="ids" item="id" open="(" separator="," close=")">
            #{id}    //id处是mapper中的删除方法。collection是mapper方法的形参。
        </foreach>   //item是变量名随便取值 open separator close三个属性需要记住            
    </delete>        //foreach记住!!!

以上是该功能需要背过记住的四个点★★★★★
功能分析
day 04  批量删除员工数据的功能、修改员工数据(回显+修改)功能、 异常处理器、case查询语法
具体实现代码如下:

/**
 * 三、批量删除 员工请求                                               Controller
 * @param ids
 * @return
 */
@DeleteMapping("/emps")
public Result deleteEmp(@RequestParam("ids") List<Integer> ids)
{  //数组  集合都行
   empService.deleteEmp(ids);
   return Result.success();
}
/**
 * 批量删除员工的业务功能                                               Service
 *                                                                         impl
 * @param ids
 */
@Transactional(rollbackFor = Exception.class)
@Override
public void deleteEmp(List<Integer> ids) {
    //删除员工基本信息
    empMapper.deleteByIds(ids);
    //删除员工工作经历
    empExprMapper.deleteByEmpIds(ids);
}
/**
 * 删除员工数据                                                        Mapper
 * @param ids                                                              interface
 */
void deleteByIds(@Param("ids") List<Integer> ids);
                                                                    //ExprMapper
void deleteByEmpIds(@Param("ids") List<Integer> ids);
<delete id="deleteByIds">                               //emp.xml
    delete from emp where id in
    <foreach collection="ids" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>
</delete>                                               

<delete id="deleteByEmpIds">                            //empexpr.xml
      delete from emp_expr where emp_id in
    <foreach collection="ids" item="id" open="(" separator="," close=")">
            #{id}
    </foreach>
</delete>

功能思路
day 04  批量删除员工数据的功能、修改员工数据(回显+修改)功能、 异常处理器、case查询语法

点三

修改员工数据的功能

1.员工数据用emp和emp_expr俩表存储的,员工信息用Emp实体类返回而员工经历需要特殊处理(实体封装的集合)

 <resultMap id="baseEmpMap" type="com.itheima.pojo.Emp">  
        <id column="id" property="id"/>         //员工信息可以用实体类Emp中的基本属性来接收
        <result column="username" property="username"/>
        <result column="password" property="password"/>
        <result column="name" property="name"/>
        <result column="gender" property="gender"/>         
        <result column="phone" property="phone"/>    
        <result column="job" property="job"/>  
        <result column="salary" property="salary"/>
        <result column="image" property="image"/>
        <result column="entry_date" property="entryDate"/>
        <result column="dept_id" property="deptId"/>
        <result column="create_time" property="createTime"/>
        <result column="update_time" property="updateTime"/>
                                                //员工经历则需要用Emp中的exprList集合来接收
        <collection property="exprList" ofType="com.itheima.pojo.EmpExpr">
            <id column="ee_id" property="id"/>
            <result column="ee_company" property="company"/>
            <result column="ee_job" property="job"/>
            <result column="ee_begin" property="begin"/>
            <result column="ee_end" property="end"/>
            <result column="ee_empid" property="empId"/>
        </collection>
    </resultMap>

    <select id="getEmpWithEmpExprById" resultMap="baseEmpMap"> 
        SELECT e.*,   //(俩表)有些属性对不上:故记住mybatis提供的方案:属性的特殊处理resultMap★★★
               ee.id      ee_id,
               ee.emp_id  ee_emp_id,
               ee.begin   ee_begin,
               ee.end     ee_end,
               ee.company ee_company,
               ee.job     ee_job
        FROM emp e
                 LEFT JOIN emp_expr ee ON ee.emp_id = e.id
        WHERE e.id = #{id}
    </select>

@注解可以抽出请求路径更方便

@PathVariable("") //接收路径参数的注解 ★

2.修改员工数据

动态sql的标签,动态sql能够让对应的功能更加灵活扩展性高

 <!--  修改员工信息  -->
    <update id="updateById">
        update emp
    <!--   优化修改功能: 只修改几个时用if来判断一些情况让修改功能更加灵活更有扩展性     -->
    <!-- set标签的作用是: 消除sql语句中的,   -->
        <set>
            <if test="username != null and username !=''">username=#{username},</if>
            <if test="password != null and password !=''">password=#{password},</if>
            <if test="name != null and name !=''">name=#{name},</if>
            <if test="gender != null">gender=#{gender},</if>
            <if test="phone != null and phone !=''">phone=#{phone},</if>
            <if test="salary != null">salary=#{salary},</if>
            <if test="job != null">job=#{job},</if>
            <if test="image != null and image !=''">image=#{image},</if>
            <if test="entryDate != null">entry_date=#{entryDate},</if>
            <if test="deptId != null">dept_id=#{deptId},</if>
            <if test="updateTime != null">update_time=#{updateTime},</if>
        </set>
        where id=#{id}
    </update>

遇到的问题: mapper中的报错
day 04  批量删除员工数据的功能、修改员工数据(回显+修改)功能、 异常处理器、case查询语法

注意: 当mapper中的方法上没有加sql注解来操作数据库的话

​ 就需要在mapper.xml文件中配置sql语句(一般处理较复杂的情况)

小技巧: 点mapper方法左侧的小鸟即可快速移动到mapper.xml修改属性的方法名(文件太多时不容易乱)

以上是总结今天修改功能学到的两个点和遇到的问题小技巧

修改功能分析
day 04  批量删除员工数据的功能、修改员工数据(回显+修改)功能、 异常处理器、case查询语法

下面是功能的具体实现:

    /**                                             Controller
     * 四、修改员工信息 ->1.数据回显(映射回显)
     * @param id
     * @return
     */
    @GetMapping("/emps/{id}")
    public Result getByID(@PathVariable Integer id){
        Emp emp = empService.getEmpWithExprById(id);
        return Result.success(emp);
    }

        //2.修改请求->修改
    @PutMapping("/emps")
    public Result updateEmp(@RequestBody Emp emp) throws Exception {
        empService.updateEmp(emp);
        return Result.success();
    }
    /**
     * 修改员工信息:
     * 一次性把员工基本信息和员工工作经历都查询出来
     *
     * @param id
     * @return
     */
    @Override
    public Emp getEmpWithExprById(Integer id) {
        return empMapper.getEmpWithEmpExprById(id);
    }

        /**
     * 修改员工信息:
     * 修改的逻辑->先删除后新增
     *
     * @param emp
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateEmp(Emp emp) {
        //1.更新员工的基本信息
        emp.setUpdateTime(LocalDateTime.now());
        empMapper.updateById(emp);

        //2.删除此员工的工作经历
        Integer id = emp.getId();
        empExprMapper.deleteByEmpIds(Arrays.asList(id));

        //3.新增此员工的工作经历
        if (!CollectionUtils.isEmpty(emp.getExprList())) {
            emp.getExprList().forEach(empExpr -> empExpr.setEmpId(id));
            empExprMapper.insertBatch(emp.getExprList());
        }
    }
 //映射回显                                         empmapper
    Emp getEmpWithEmpExprById(Integer id);

    //简单回显
//    @Select("select * from emp where id=#{id}")
//    Emp getById(Integer id);

    void updateById(Emp emp);
 <!--  修改员工信息                               empmapper.xml-->        
    <update id="updateById">
        update emp
    <!--   优化修改功能: 单个修改时更加灵活更有扩展性     -->
    <!-- set标签的作用是: 消除sql语句中的,   -->
        <set>
            <if test="username != null and username !=''">username=#{username},</if>
            <if test="password != null and password !=''">password=#{password},</if>
            <if test="name != null and name !=''">name=#{name},</if>
            <if test="gender != null">gender=#{gender},</if>
            <if test="phone != null and phone !=''">phone=#{phone},</if>
            <if test="salary != null">salary=#{salary},</if>
            <if test="job != null">job=#{job},</if>
            <if test="image != null and image !=''">image=#{image},</if>
            <if test="entryDate != null">entry_date=#{entryDate},</if>
            <if test="deptId != null">dept_id=#{deptId},</if>
            <if test="updateTime != null">update_time=#{updateTime},</if>
        </set>
        where id=#{id}
    </update>

修改-的回显功能还有第二种方法更简单一些,具体可以对比一下想用哪个都行
动态sql方法
day 04  批量删除员工数据的功能、修改员工数据(回显+修改)功能、 异常处理器、case查询语法
俩sql的方法
day 04  批量删除员工数据的功能、修改员工数据(回显+修改)功能、 异常处理器、case查询语法[![]
功能思路
day 04  批量删除员工数据的功能、修改员工数据(回显+修改)功能、 异常处理器、case查询语法
点四项目异常

全局异常处理器:统一项目的全局异常处理格式
day 04  批量删除员工数据的功能、修改员工数据(回显+修改)功能、 异常处理器、case查询语法
day 04  批量删除员工数据的功能、修改员工数据(回显+修改)功能、 异常处理器、case查询语法

 @RestControllerAdvice                //加在类上 加强异常。和下面注解一起使用
@ExceptionHandler(Exception.class)    //加在方法上,每个方法可以精准的处理对应的异常

具体代码实现:

@RestControllerAdvice
public class GlobalExceptionAdvice {            //写一个异常处理器,注意放在启动类同级目录下
    @ExceptionHandler(Exception.class)
    public Result allException(Exception e){    //所有异常
        e.printStackTrace(); //报错打印到后台
            return Result.error("服务器异常,请联系管理员"); //Result统一数据格式
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public Result allException(DuplicateKeyException e){    //有重复值的异常
        e.printStackTrace(); //报错打印到后台
        if (e.getMessage().contains("emp.username")){
            return Result.error("您新增的用户名已存在");
        }
        if (e.getMessage().contains("emp.phone")){
            return Result.error("对应手机号的用户已存在");
        }
        if (e.getMessage().contains("emp.image")){
            return Result.error("对应手已存在");
        }
        return Result.error("数据已存在"); //Result统一数据格式
    }
}

效果如下:
day 04  批量删除员工数据的功能、修改员工数据(回显+修改)功能、 异常处理器、case查询语法
注意点:
全局异常处理器的包要 和启动类同级才能扫描到