三条命令完成 qmc3 转 mp3:qmc-decoder 做 QQ音乐格式转换的指南
2026/8/22 13:32:23
packagecom.atguigu.pojo;publicclassEmployee{privateIntegerid;privateStringname;privateStringplone;publicIntegergetId(){returnid;}publicvoidsetId(Integerid){this.id=id;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicStringgetPlone(){returnplone;}publicvoidsetPlone(Stringplone){this.plone=plone;}@OverridepublicStringtoString(){return"Employee{"+"id="+id+", name='"+name+'\''+", plone='"+plone+'\''+'}';}}packagecom.atguigu.mapper;importcom.atguigu.pojo.Employee;importorg.apache.ibatis.annotations.Param;importjava.util.List;importjava.util.Map;publicinterfaceEmployeeMapper{根据id查看员工信息EmployeequeryById(Integerid);根据id删除员工信息(单个简单类型作为参数)intdeleteById(Integerid);根据 plone 查询员工的信息(单个简单类型作为参数)List<Employee>queryByPlone(Stringplone);插入员工数据(单个实体对象作为参数)intinsertEmp(Employeeemployee);传入多个简单类型的参数List<Employee>queryByNameAndPlone(@Param("xname")Stringname,@Param("xplone")Stringplone);传入 map类型的参数intinsertEmpMap(Mapdata);-----------------------------------------------------------------------------查询工资高于传入值的员工姓名们List<String>queryNamesBySalary(@Param("salary")Doublesalary);返回集合类型,查询全部员工信息List<Employee>queryAll();返回map类型,查询城市的最高工资和平均工资Map<String,Object>selectEmpNameAndMaxSalary();// 多条结果返回 List<Map>// 多条结果 → 返回 List<Map<String, Object>>List<Map<String,Object>>selectAllEmpWithMaxSalary();自增长主键回显,自动提交事务intinsertUser(Employeeemployee);-----------------------------------------------------------------------------mybatis自己维护非自增主键intinsertEmployee(Employeeemployee);EmployeequeryByIdd(StringtId);}<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTO Config 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">namespace = 接口的权限定符<mappernamespace="com.atguigu.mapper.EmployeeMapper"><selectid="queryById"resultType="com.atguigu.pojo.Employee">select id, name, plone from my_user where id = #{id}</select>场景1:传入参数,是单个简单类型,key的值随便写,一般推荐使用参数名<deleteid="deleteById"><!-- key的值可以这样写:delete from my_user where id = #{ergouzi} --><!-- 推荐还是使用参数名,如下 -->delete from my_user where id = #{id}</delete><selectid="queryByPlone"resultType="com.atguigu.pojo.Employee">select id, name, plone from my_user where plone = #{plone}</select>场景2:传入的参数,是单个实体对象,key的值怎么写呢? key = (实体类的每个)属性名,即可 其实,不用把实体类的每个属性都写出来,只需要把你要用的属性写出来就行了<insertid="insertEmp">insert into my_user (name, plone) values (#{name},#{plone});</insert>场景3:传入多个简单类型的参数,key的值怎么写呢? * 方案1:使用@param注解(推荐使用注解) * 方案2:mybatis的默认机制,如下: 形参arg0, arg1 ... , argn 从左到右依次对应的key值是 arg0, arg1 ... , argn<selectid="queryByNameAndPlone"resultType="com.atguigu.pojo.Employee">select id, name, plone from my_user where plone = #{xplone} and name = #{xname}</select>场景4:传入的是 map类型 的参数,key的值怎么写呢? key = map的key,即可<insertid="insertEmpMap">insert into my_user (name, plone) values (#{name},#{plone});</insert>--------------------------------------------------------------------------------------------------- 当,返回值是,集合类型,时,resultType 怎样指定? 这里就用到了MyBatis中的别名 切记: 返回值是集合时,resultType不需要指定集合类型,只需要指定泛型即可, 为什么呢? 因为 mybatis 底层是 ibatis, 虽然,selectOne是查询单个,selectList是查询集合, 但是,selectOne 其实也是调用的 selectList, 只不过, selectOne的时候,取的是selectList里面的第一个值而已 所以,返回值是集合时,resultType不需要指定集合类型,只需要指定泛型即可。<selectid="queryNamesBySalary"resultType="string">select name from my_user where salary > #{salary}</select>因为,在mybatis-config.xml文件种配置了别名,下面这一行<typeAliases><packagename="com.atguigu.pojo"/></typeAliases>所以,这里可以 resultType="employee",而不用 resultType="com.atguigu.pojo.Employee" 了<selectid="queryAll"resultType="employee">select * from my_user</select>什么时候,返回map? 当没有实体类可以使用接值的时候,可以使用map接受数据, map的key,对应,查询的列名 map的value,对应,查询的值<selectid="selectEmpNameAndMaxSalary"resultType="map">SELECT name, salary, (SELECT AVG(salary) FROM my_user) avgSalary FROM my_user WHERE salary = (SELECT MAX(salary) FROM my_user) LIMIT 1 -- 限制只返回1条</select>多条结果 → 返回 List<Map<String,Object>> List<Map<String,Object>> selectAllEmpWithMaxSalary();<selectid="selectAllEmpWithMaxSalary"resultType="map">SELECT name, salary, (SELECT AVG(salary) FROM my_user) avgSalary FROM my_user WHERE salary = (SELECT MAX(salary) FROM my_user)</select>自增长主键回显,自动提交事务 【实体类必须有setter:MyBatis 通过反射调用setId()给主键赋值,没有 setter 则 id 永远为 null】 获取自增长的主键,可以使用: useGeneratedKeys="true",代表,我们想要获取数据库自增的主键id keyColumn="id",代表,数据库表的主键列的值 keyProperty="id",代表,接收主键列值的实体类的属性<insertid="insertUser"useGeneratedKeys="true"keyColumn="id"keyProperty="id">insert into my_user (name, plone) values(#{name}, #{plone});</insert>--------------------------------------------------------------------------------------------------- mybatis自己维护非自增主键<insertid="insertEmployee">让mybatis帮我们维护非自增的主键,我们就不在MybatisTest.java中编写相关的代码了 order="BEFORE" 或者 "AFTER",意思是,在sql语句之前执行,还是之后执行 resultType,表示,返回值类型 keyProperty,表示,查询的结果,给实体类中的哪个属性 这个 selectkey 就相当于 MybatisTest.java文件中的,下面这几行代码 自己维护主键,使用uuid,这里replaceAll操作,是去掉uuid的中划线 String id = UUID.randomUUID().toString().replaceAll("-", ""); employee.settId(id);<selectKeyorder="BEFORE"resultType="string"keyProperty="id">SELECT REPLACE(UUID(),'-','') // 生成无中划线的UUID</selectKey>insert into my_user (id, name) values(#{id}, #{name})</insert>order="BEFORE"的情况 1. MyBatis 先单独执行 selectKey 里面这条查询 SQL: 2. 拿到返回的 UUID 字符串,把这个值 set 到你传入实体对象的 `id` 属性上(`keyProperty="id"`) 3. 然后再执行下面的 `insert` SQL,此时 `#{id}` 就已经有值了。 order="AFTER"的情况 1. insert先执行,`#{id}`是null → 数据库存入一条 id=null 的记录,直接报错!主键不能为 null 2. 后面才去查 UUID,为时已晚。 3. AFTER 永远不能用来生成主键!只能取回数据库已经生成好的主键。 属性 执行顺序 适用场景 插入时实体id值 数据库主键配置 order="BEFORE" 先查,再插入 UUID、雪花ID,程序/数据库函数生成主键 有值 不要 AUTO_INCREMENT order="AFTER" 先插入,再查询 MySQL 自增主键 null 必须 AUTO_INCREMENT 列名 和 属性名 不一致如何解决? 方案1:别名:select t_id tId, t_name tName from teacher where t_id = #{tId} 方案2:开启mybatis的驼峰式映射配置:<settingname="mapUnderscoreToCamelCase"value="true"/>会自动把 t_id 映射成 tId 方案3:使用resultMap自定义映射,注意:resultType 和 resultMap 二选一! resultType按照规则自动映射,按照是否开启驼峰式映射。自己映射属性和列名,只能映射一层结构 resultMap可以深层次的映射哦!!! 例如: 声明 resultMap标签,定义自己的映射规则 id:是某个resultMap的唯一标识, 用于在<selectid="queryById"resultMap="id">中, 确定这个select使用哪个resultMap result:普通列的映射关系 id标签,通常用于标识主键字段, result标签,用于普通字段。这可能涉及到MyBatis的缓存机制,比如一级缓存和二级缓存,因为主键可能用于唯一标识记录,影响缓存的效率。另外,在关联查询或者嵌套结果的时候,主键可能起到关键作用,比如一对一或一对多的映射。<resultMapid="tMap"type="teacher"><idcolumn="t_id"property="tId"/><resultcolumn="t_name"property="tName"/></resultMap><selectid="queryByIdd"resultMap="tMap">select * from teacher where t_id = #{tId}</select></mapper>packagecom.atguigu.test;importcom.atguigu.mapper.EmployeeMapper;importcom.atguigu.pojo.Employee;importorg.apache.ibatis.io.Resources;importorg.apache.ibatis.session.SqlSession;importorg.apache.ibatis.session.SqlSessionFactory;importorg.apache.ibatis.session.SqlSessionFactoryBuilder;importorg.junit.jupiter.api.Test;importjava.io.IOException;importjava.io.InputStream;publicclassMybatisTest{@Testpublicvoidtest_01()throwsIOException{1、读取外部配置文件(mybatis-config.xml)使用MyBatis提供的Resources类,读取名为mybatis-config.xml的配置文件。InputStreamips=Resources.getResourceAsStream("mybatis-config.xml");2、创建sqlSessionFactory 使用SqlSessionFactoryBuilder根据配置文件构建SqlSessionFactory对象。SqlSessionFactorysqlSessionFactory=newSqlSessionFactoryBuilder().build(ips);3、根据sqlSessionFactory创建sqlSession对象【自动开启JDBC】【自动开启事务,但不会自动提交事务,需要sqlSession.commit()手动开启】 或者使用 sqlSessionFactory.openSession(true)【会自动开启事务,自动提交事务,不需要写sqlSession.commit()】SqlSessionsqlSession=sqlSessionFactory.openSession();4、使用SqlSession的getMapper()方法,获取EmployeeMapper接口的代理对象,并且调用具体的SQL方法EmployeeMappermapper=sqlSession.getMapper(EmployeeMapper.class);调用EmployeeMapper接口的queryById()方法,传入参数1,执行查询操作,并将结果赋值给employee对象。Employeeemployee=mapper.queryById(1);System.out.println(employee);// 创建Employee对象(此时id为null)Employeeemployee=newEmployee();employee.setName("李四");employee.setPhone("13900139000");System.out.println("插入前的Employee:"+employee);// Employee{id=null, name='李四', phone='13900139000'}// 执行插入操作intaffectRows=mapper.insertUser(employee);System.out.println("插入影响的行数:"+affectRows);// 输出:1// 关键:获取回显的自增主键(此时employee的id已被赋值)System.out.println("插入后的Employee:"+employee);// 输出:Employee{id=1, name='李四', phone='13900139000'}(id是数据库自增的实际值)"主键回显本质:自增 id 会赋值到传入的实体类对象中,方法返回值仅代表插入影响的行数"// 因为在 EmployeeMapper.xml 中使用了 selectkey 让mybatis帮我们维护主键,所以这里可以注掉了// 自己维护主键,使用uuid,这里replaceAll操作,是去掉uuid的中划线// String id = UUID.randomUUID().toString().replaceAll("-", "");// employee.settId(id);// insertEmpMap(Map data) 的例子---------------------------// 构建Map:key必须和SQL中的#{name}、#{phone}完全一致Map<String,Object>userMap=newHashMap<>();userMap.put("name","张三");// key="name" 对应 SQL中的 #{name}userMap.put("phone","13800138000");// key="phone" 对应 SQL中的 #{phone}// 调用方法插入数据intaffectedRows=mapper.insertEmpMap(userMap);System.out.println("插入成功,影响行数:"+affectedRows);// insertEmpMap(Map data) 的例子---------------------------// Map<String, Object> selectEmpNameAndMaxSalary() 的例子------------------------Map<String,Object>resultMap=mapper.selectEmpNameAndMaxSalary();System.out.println("姓名:"+resultMap.get("name"));// 输出:张三System.out.println("薪资:"+resultMap.get("salary"));// 输出:15000.00System.out.println("平均薪资:"+resultMap.get("avgSalary"));// 输出:12500.00// Map<String, Object> selectEmpNameAndMaxSalary() 的例子------------------------// List<Map<String, Object>> selectAllEmpWithMaxSalary();// 返回 List<Map<String, Object>>List<Map<String,Object>>resultList=mapper.selectAllEmpWithMaxSalary();for(Map<String,Object>map:resultList){System.out.println("姓名:"+map.get("name")+",薪资:"+map.get("salary"));}// 输出:// 姓名:张三,薪资:15000.00// 姓名:王五,薪资:15000.00// 创建Employee对象(仅设置name,id为null)Employeeemployee=newEmployee();employee.setName("张三");System.out.println("插入前的Employee:"+employee);// Employee{id='null', name='张三'}// 执行插入操作intaffectRows=mapper.insertEmployee(employee);System.out.println("插入影响的行数:"+affectRows);// 输出:1// 关键:主键已自动回显到employee的id属性中System.out.println("插入后的Employee:"+employee);// 输出示例:Employee{id='f85e9d786b5a4c3b8d7e6f5a4b3c2d1e', name='张三'}"插入后,主键会自动赋值到传入的Employee对象中,无需手动处理。"5、提交事务(非DQL)和释放资源 sqlSession.commit():提交事务,但是在这个查询操作的上下文中,commit是不必要的,因为查询操作不需要提交事务。 通常,只有DML(如INSERT、UPDATE、DELETE)操作才需要提交事务。 sqlSession.commit();sqlSession.close();}}