自学内容网 自学内容网

Web day08 项目实战(2)

目录

查询员工:

 在EmpController层:

在pojo层:

在EmpServiceImpl 层中:

在dao层:

新增员工:

pojo层:

EmpController层:

在EmpServiceImpl 层中:

在EmpMapper层:

在EmpExprMapper层中:

事务管理:

Transactional注解:

rollbackFor:

propagation:

其他属性:

事务的四大特性(面试):

文件上传:

生成的前端代码形式如下:

上传文件页面三要素:

引入阿里云实现 文件 上传:

FileUploadController层:

工具类(上传文件到阿里云):


查询员工:

接口文档为:

因为请求参数过多 所以 把传入的请求参数封装为对象 

返回 data中需要有 total 和   rows属性所以 需要 单独定义实体类:PageResult、

  分页查询的对象都要 封装 在PageResult中 注释掉的count为查询总数

因为传入的数据为 传统url风格 所以 只要传入的 字段名 和实体类中的 变量名相同即可 自动传入

只有 在传入的数据为 json 对象 时 (例如post请求的请求体为json对象)接json的对象 时 才用

@RequestBody 修饰 参数

 在EmpController层:

直接用对象名接收即可 不用写@RequestBody

在pojo层:

在EmpServiceImpl 层中:

运用PageHelper 中 的 getTotal可获得总数 getResult 可以根据 传入的 page 和PageSize 

得到指定页的全部数据


 

pageHelper的依赖为:

 <!-- 分页插件PageHelper -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.4.7</version>
        </dependency>

PageHelper.startPage(从第几页开始,一共分多少页)

利用动态代理和插入的思想 可以 省略 分页查询 在后续Service层调用 dao层时 查询时 不用传入 分页查询的参数

分页查询:

在dao层:

利用xml 映射文件 写出 sql 查询语句 因为 不能把sql写死 要根据 参数是否 为空进行 条件判断:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.dao.EmpMapper">

    <!--查询操作-->
    <select id="list" resultType="com.itheima.pojo.Emp">
        select * from emp e left join dept d on e.dept_id = d.id
        <where>
            <if test="name!=null and name!=''">
                and e.name like concat('%',#{name},'%')
            </if>
            <if test="gender!=null">
                and e.gender = #{gender}
            </if>
            <if test="begin!=null and begin!=''">
                and e.entry_date >= #{begin}
            </if>
            <if test="end!=null and end!=''">
                and e.entry_date &lt;= #{end}
            </if>
        </where>
    </select>

    <insert id="insertExprBatch">
        insert into emp_expr(emp_id,begin,end,company,job) values
        <foreach collection="list" item="expr" separator=",">
            (#{expr.empId},#{expr.begin},#{expr.end},#{expr.company},#{expr.job})
        </foreach>
    </insert>
</mapper>

新增员工:

发送请求的格式

pojo层:

1). 需要在 Emp 员工实体类中增加属性 exprList 来封装工作经历数据。 最终完整代码如下:

@Data
public class Emp {
    private Integer id; //ID,主键
    private String username; //用户名
    private String password; //密码
    private String name; //姓名
    private Integer gender; //性别, 1:男, 2:女
    private String phone; //手机号
    private Integer job; //职位, 1:班主任,2:讲师,3:学工主管,4:教研主管,5:咨询师
    private Integer salary; //薪资
    private String image; //头像
    private LocalDate entryDate; //入职日期
    private Integer deptId; //关联的部门ID
    private LocalDateTime createTime; //创建时间
    private LocalDateTime updateTime; //修改时间

    //封装部门名称数
    private String deptName; //部门名称

    //封装员工工作经历信息
    private List<EmpExpr> exprList;
}

EmpController层:

在EmpServiceImpl 层中:

在EmpMapper层:

 

主键返回:

主键返回:@Options(useGeneratedKeys = true, keyProperty = "id")

由于稍后,我们在保存工作经历信息的时候,需要记录是哪位员工的工作经历。 所以,保存完员工信息之后,是需要获取到员工的ID的,那这里就需要通过Mybatis中提供的主键返回功能来获取。

 

useGeneratedKeys = true:
表示启用自动生成的主键值。
通常用于插入记录时,数据库会自动生成主键值(例如,使用 AUTO_INCREMENT 的 MySQL 表)。
keyProperty = "id":
指定将自动生成的主键值赋值给对象的哪个属性。
在这个例子中,自动生成的主键值会被赋值给对象的 id 属性。

在EmpExprMapper层中:

添加员工经历


在EmpExprMapper.xml 映射文件中写 sql 插入语句

主键为自增在 insert into emp_expr() 括号中不用写入  id 

事务管理:

目的:

在添加 员工 时 添加员工数据 和 员工经历 要一起 添加成功 或 添加失败 防止因为经历添加失败 员工经历添加成功  会导致数据库数据 的不完整 不一致

 

Transactional注解:

可以在application.yml配置文件中开启事务管理日志,这样就可以在控制看到和事务相关的日志信息了

#spring事务管理日志
logging: 
  level: 
    org.springframework.jdbc.support.JdbcTransactionManager: debug

rollbackFor:

Teansactional 默认为RuntimeException 只能改成 范围大的 Exeption 遇到所有异常都会 回滚事务

propagation:

@Transactional注解当中的第二个属性propagation,这个属性是用来配置事务的传播行为的。

在日志记录中运用 propagation 属性 使日志记录 保存到数据库中成为 单独的事务 不受 添加员工 和 添加 员工经历数据 的事务影响

                                                   

其他属性:

事务的四大特性(面试):

  • 原子性(Atomicity):事务是不可分割的最小单元,要么全部成功,要么全部失败。

  • 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。

  • 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。

  • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。

文件上传:

生成的前端代码形式如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传文件</title>
</head>
<body>

    <form action="/upload" method="post" enctype="multipart/form-data">
        姓名: <input type="text" name="username"><br>
        年龄: <input type="text" name="age"><br>
        头像: <input type="file" name="file"><br>
        <input type="submit" value="提交">
    </form>

</body>
</html>

上传文件页面三要素:

  • 表单必须有file域,用于选择要上传的文件

  • 表单提交方式必须为POST:通常上传的文件会比较大,所以需要使用 POST 提交方式

  • 表单的编码类型enctype必须要设置为:multipart/form-data:普通默认的编码格式是不适合传输大型的二进制数据的,所以在文件上传时,表单的编码格式必须设置为multipart/form-data

服务端代码为:

@RestController
public class UpLoadFileController {
    @PostMapping("/upload2")
    public Result upload(String name , Integer age , MultipartFile file) throws Exception {
        String originalFilename = file.getOriginalFilename();
        //生成新的文件名 用重复的文件名可能被覆盖并取原文件后缀名
        String newFileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
        File dir = new File("D:/resource/images/");
        if (!dir.exists()){
            dir.mkdirs();
        }
        //transferTo 方法可以把文件写入磁盘
        file.transferTo(new File(dir,newFileName));
        return Result.Success("http://localhost:8080/images/"+newFileName);

    }
}

工具类 单独建一个包 叫 uiti

引入阿里云实现 文件 上传:

接口信息:

 响应数据格式为:

 

FileUploadController层:

用MultipartFile 类型接受 file对象:

file.getBytes() 为获取文件的字节码文件 

工具类(上传文件到阿里云):

@Component
public class OSSFileUpholdUtil {
    @Value(value = "${aliyun.oss.endpoint}")
    private String endpoint ;

    @Value(value = "${aliyun.oss.bucketName}")
    private String bucketName ;

    @Value(value = "${aliyun.oss.region}")
    private String region ;

    public String upload(String originalFilename,byte[] content) throws Exception {
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量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"));
        //生成一个新的不重复的文件名
        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));
            System.out.println("文件 " + objectName + " 上传成功。");
        } finally {
            ossClient.shutdown();
        }

        return "https://" + bucketName + "." + endpoint.replaceAll("https://", "") + "/" + objectName;
    }

}

application.yml中配置

aliyun:
  oss:
    endpoint: https://oss-cn-beijing.aliyuncs.com
    bucketName: mos-strorge
    region: cn-beijing

 


原文地址:https://blog.csdn.net/moskidi/article/details/144276692

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!