1.多个参数811.1需求:通过name和sex查询81test中的comm.powernode.mybatis.teststudentmapertest类testelectbynamendsex
//多个参数 81 @Test public void testSelectByNameAndSex(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<Student> students = mapper.selectByNameAndSex(张三), '男'); students.forEach(student -> System.out.println(student)); sqlSession.close(); }
StudentMapper.xml
<select id="selectByNameAndSex" resultType="Student"> <!--select * from t_student where name = #{name} and sex = #{age}--> <!--select * from t_student where name = #{arg0} and sex = #{arg1}--> <!--select * from t_student where name = #{param1} and sex = #{param2}--> select * from t_student where name = #{arg0} and sex = #{param2} </select>
1.2通过测试可以看到:81
<select id="selectByNameAndSex" resultType="Student"> select * from t_student where name = #{name} and sex = #{age} </select>
异常信息描述:name参数找不到,但是⽤参数包括[arg1、arg0、param1、param2]
修改Studentmapper.xml配置⽂件:尝试使⽤参数[arg1,arg0,param1,param2]
<select id="selectByNameAndSex" resultType="Student"> select * from t_student where name = #{arg0} and sex = #{arg1}</select>
1.3根据name和sex查询Student信息得出结论
*如果是多个参数,mybatis框架底层是怎么做的?
*Mybatis框架将自动创建Map集合。Map集合以这种方式存储参数:
*map.put(arg0”,name);
*map.put(arg1”,sex);
或者
*map.put(param1)name);
*map.put(param2”,sex);
arg0是第⼀个参数
第一个是param1⼀个参数
arg1是第⼆个参数
param2是第一个⼆个参数
1.3.1注意81在低版本的mybatis中,使用#{0}和#{1},以及#{2}...
在高版mybatis中,使用的是:
#{arg0}
#{arg1}
#{arg2}
#{arg3}
#{arg4}
#{param1}
#{param2}
#{param3}
#{param4}
2.参数Param注释82可以不⽤arg0arg1param1param2?这个map集合的key,我们⾃定义可以吗?当然可以。使。⽤@Param注释即可。这样可以增强可读性。
/** * Param注释。 82 * * 实现mybatis框架底层的原理: * map.put("name", name); * map.put("sex", sex); * * @param name * @param sex * @return */ List<Student> selectbynamendsex2(@Param("name") String name, @Param("sex") Character sex);
2.1要求:根据name和age查询82test中的comm.powernode.mybatis.teststudentmapertest类testelectbynamendsex2
///参数注释Param 82 @Test public void Testselectbynamendsex2(){ SqlSession sqlSession = SqlSessionUtil.openSession(); // 实际上,mapper指向代理对象 StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // mapper是代理对象 // selectbynamendsex2代理方法 List<Student> students = mapper.selectByNameAndSex2(“张三” '男'); students.forEach(student -> System.out.println(student)); sqlSession.close(); }
StudentMapper.xml
<select id=“selectbynameAndsex2” resultType="Student"> <!--使用@Param注释后,arg0和arg1失效--> <!--select * from t_student where name = #{arg0} and sex = #{arg1}--> <!--使用@Param注释后,param1和param2也可以使用--> <!--select * from t_student where name = #{param1} and sex = #{param2}--> select * from t_student where name = #{name} and sex = #{sex} </select>
2.2注意82
使用@Param注释后,arg0和arg1失效
select*fromt_studentwherename=#{arg0}andsex=#{arg1}
使用@Param注释后,param1和param2也可以使用
select*fromt_studentwherename=#{param1}andsex=#{param2}
3.Param源码分析833 4.总代码main中com.powernode.mybatis.mapperStudentMapper
package com.powernode.mybatis.mapper;import com.powernode.mybatis.pojo.Student;import org.apache.ibatis.annotations.Param;import java.util.Date;import java.util.List;import java.util.Map;//处理mybatis参数 76public interface StudentMapper { /** * Param注释。 82 * * 实现mybatis框架底层的原理: * map.put("name", name); * map.put("sex", sex); * * @param name * @param sex * @return */ List<Student> selectbynamendsex2(@Param("name") String name, @Param("sex") Character sex); /** * 这是多参数。 81 * Student信息根据name和sex查询。 81 * Student信息根据name和sex查询。 * 如果是多个参数,mybatis框架底层是怎么做的? * Mybatis框架将自动创建Map集合。Map集合以这种方式存储参数: * map.put(arg0”, name); * map.put(arg1”, sex); * map.put(param1) name); * map.put(param2”, sex); * * @param name * @param sex * @return */ List<Student> selectByNameAndSex(String name, Character sex); /** * 通过POJO参数保存学生信息。Student是单个参数。Student是单个参数。但不是简单的类型。 80 * @param student * @return */ int insertStudentByPOJO(Student student); /** * 通过Map参数保存学生信息。以下是单个参数。但是参数的类型并不简单。是Map集合。79 * @param map * @return */ int insertStudentByMap(Map<String, Object> map); /** * 接口中只有一个参数(单个参数),参数的数据类型都是简单类型。 77-78 * 根据id查询、name查询、birth查询、sex查询 */ List<Student> selectById(Long id); List<Student> selectByName(String name); List<Student> selectByBirth(Date birth); List<Student> selectBySex(Character sex);}
com在test中.powernode.mybatis.testStudentMapperTest类别
package com.powernode.mybatis.test;//处理mybatis参数 76import com.powernode.mybatis.mapper.StudentMapper;import com.powernode.mybatis.pojo.Student;import com.powernode.mybatis.utils.SqlSessionUtil;import org.apache.ibatis.session.SqlSession;import org.junit.Test;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Map;/** * 代理模式: * 代理对象 链家 * 代理方法 找房子 * 目标对象 我 * 目标方法 找房子 */public class StudentMapperTest { ///参数注释Param 82 @Test public void Testselectbynamendsex2(){ SqlSession sqlSession = SqlSessionUtil.openSession(); // 实际上,mapper指向代理对象 StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // mapper是代理对象 // selectbynamendsex2代理方法 List<Student> students = mapper.selectByNameAndSex2(“张三” '男'); students.forEach(student -> System.out.println(student)); sqlSession.close(); } //多个参数 81 @Test public void testSelectByNameAndSex(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<Student> students = mapper.selectByNameAndSex(张三), '男'); students.forEach(student -> System.out.println(student)); sqlSession.close(); } // POJO对象参数 80 @Test public void testInsertStudentByPOJO(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // POJO对象 Student student = new Student(); student.setName(张飞); student.setAge(50); student.setSex('女'); student.setBirth(new Date()); student.setHeight(10.0); mapper.insertStudentByPOJO(student); sqlSession.commit(); sqlSession.close(); } ///参数值Map集合 79 @Test public void testInsertStudentByMap(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Map<String,Object> map = new HashMap<>(); map.put(“姓名”, "赵六"); map.put(年龄”, 20); map.put(身高”, 1.81); map.put(性别”, '男'); map.put(“生日”, new Date()); mapper.insertStudentByMap(map); sqlSession.commit(); sqlSession.close(); } //当界面中的方法只有一个参数(单个参数),而且参数的数据类型都是简单类型。 78 //根据sex查询 @Test public void testSelectBySex(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // char --> Character Character sex = Character.valueOf('男'); List<Student> students = mapper.selectBySex(sex); students.forEach(student -> System.out.println(student)); sqlSession.close(); } //当界面中的方法只有一个参数(单个参数),而且参数的数据类型都是简单类型。 78 //根据birth查询 // java.util.Date java.sql.Date,它们都是简单的类型。 @Test public void testSelectByBirth() throws Exception{ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); //定义日期格式 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); ///按日期格式写日期(将“1980-10-11”字符串转换为日期类型) Date birth = sdf.parse("1980-10-11"); List<Student> students = mapper.selectByBirth(birth); students.forEach(student -> System.out.println(student)); sqlSession.close(); } //当界面中的方法只有一个参数(单个参数),而且参数的数据类型都是简单类型。 78 //根据name查询 @Test public void testSelectByName(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<Student> students = mapper.selectByName(李四); students.forEach(student -> System.out.println(student)); sqlSession.close(); } //当界面中的方法只有一个参数(单个参数),而且参数的数据类型都是简单类型。 77 //根据id查询 @Test public void testSelectById(){ SqlSession sqlSession = SqlSessionUtil.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<Student> students = mapper.selectById(1L); students.forEach(student -> System.out.println(student)); sqlSession.close(); }}
main中com.powernode.mybatis.utils工具类Utils
package com.powernode.mybatis.utils;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;/** * MyBatis工具 * @author 动力节点 * @version 1.0 * @since 1.0 */public class SqlSessionUtil { private SqlSessionUtil(){} private static SqlSessionFactory sqlSessionFactory; static { try { sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")); } catch (IOException e) { throw new RuntimeException(e); } } // 全局的,对于服务器级别,可以在服务器中定义一个。 // 为何将SqlSession对象放入Threadlocal? // 为什么要把SqlSession对象放在Threadlocal中?确保一个线程对应于SqlSession。 private static ThreadLocal<SqlSession> local = new ThreadLocal<>(); /** * 获取会话对象。 * @return 会话对象 */ public static SqlSession openSession(){ SqlSession sqlSession = local.get(); if (sqlSession == null) { sqlSession = sqlSessionFactory.openSession(); // 将sqlsession对象绑定到当前线程。 local.set(sqlSession); } return sqlSession; } /** * 关闭SqlSession对象(从当前线程中删除SqlSession对象。) * @param sqlSession */ public static void close(SqlSession sqlSession){ if (sqlSession != null) { sqlSession.close(); // 注意移除SqlSession对象与当前线程的绑定关系。= null) { sqlSession.close(); // 注意移除SqlSession对象与当前线程的绑定关系。 // 因为Tomcat服务器支持线程池。也就是说,用过的线程对象T1下次可能会用到这个T1线程。 local.remove(); } }}
main中com.powernode.mybatis.pojoStudent
package com.powernode.mybatis.pojo;import java.util.Date;//pojo 76public class Student { private Long id; private String name; private Integer age; private Double height; private Date birth; private Character sex; @Override public String () { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", height=" + height + ", birth=" + birth + ", sex=" + sex + '}'; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Double getHeight() { return height; } public void setHeight(Double height) { this.height = height; } public Date getBirth() { return birth; } public void setBirth(Date birth) { this.birth = birth; } public Character getSex() { return sex; } public void setSex(Character sex) { this.sex = sex; } public Student(Long id, String name, Integer age, Double height, Date birth, Character sex) { this.id = id; this.name = name; this.age = age; this.height = height; this.birth = birth; this.sex = sex; } public Student() { }}
StudentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.powernode.mybatis.mapper.StudentMapper"> <select id=“selectbynameAndsex2” resultType="Student"> <!--使用@Param注释后,arg0和arg1失效--> <!--使用@Param注释后,arg0和arg1失效--> <!--select * from t_student where name = #{arg0} and sex = #{arg1}--> <!--使用@Param注释后,param1和param2也可以使用--> <!--select * from t_student where name = #{param1} and sex = #{param2}--> select * from t_student where name = #{name} and sex = #{sex} </select> <!-- 注:在低版mybatis中,使用的是:#{0}和#{1},以及#{2}... 在高版mybatis中,使用的是: #{arg0} #{arg1} #{arg2} #{arg3} #{arg4} #{param1} #{param2} #{param3} #{param4} --> <select id="selectByNameAndSex" resultType="Student"> <!--select * from t_student where name = #{name} and sex = #{age}--> <!--select * from t_student where name = #{arg0} and sex = #{arg1}--> <!--select * from t_student where name = #{param1} and sex = #{param2}--> select * from t_student where name = #{arg0} and sex = #{param2} </select> <!--<insert id="insertStudentByPOJO" parameterType="student">--> <insert id="insertStudentByPOJO"> insert into t_student(id,name,age,sex,birth,height) values(null,#{name},#{age},#{sex},#{birth},#{height}) </insert> <!--<insert id="insertStudentByMap" parameterType="map">--> <insert id="insertStudentByMap"> insert into t_student(id,name,age,sex,birth,height) values(null,#{姓名},#{年龄},#{性别},#{生日},#{身高}) </insert> <!-- List<Student> selectById(Long id); List<Student> selectByName(String name); List<Student> selectByBirth(Date birth); List<Student> selectBySex(Character sex); parametertype属性的作用: 告诉mybatis框架,这种方法的参数类型是什么? mybatis框架本身就有一种类型的自动推断机制,所以在大多数情况下,parametertype属性是可以省略的。 mybatis框架本身就有一种类型的自动推断机制,所以在大多数情况下,parametertype属性是可以省略的。 SQL语句最终是这样的: select * from t_student where id = ? JDBC代码必须给出传值的。 怎么传值?ps.setXxx(几个问号, 传什么值); ps.setLong(1, 1L); ps.setString(1, "zhangsan"); ps.setDate(1, new Date()); ps.setInt(1, 100); ... 根据parametertype属性的值,mybatis底层调用setxx的方法。 注:mybatis框架实际上内置了许多别名。 注:mybatis框架实际上内置了许多别名。请参考开发手册。 --> <select id="selectById" resultType="Student" parameterType="long"> select * from t_student where id = #{id} </select> <select id="selectByName" resultType="student"> select * from t_student where name = #{name, javaType=String, jdbcType=VARCHAR} </select> <select id="selectByBirth" resultType="student"> select * from t_student where birth = #{birth} </select> <select id="selectBySex" resultType="student"> select * from t_student where sex = #{sex} </select></mapper>
pom.xml
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.powernode</groupId> <artifactId>course16</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.10</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.11</version> </dependency> </dependencies> <properties> <!-- jdk版本用于编译代码--> <maven.compiler.source>1.8</maven.compiler.source> <!-- 使用jdk版本的操作程序--> <maven.compiler.target>1.8</maven.compiler.target> </properties></project>
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration> <properties resource="jdbc.properties"/> <typeAliases> <package name="com.powernode.mybatis.pojo"/> </typeAliases> <environments default="dev"> <environment id="dev"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <mappers> <package name="com.powernode.mybatis.mapper"/> </mappers></configuration>
jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/powernodejdbc.username=rootjdbc.password=lzl
logback.xml
<?xml version="1.0" encoding="UTF-8"?><configuration debug="false"> <!-- 控制台输出 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:从左显示5个字符宽度%msg:日志消息,%n是换行符--> <pattern>[%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <!--mybatis log configure--> <logger name="com.apache.ibatis" level="TRACE"/> <logger name="java.sql.Connection" level="DEBUG"/> <logger name="java.sql.Statement" level="DEBUG"/> <logger name="java.sql.PreparedStatement" level="DEBUG"/> <!-- 日志输出水平,logback日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR --> <root level="DEBUG"> <appender-ref ref="STDOUT"/> <appender-ref ref="FILE"/> </root></configuration>