MyBatis从浅入深
目录
框架概述
MyBatis框架快速入门
编辑
编辑
编辑
编辑
MyBatis框架Dao代理
编辑
MyBatis框架动态Sql
MyBatis配置文件
扩展
使用步骤
框架概述
- 三层架构
- 界面层(User Interface layer):和用户打交道的,接收用户的请求参数,显示处理结果的。(jsp,html,servlet)
- 业务逻辑层(Business Logic layer):接收了界面层传递的数据,计算逻辑,调用数据库,获取数据
- 数据访问层(Data access layer):就是访问数据库,执行对数据的查询,修改,删除等等。
- 三层对应的包
- 界面层:controllerbao包(Servlet类)
- 业务逻辑层:service包(Service类)
- 数据访问层:dao包(Dao类)
- 三层中类的交互
- 用户使用界面层--->业务逻辑层--->数据访问层(持久层)--->数据库(MySql)
- 三层对应的处理框架
- 界面层---servlet---springmvc
- 业务逻辑层---service类---spring
- 数据访问层---dao类---mybatis
框架是一个舞台,一个模板
- 模板
- 规定好了一些条款,内容。
- 加入自己的东西
- 框架是一个模板
- 框架中定义好了一些功能,这些功能是可用的。
- 可以加入项目中自己的功能,这些功能可以利用框架中写好的功能。
框架是一个软件,半成品的软件,定义好了一些基础功能,需要加入你的功能就是完整的。
基础功能时可重复使用的,可升级的。
- 框架特点:
- 框架一般不是全能的,不能做所有事情
- 框架是针对某一个领域有效。特长在某一个方面,比如mybatis做数据库操作强,但是他不能做其他的。
- 框架是一个软件
- 使用JDBC的缺陷
- 代码比较多,开发效率低
- 需要关注Connection,Statement,ResultSet对象创建和销毁
- 对ResultSet查询的结果,需要自己封装为List
- 重复的代码比较多些
- 业务代码和数据库的操作混在一起
- Mybatis框架
- 一个框架,早起叫做iBatis,代码在github
- MaBatis是 MyBatis SQL Mapper Frameword for Java (sql映射框架)
- sql mapper :sql映射
- 可以把数据库表中的一行数据,映射为一个java对象。
- 一行数据可以看做是一个java对象,操作这个对象,就相当于操作表中的数据
- Data Access Object (DAOs) :数据访问,对数据库执行增删改查
- MyBatis提供了那些功能:
- 1、提供了创建Connection,Statement,ResultSet的能力,不用开发人员创建这些对象了
- 2、提供了执行sql语句的能力,不用你执行sql
- 3、提供了循环sql,把sql的结果转为java对象,List集合的能力
- 4、提供了关闭资源的能力,不用你关闭Connection,Statement,ResultSet
开发人员做的是:提供sql语句
最后是:开发人员提供sql语句--MyBatis处理sql--开发人员得到List集合或Java对象(表中的数据)
- 总结:
- MyBatis是一个sql映射框架,提供的数据库的操作能力,增强的JDBC。
- 使用MyBatis让开发人员集中精神写sql就行了,不必关心Connection,Statement,ResutSet的创建,销毁,sql的执行
MyBatis框架快速入门
- 主要类的介绍
- 1、Resources:mybatis中的一个类,负责读取主配置文件
- InputStream in = Resources.getResourceAsStream("mybatis.xml");
- 2、SqlSessionFactoryBuilder:创建SqlSessionFactory对象
- SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
- //创建SqlSessionFactory对象
- SqlSessionFactory factory = builder.build(in);
- 3、SqlSessionFactory:重量级对象,程序创建一个对象耗时比较长,使用资源比较多,在整个项目中,有一个就够用了
- SqlSessionFactory:接口,接口实现类:DefaultSqlSessionFactory
- SqlSessionFactory作用:获取SqlSession对象。
- SqlSession sqlSession = factory.openSession();
- openSession()方法说明:
- 1、openSession():无参数的,获取是非自动提交事务的SqlSession对象
- 2、openSession(boolean):openSession(true) 获取自动提交事务的SqlSession
- 1、Resources:mybatis中的一个类,负责读取主配置文件
openSession(false) 获取非自动提交事务的SqlSession
- 4、SqlSession:
- SqlSession接口:定义了操作数据的方法 例如 seelctOne(), selectList(), insert(), update(), delete(), commit(), rollback()
- SqlSession接口的实现类DefaultSqlSession
- 使用要求:SqlSession对象不是线程安全的,需要在方法内部使用,在执行sql语句之前,使用openSession()获取SqlSession对象,在执行完sql语句后,需要关闭它,执行SqlSession.close(),这样能保证它的使用时线程安全的。
MyBatis框架Dao代理
- MyBatis动态代理
- 使用SqlSession.getMapper(dao接口.class) 获取这个dao接口的对象
- 传入参数:从java代码中把数据传入到mapper文件的sql语句中
- parameterType:写在mapper文件中的一个属性。表示dao接口中方法的参数的数据类型。
- 例如 StudentDao接口:Student selectStudentById(Integer id);
- 对应的mapper文件中的parameterType: paramterType="java.lang.Integer"
- parameterType:dao接口中方法参数的数据类型。
- parameterType它的值是java的数据类型全限定名称或者是mybatis定义的别名
- 例如:parameterType="java.lang.Integer"
parameterType="int"
- 注意parameterType不是强制的,mybatis通过反射机制能够发现接口参数的数据类型。所以可以没有,一般我们也不写。
- 一个简单类型的参数
- 简单类型:mybatis把java的基本数据类型和String都叫简单类型
- 在mapper文件获取简单类型的一个参数的值,使用#{任意字符}
- 接口: Student selectStudentById(Integer id)
- mapper:select id,name,email,age from student where id = #{studentId}
- 多个参数,使用@Param命名参数
- 接口中的方法:List<Student> selectMultipleParam(@Param("myName") String name,@Param("myAge") Integer age)
- 在形参定义的前面加入 @Param("自定义参数名称")
- mapper 文件:
- <select>
- select * from student where name = #{myName} or age = #{myAge}
- </select>
- <select>
- 多个参数,使用java对象的属性值,作为参数实际值
- 接口中的方法:List<Student> selectMultipleObject(Object object);
- 使用对象语法:#{属性名,javaType=类型名称,jdbcType=数据类型} 很少用
javaType:指java中的属性数据类型
jdbcType:在数据库中的数据类型
例如:#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
- 我们使用的简化方式:#{属性名} ,javaType,jdbcType的值mybatis反射能获取。不用提供
- 多个参数,简单类型的,按位置传值
- mybatis.3.4之前,使用 #{0} ,#{1}
- mybatis.3.4之后,使用 #{arg0} ,#{arg1}
- 接口中的方法:List<Student> selectMultiplePosition(String name,Integer age);
- mapper:
- <select>
- select id,name,email,age from student where name = #{arg0} or age = #{arg1}
- </select>
- <select>
- 多个参数,使用Map存放多个值
- 在mapper中使用map集合的key作为参数
- 接口中的方法:List<Student> selectMultipleByMap(Map<String,Object> map);
- mapper:
- <select>
- select id,name,email,age from student where name = #{myName} or age = {myAge}
- </select>
- <select>
- 两个占位符 # 和 $
- #:占位符,告诉mybatis使用实际的参数值代替。并使用PreparedStatement对象执行sql语句,#{…}代替sql语句的 '?'。这样做更安全,更迅速,通常也是首选做法。
- $:字符串拼接,告诉mybatis使用$包含的字符串替换所在位置。使用Statement把sql语句和${}的内容连接起来。主要用在替换表名,列名,不同列排序等操作。
- select id,name,email,age from student where id = #{studentId}
- # 的结果是:select id,name,email,age from student where id = ?
- $ 的结果是:select id,name,email,age from student where id = 1001
- String sql = "select id,name,email,age from student where id = " + "1001";
- 使用的Statement对象执行sql,效率比PreparedStatement低。
- # 和 $的区别
- #使用 ?在sql语句中做占位的,使用PreparedStatement执行sql,效率高。
- #能够避免sql注入,更安全。
- $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
- $有sql注入的风险,缺乏安全性
- $可以替换表名或者列名,你能确定数据是安全的,可以使用$
- mybatis的输出结果,resultType
- resultType的默认原则是 同名的列 值赋值给同名的属性
- resultType:执行sql得到ResultSet转换的类型,使用类型的完全限定名或别名。注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。resultType 和 resultMap 不能同时使用。
- resultType结果类型,指sql语句执行完毕后,数据转为的java对象,java类型是任意的。
- resultType结果类型的值
- 1、类型的全限定名称
- 2、类型的别名 例如 java.lang.Integer 别名是 int
- 处理方式:
- 1、mybatis执行sql语句,然后mybatis调用类的无参数构造方法,创建对象。
- 2、mybatis把ResultSet指定列值付给同名的属性。
- 定义别名,在mybatis.xml 主配置文件中设置
- 第一种方式
- 可以指定一个类型一个自定义别名
- type:自定义类型的全限定名称
- alias:别名
- <typeAliases>
- <typeAlias type="com.li.domain.Student" alias="stu" />
- </typeAliases>
- 第二种方式
- name是包名,这个包中的所有类,类名就是别名(类名不区分大小写)
- <typeAliases>
- <package name="com.li.domain" />
- </typeAliases>
- 第一种方式
- 当返回值为Map时,不建议返回Map
- 列名是map的key,列值是map的value
- 只能最多返回一行记录,多余一行就会报错
- 接口中的方法: Map<Object,Object> selectStudentById(@Param("stuId") Integer id);
- mapper:
- <select id="selectStudentById" resultType="map">
- select id,name,email,age from student where id = #{stuId}
- </select>
- <select id="selectStudentById" resultType="map">
- resultMap:结果映射,指定列名和java对象的属性对应关系。
- 1、你自定义列值赋值给哪个属性
- 2、当你的列名和属性名不一样时,一定使用resultMap
- 也可以将查询后的列名改为别名,与java对象的属性相对应
- resultMap的使用
- 1、先定义resultMap
- 2、在select标签,使用resultMap来引用定义好的resultMap
- 定义resultMap
- id:自定义名称,表示你定义的这个resultMap
- type:java类型的全限定名称
- <resultMap id="studentMap" type="com.li.domain.Student">
- <!--列名和java属性的关系-->
- <!-- column:列名,property:java类型的属性名 -->
- <!-- id为主键列,result为非主键列 -->
- <id column="id" property="id" />
- <result column="name" property="name" />
- <result column="email" property="email" />
- <result column="age" property="age" />
- </resultMap>
- 使用resultMap
- <select id="selectStudents" resultMap="studentMap">
- select id,name,email,age from student
- </select>
- <select id="selectStudents" resultMap="studentMap">
MyBatis框架动态Sql
- 动态sql:
- 使用java对象作为参数
- sql的内容是变化的,可以根据条件获取到不同的sql语句。
- 主要是where部分发生变化
动态sql的实现,使用的是mybatis提供的标签,<if>,<where>,<foreach>
- <if>是判断条件的
- <if test="使用参数java对象的属性值作为判断条件">
- 部分sql语句
- </if>
- 例如:
- <select id="selectStudentIf" resultType="com.li.domain.Student">
- select id,name,email,age from student where
- <if test="name != null and name != '' ">
- name = #{name}
- </if>
- <if test="age > 0">
- or age > #{age}
- </if>
- </select>
- <select id="selectStudentIf" resultType="com.li.domain.Student">
- <if test="使用参数java对象的属性值作为判断条件">
- <where>标签
- 用来包含多个<if>的,当多个if有一个成立的,<where>会自动增加一个where关键字,并去掉if中多余的 and ,or等。
- 例如:
- <select id="selectStudentWhere" resultType="com.li.domain.Student">
- select id,name.email,age from student
- <where>
- <if test="name != null and name != '' ">
- <select id="selectStudentWhere" resultType="com.li.domain.Student">
name = #{name}
- </if>
- <if test="age > 0">
- or age > #{age}
- </if>
- </where>
- </select>
- <foreach>标签
- 循环java中的数组,list集合。主要用在sql的in语句中。
- select * from student where id in (1001,1002,1003);
- 语法:
- collection:表示接口中的方法参数的类型,如果是数据使用array,如果是List集合使用list
- item:自定义的,表示数组和集合成员的变量
- open:循环开始时的字符
- close:循环结束时的字符
- separator:集合成员之间的分隔符
- <foreach collection="" item="" open="" close="" separator="">
- </foreach>
- 基本数据类型例子:
- <select id="selectStudentForeach" resultType="com.li.domain.Student">
- select id,name,email,age from student where id in
- <foreach collection="list" item="myId" open="(" close=")" separator=",">
- #{myId}
- </foreach>
- </select>
- <select id="selectStudentForeach" resultType="com.li.domain.Student">
- 引用数据类型例子:
- <select id="selectStudentForeach" resultType="com.li.domain.Student">
- select id,name,email,age from student where id in
- <foreach collection="list" item="stu" open="(" close=")" separator=",">
- #{stu.id}
- </foreach>
- </select>
- <select id="selectStudentForeach" resultType="com.li.domain.Student">
- 代码片段
- <sql>标签用于定义sql片段,以便其他sql标签复用。而其他标签使用该sql片段,需要使用<include>字标签。该<sql>标签可以定义sql语句中的任何部分,所以<include>子标签可以放在动态sql的任何位置。
- 就是复用一些语句
- 使用步骤
- 1、先定义<sql id="自定义名称唯一" > sql语句 </sql>
- 2、在使用,<include refid="id的值" />
- 例如:
- <sql id="studentSql">
- select id,name,email,age from student
- </sql>
- <select id="selectStudentSqlFragment" resultType="com.li.domain.Student">
- <include refid="studentSql" /> where name = #{myName}
- </select>
- <sql id="studentSql">
MyBatis配置文件
- transactionManager
- type:事务的处理的类型
- JDBC:表示mybatis底层是调用JDBC中的Connection对象的,commie,rollback
- MANAGED:把mybatis的事务处理委托为其他的容易(一个服务器软件,spring)
- type:事务的处理的类型
- dataSource
- 表示数据源,java体系中,规定了实现javax.sql.DataSource接口的都是数据源。
- 数据源表示Connection对象的。
- type:指定数据源的类型
- POOLED:使用连接池,mybatis会创建PooledDataSource类
- UPOOLED:不使用连接池,在每次执行sql语句,先创建连接,执行sql,再关闭连接,mybatis会创建一个UnPooledDataSource,管理Connection对象的使用
- JNDI:java命令和目录服务(windows注册表)
- 数据库的属性配置文件:
- 把数据库连接信息放到一个单独的文件中,和mybatis主配置文件分开。
- 目的是便于修改,保存,处理多个数据库的信息。
- 在resources目录下定义一个属性配置文件,xxxx.properties
- 在属性配置文件中,定义数据,格式是 key=value
- key:一般使用 . 作为多级目录的
- 例如:
- jdbc.driver=com.mysql.jdbc.Driver
- jdbc.url=jdbc:mysql://localhost:3306/myabtis
- jdbc.username=root
- jdbc.password=1212
- 在mybatis的主配置文件,使用<properties> 指定文件的位置
- <!--指定properties文件的位置,从类路径根开始找文件-->
- <properties resource="jdbc.properties" />
- 在需要使用值的地方,使用 ${key}
- mapper的位置
- 第一种方式:指定多个mapper文件
- <mappers>
- <mapper resource="com/li/dao/StudentDao.xml" />
- <mapper resource="com/li/dao/OrderDao.xml" />
- </mappers>
- <mappers>
- 第二种方式:使用包名
- name:xml文件所在的包名,这个包中所有的xml文件一次都能加载给mybatis
- 使用package的要求:
- 1、mapper文件名称需要和接口名称一样,区分大小写
- 2、mapper文件和dao接口需要在同一目录下
- <mappers>
- <package name="com.li.dao" />
- <package name="com.li.dao2" />
- </mappers>
- 第一种方式:指定多个mapper文件
扩展
- PageHelper:做数据分页的,不是mybatis框架的,是一个牛人写的组件
- 在pom.xml文件中加入
- <dependency>
- <groupId>com.github.pagehelper</groupId>
- <artifactId>pagehelper</artifactId>
- <version>5.1.10</version>
- </denpendency>
- <dependency>
- 在主配置文件mybatis.xml的 <environments> 之前加入
- <plugins>
- <plugin interceptor="com.github.pagehelper.PageInterceptor" />
- </plugins>
- <plugins>
- 在pom.xml文件中加入