mybatis—动态代理getMapper、传入参数、输出结果、动态sql以及扩展的PageHelper分页

传统dao执行数据库方法

public class TestMyBatis {
    @Test
    public void testSelectStduents(){
        StudentDao student=new StudentDaoImpl();
        List<Student> students = student.selectStudents();
        
        students.forEach(student1 -> System.out.println(student1));
    }
    @Test
    public void TestInsertStudent(){
        StudentDao dao=new StudentDaoImpl();
        Student student=new Student();
        student.setId(1004);
        student.setName("ccl");
        student.setEmail("ccl@qq.com");
        student.setAge(20);
        dao.insertStudent(student);
    }
}

List<Student> students = student.selectStudents(); 调用
1、dao对象,类型是StudentDao,全限定名称是:com.hr.qjb.dao.StudentDao

全限定名称,和 namespace是一样的

2、方法名称,selectStudents,这个方法就是mapper文件中的id值, selectStudents

3、通过dao中方法的返回值也可以确定MyBatis要调用的SqlSession的方法

如果返回值是List,调用的是SqlSession.selectList()方法

如果返回值是int , 或是非List的,看mapper文件中的标签是<insert>,<update>就会调用

sqlSession的insert、update等方法

mybatis的动态代理:mybatis根据dao的方法调用,获取执行sql语句的信息

mybatis根据你的dao接口,创建出一个dao接口的实现类,并创建这个类的对象。

完成SqlSession调用方法,访问数据库。

动态代理getMapper

使用SqlSession.getMapper(dao接口.class) 获取这个dao接口的对象

public class TestMyBatis {
    @Test
    public void testSelectStduents(){
        /*
        * 使用mybatis的动态代理机制,使用SqlSession.getMapper(dao接口)
        * getMapper 能获取dao接口对于的实现类对象
        *
        * */
        SqlSession sqlSession= MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //调用dao的方法,执行数据库的操作
        List<Student> students = dao.selectStudents();
        students.forEach(student -> System.out.println(student));
    }

传统dao执行数据库方法,需要接口的实现类支撑,但是使用动态代理以后,可以通过getMapper去代替接口实现类

通过执行System.out.println(dao.getClass().getName());查看dao的类型发现

com.sun.proxy.$Proxy2

可以看到用的就是动态代理

深入理解参数

传入一个简单类型参数

如果想要在进行数据库操作的时候加入参数

传入参数:从Java代码中把数据传入到mapper文件的sql语句中。

1、parameterType:写在mapper文件中的要给属性。表示dao接口中方法的参数的数据类型,

​ 例如StudentDao接口

​ public Student selectStudent ById(Integer id)

parameterType:用来表示dao接口方法参数的数据类型

parameterType它的值是Java的数据类型全限定名称或者是mybatis定义的别名

​ 例如:parameterType=“java.lang.Integer”

​ parameterType=“int”

注意:parameterType不是强制的,mybatis通过反射能够发现接口参数的数类型

​ 所以可以没有。一般我们不写

在mapper文件(dao接口)获取简单类型的一个参数的值,使用#{任意字符}

例如

mapper类

    <select id="selectStudentById" parameterType="java.lang.Integer" resultType="com.hr.qjb.domain.Student">
        select id , name ,email, age from student where id=#{id}
    </select>

测试类

public void testSelectStduents(){
        SqlSession sqlSession= MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
    	//传过去参数
        Student student = dao.selectStudentById(1004);
        System.out.println(student);
    }

接口类

public interface StudentDao {
    public Student selectStudentById(Integer id);
}

使用#{}之后,mybatis执行sql是使用jdbc中的PreparedStatement对象

由mybatis执行下面的代码:
1、mybatis创建Connection,PreparedStatement对象

​ String sql=”select id, name ,email,age from student where id=?“

PreparedStatement pst = conn.preparedStatement(sql);

​ pst.setInt(1,1001);

2、执行sql封装为resultType=”com.hr.qjb.domain.Student“这个对象

​ ResultSet rs = ps.executeQuery();

​ Student student = null;

​ while(rs.next()){

​ //从数据库取表的一行数据,存到一个Java对象属性中

​ Student student = new Student();

​ student.setId(rs.getInt(“id”));

​ student.setName(rs.getString(“name”));

​ student.setEmail(rs.getString(“email”));

​ student.setAge(rs.getString(“age”));

}

return student; // 给了dao方法调用的返回值

传入多个参数

使用@Param

当Dao接口方法多个参数,需要通过名称使用参数。在方法形参前面加入@Param(“自定义参数名”),

mapper文件使用#{自定义参数名}

例如定义 List<Student>selectStudent(@Param(“personName”) String name ){ … }

​ mapper 文件 select * from student where name = #{ personName}

接口方法:
List<Student> selectMultiParam(@Param(“personName”) String name ,@Param(“personAge”) int age);

mapper文件:

<select id ="selectMultiParam" resultType="com.hr.qjb.domain.Student">

​ select id , name, email,age from student where name = #{personName} or age = #{personAge}

</select>

实例代码

StudentDao

    //多个参数:命名参数,在形参定义的前面加入@Param("自定义参数名称")
    List<Student> selectMultiParam(@Param("myname") String name ,
                                   @Param("myage") Integer age);

StudentDao.xml

<!--    多个参数,使用@Param命名-->
    <select id="selectMultiParam" resultType="com.hr.qjb.domain.Student">
        select id , name ,email, age from student where name=#{myname} or age=#{myage}
    </select>

测试类

    @Test
    public void testSelectMultiParam(){
        SqlSession sqlSession=MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        List<Student> students = dao.selectMultiParam("ccl", 20);
        students.forEach(student -> System.out.println(student));
        sqlSession.close();
    }
使用对象

可以新建一个类,也可以使用已有的类,只要xml文件中#{}花括号中的参数与实体类的属性名对应就可以

studentDao.xml文件中:

多个参数,使用Java对象的属性值,作为参数实际值
使用对象的语法:#{属性名,javaType=类型名称,jdbcType=数据类型} 很少用
JavaType:指Java中的属性数据类型。
jdbcType:在数据库中的数据类型
例如:#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}

<select id="selectMultiObject" resultType="com.hr.qjb.domain.Student">
        select id , name ,email, age from student where
        name=#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
        or age=#{paramAge,javaType=java.lang.Integer,jdbcType=INTEGER}
    </select>

​ 上面是最为完整的,我们一般用简化的
​ 简化方式:#{属性名} , JavaType,jdbcType的值mybatis反射能获取,不同提供

<select id="selectMultiObject" resultType="com.hr.qjb.domain.Student">
        select id , name ,email, age from student where
        name=#{paramName} or  age=#{paramAge}
    </select>

vo:value object,放一些存储数据的类。比如说 提交请求参数, name, age现在想把name,age 传给一个service类。

vo:view object,从servlet把数据返回给浏览器使用的类,表示显示结果的类。

pojo:普通的有set,get方法的Java类,普通的Java对象

entity(domain域):实体类,和数据库中的表对应的类

使用位置(了解)

使用位置的话是通过接口中方法传递过来的参数从左往右计算,从零开始数,

例如:

List<Student> selectMultiPosition(String name , Integer age);

想要进行查询的话就是

<select id="selectMultiPosition" resultType="com.hr.qjb.domain.Student">
        select id , name ,email, age from student where
        name=#{arg0} or  age=#{arg1}
    </select>

在mybatis 3.4之前 , 使用#{0} ,#{1} 表示

在mybatis3.4之后,使用#{arg0} , #{arg1}

使用map(了解)
List<Student> selectMultiMap(Map<String,Object> map);

使用Map,使用语法#{map的key}

xml

    <select id="selectMultiMap" resultType="com.hr.qjb.domain.Student">
        select id , name , email ,age from student where name=#{name} or age=#{age}
    </select>

测试

    @Test
    public void testSelectMultiMap(){
        //获取SqlSession对象
        SqlSession sqlSession= MyBatisUtils.getSqlSession();
        //通过getMapper方法,得到dao对象
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //因为要传一个map,所以创建要给map
        Map<String ,Object> map =new HashMap<>();
        map.put("name","ccl");
        map.put("age",20);
        //通过传过去的map调用方法,得到结果集,并且打印
        List<Student> students = dao.selectMultiMap(map);
        students.forEach(student -> System.out.println(student));
    }

占位符

$和#的区别

select id , name ,email, age from student where id=#{id}

#的结果: select id , name ,email, age from student where id=?

select id , name ,email, age from student where id=${id}

$的结果:select id , name ,email, age from student where id=1004

String sql="select id , name ,email, age from student where id = "+“1004”;

使用Statement对象执行sql,效率比PreparedStatement低。

1、#使用?在sql语句中能做站位的,使用PreparedStatement执行sql,效率高

2、#能够避免sql注入,更安全

3、$不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低

4、$有sql注入的风险,缺乏安全性

5、$:可以替换表名或者列名

#:占位符,告诉mybatis使用实际的参数值代替。并使用PrepareStatement对象执行sql语句。#{…}代替sql语句的"?"。这样做更安全,更迅速,通常也是首选做法,

mappper文件

    <select id="selectStudentById" parameterType="java.lang.Integer" resultType="com.hr.qjb.domain.Student">
        select id , name ,email, age from student where id=#{id}
    </select>

转为MyBatis的执行是:

String sql="select id , name ,email , age from student where id=?";
    PreparedStatement ps= conn.prepareStatement(sql);
ps.setInt(1,1005);

解释:

where id = ? 就是where id = #{id}

ps.setInt(1,1005) , 1005 会替换掉 #{id}

$

$ 字符串替换,告诉mybatis 使用 包 含 的 “ 字 符 串 ” 替 换 所 在 位 置 。 使 用 S t a t e m e n t 把 s q l 语 句 和 包含的“字符串” 替换所在位置。使用 Statement 把sql 语句和 使Statementsql{}的内容连接起来,主要用在替换表名,列名,不同列排序等操作。

: 可 以 替 换 表 名 或 者 列 名 , 你 能 确 定 数 据 是 安 全 的 , 可 以 使 用 :可以替换表名或者列名,你能确定数据是安全的,可以使用 :使

MyBatis输出结果

resultType

resultType:结果类型,指sql语句执行完毕后,数据转为的Java对象。|java 类型是任意的。

resultType结果类型它的值:1、类型的全限定名称, 2、类型的别名, 例如java.lang.Integer别名为int

处理方式:

1、mybatis执行sql语句,然后mybatis调用类的无参数构造方法,创建对象

2、mybatis把ResultSet指定列值赋给同名的属性。

<select id="selectStudentById" parameterType="java.lang.Integer" resultType="com.hr.qjb.domain.Student">
    select id , name ,email, age from student
</select>

对等的jdbc

ResultSet rs =executeQuery(" select id, name ,email ,age from student")

while (rs.next()){

​ Student student =new Student();

​ student.setId(rs.getInt(“id”));

​ student.setname(rs.getString(“name”));

​ student.setEamil(rs.getSring(eamil));

​ student.setInt(rs.getInt(“age”));

}

返回对象类型
<select id="selectStudentReturnViewStudent" resultType="com.hr.qjb.vo.ViewStudent">
    select id ,name  from student where id=#{sid}
</select>

不管查询多少列,他只会存储类中有的属性

返回简单类型

全限定名称

    <select id="countStudent" resultType="java.lang.Integer">
        select count(*) from student
    </select>

或别名

    <select id="countStudent" resultType="int">
        select count(*) from student
    </select>

定义自定义类型的别名

1、在mybatis主配置文件中定义,<typeAlias>定义别名

2、可以在resultType中使用自定义别名

第一种方式:
可以指定一个类型 一个自定义别名
type:自定义类型的全限定名称
alias:别名(短小,容易记忆的)

例如

<typeAlias type="com.hr.qjb.vo.ViewStudent" alias="vstu"/>
<typeAlias type="com.hr.qjb.domain.Student" alias="stu"/>

alias的值就是类的别名

第二种方式
<package> name是包名,这个包中的所有类,类名就是别名(类名不区分大小写)

<package name="com.hr.qjb.domain"/>
<package name="com.hr.qjb.vo"/>

定义路径下的类的类名就是每个类的别名

返回Map

1、列名是map的key,列值是value

2、只能最多返回一行记录,多余一行是错误

<select id="selectMapById" resultType="map">
    select id, name from student where id=#{stuid}
</select>

resultMap

resultMap:结果映射,指定列名和Java对象的属性对应关系。

1、你自定义列值赋给哪个属性

2、当你的列名和属性名不一样时,一定使用resultMap

resultMap使用步骤

xml

使用resultMap
1、先定义resultMap
2、在select标签,使用resultMap来引用定义的

定义resultMap
id:是自定义的名称,表示你定义的这个resultMap
type:Java类型的全限定名称

<resultMap id="studentMap" type="com.hr.qjb.domain.Student">

主键列,使用id标签
column:列名
property:Java类型的属性名

<id column="id" property="id" />

非主键列,使用result

<result column="name" property="email"/>
        <result column="email" property="name"/>
        <result column="age" property="age"/>

如果遇到表中的列名跟类中的属性名不一致时,可以通过resultMap解决, column是表中列名,property是Java类种属性的名字

注意:resultMap和resultType不要一起用,二选一

这是解决列名和属性名不一样的第一种方式

第二种方式

resultType的默认原则是 同名的列值赋值给同名的属性,使用列别名(Java对象的属性名)解决

在sql语句上进行解决

原来:select id , name , email , age from student

为了保持跟Java类中的属性名一样,将sql语句改为

select id as stuid, name as stuname, email as stuemail ,age as stuage from student

解决!

Like模糊查询

第一个模糊查询,在Java代码中 指定like的内容

xml

<select id="selectLikeOne" resultType="com.hr.qjb.domain.Student">
        select id, name , email , age from student  where name like #{name}
    </select>

在测试传值的时候将模糊查询的数据在Java代码中拼接好,传过去

@Test
    public  void  testSelectLikeOne(){
        SqlSession sqlSession=MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //准备好like的内容
        String name ="%磊%";
        List<Student> lists = dao.selectLikeOne(name);
        lists.forEach(student -> System.out.println(student));
    }

第二种方式:在mapper文件中来拼接like内容

xml

<select id="selectLikeTwo" resultType="com.hr.qjb.domain.Student">
        select id , name ,email ,age from student where name like "%" #{name} "%"

    </select>

在mapper文件中写好模糊数据的格式,只需要传一个要查的文字过来

 @Test
    public  void  testSelectLikeTwo(){
        SqlSession sqlSession=MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        List<Student> lists = dao.selectLikeTwo("磊");
        lists.forEach(student -> System.out.println(student));
    }

相比之下,第一个方法更加灵活,好理解,如果需要改模糊查询的方法,比如说要李姓:李%。等等再第一种方法里改Java代码的字符串即可,第二个问题要去改动mapper文件

动态sql

动态sql:sql的内容是变化的,可以根据条件获取到不同的sql语句

​ 主要是where部分发生变化。

动态sql的实现,使用的是mybatis提供的标签,<if>,<where>,<foreach>

<if>

1、<if>是判断条件的,

​ 语法<if test="判断Java对象的属性值">

​ 部分sql语句

</if>

<where>

2、<where>用来包含 多个<if>的,当多个if有一个成立的,<where>会自动增加一个where关键字,并去掉if种多余的and,or等

<foreach>

3、<foreach>循环Java中的数组,list集合的。主要用在sql的in语句中。

例如:学生id是 1001、1002、1003的三个学生

sql:select * from student where id in (1001,1002,1003);

语法规则

<foreach collection="" item="" open="" close="" separator="">
	#{xxx}
</foreach>

collection:用来表示接口中方法参数的类型,如果是数组使用array ,如果是list 集合使用list

item:自定义的,表示数组和集合成员的变量

open:循环开始时的字符

close:循环结束时的字符

separator:集合成员之间的分隔符

集合中是简单类型

<foreach collection="list" item="myid" open="(" close=")" separator=",">
        #{myid}
</foreach>

集合中是引用类型

<foreach collection="list" item="stu" open="(" close=")" separator=",">
                  #{stu.id}
        </foreach>

separator、close、open只是为了拼接的话更加方便,也可以去掉,通过自己的思维,加上自己的拼接,完成要达到的目的

例如:去掉open、close,可以手动加载循环前后

<select id="selectForeachTwo" resultType="com.hr.qjb.domain.Student">
        select * from student where id in (
        <foreach collection="list" item="stu" separator=",">
                  #{stu.id}
        </foreach>
    )
    </select>

这样拼接的话也可以

sql代码片段

sql代码片段,就是复用一些语法

步骤

1、先使用<sql id="自定义名称唯一"> sql语句,表名,字段等 </sql>

2、再使用,<include refid="id的值" /> 复用

例如:

<sql id="studentSql" >
    select id ,name ,email ,age from student
</sql>

将sql有可能复用的语句定义为id为studentSql

再用的话可以用

<select id="selectStudentWhere" resultType="com.hr.qjb.domain.Student">
    		<!--代码片段的调用-->
        <include refid="studentSql"/>
    <where>
        <if test="name !=null and name !=''">
            name=#{name}
        </if>
        <if test="age > 0">
            and age > #{age}
        </if>
    </where>
    </select>

mybatis.xml

 <environments default="mydev">
        <!--environment:一个数据库信息的配置,环境
			id:一个唯一值,自定义,表示环境的名称-->
        <environment id="mydev">
<!--           transactionManager:mybatis提交事务,回滚事务的方式
                type:事务的处理的类型
                1)JDBC:表示mybatis底层是调用JDBC中的Connection对象的,commit,rollback
                2)MANAGED:把mybatis的事务处理委托给其他的容器(一个服务器软件,一个框架(spring))-->
            <transactionManager type="JDBC"/>
<!--          dataSource:表示数据源,Java的体系中,规定实现了javax.sql.DataSource接口的都是数据源.
                         数据源表示Connection对象的
               type:指定数据源的类型
                     1)POOLED:使用连接池,mybatis会创建PooledDataSource类
                     2)UPOOLED:不适用连接池,在每次执行sql语句,先创建连接,实行sql,在关闭连接
                                mybatis会创建一个UnPooledDataSource, 管理Connection对象的使用
                     3)JNDI:Java命名和目录服务(windows注册表)
               -->
            <dataSource type="POOLED">
                <!--driver,user,username,password 是固定的,不能自定义-->
                <!--数据库的驱动类名-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!--连接数据库的url字符串-->
                <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
                <!--访问数据库的用户名称-->
                <property name="username" value="root"/>
                <!--访问数据库的密码-->
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

属性配置文件

1、数据库的属性配置文件:把数据库的连接信息,放到单独文件中。和mybatis主配置文件分开。

​ 目的是便于修改,保存,处理多个数据库的信息。

​ 1、在resources目录中定义一个属性配置文件。 xxxx.properties , 例如 jdbc.propertes

​ 在属性配置文件中,定义数据,格式是key=value

​ key:一般使用 做多级目录的。

​ 例如 jdbc.mysql.driver , jdbc.driver ,

​ jdbc.driver=com.mysql.jdbc.Driver

​ jdbc.url=jdbc:mysql//…

​ jdbc.username=root

​ jdbc.password=123456

​ 2、在mybatis的主配置文件,使用<property>指定文件的位置

​ 在需要使用值的地方,${key}

jdbc.properties文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm
jdbc.username=root
jdbc.password=123456

在mybatis.xml文件中需要加入读取jdbc.properties的语句

<properties resource="jdbc.properties"/>

mybatis.xml中使用package sql映射文件方法

<!--        第一种方式:有一个,写一个语句,来指定位置-->
       <mapper resource="com\hr\qjb\dao\StudentDao.xml"/>
<!--        <mapper resource="com\hr\qjb\dao\OrderDao.xml"/>-->

<!--        第二种方式:指定包名
               name:xml文件(mapper文件)所在的包名,这个包中所有的xml文件一次都加载给mybatis
               使用package的要求
               1)mapper文件名称需要和接口名称一样,区分大小写的一样
               2)mapper文件和dao接口需要在同一目录下-->
        <package name="com.hr.qjb.dao"/>

使用package的要求
1)mapper文件名称需要和接口名称一样,区分大小写的一样
2)mapper文件和dao接口需要在同一目录下

扩展

PageHelper分页

PageHelper做数据分页的

先在pom文件中导入依赖

<!--    PageHelper的依赖-->
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>5.1.10</version>
    </dependency>

然后在mybatis.xml中配置插件

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>
  @Test
    public void testSelectAll(){
        SqlSession sqlSession=MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //加入PageHelper的方法,分页
        //pageNum:表示显示第几页 ,第一页
        //pageSize:表示一页有多少行数据
        PageHelper.startPage(2,2);
        List<Student> students = dao.selectAll();
        students.forEach(student -> System.out.println(student));
    }

主要使用PageHelper的startPage方法,第一个参数pageNum表示显示的页数,第二个参数pageSize:表示每页有多少条数据

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值