MyBatis编程基础与进阶

MyBatis 编程基础

1.1. MyBatis 基本步骤

Step01:创建maven 桌面项目(Java 项目)

Step02:添加mybatis依赖以及mysql驱动依赖

Step03:创建mybatis 配置文件,映射文件

Step04:配置数据访问(配置文件),SQL映射(映射文件)

Step05:创建MyBatis API(例如SqlSession)对象,执行SQL操作.

 

常见问题及解决办法

1) 数据库连不上,可能存在哪些问题?

a) 检测url,用户名,密码

b) 检测端口号(port)

c) id地址是否能ping

d) 检测驱动程序(有可能依赖的驱动程序与数据库版本不兼容)

 

2) mybatis 配置文件的名字有要求吗?(只要符合标识符规范即可)

3) mybatis 配置文件要对哪些信息进行配置呢?

4) mybatis 映射文件中主要用于定义哪些内容?(sql元素)

5) MyBatis 执行SQL操作时一个基本过程是怎样的?

a) step01:MyBatis API调用JDBC API

b) step02:JDBC API 调用数据库驱动程序API

1.2. MyBatis 编程实现

1.2.1. 数据准备

创建数据库,并在中创建表

create database cgb1711 character set utf8;


打开数据库

use cgb1711;


创建

create table blog(

 id int primary key auto_increment,

 title varchar(200) not null,

 content varchar(500) not null,

 createdTime date

) engine=innoDB;

 

表中写入数据

insert into blog values (null,'ta','ta...',now());

insert into blog values (null,'tb','tb...',now());

1.2.2. 创建Maven桌面项目

创建maven 桌面项目,并添加依赖(mybatis,mysql驱动)

<!-- 添加mybatis依赖 -->

 <dependency>

  <groupId>org.mybatis</groupId>

  <artifactId>mybatis</artifactId>

  <version>3.2.8</version>

 </dependency>

 

 <!-- 添加mysql驱动依赖 -->

 <dependency>

   <groupId>mysql</groupId>

   <artifactId>mysql-connector-java</artifactId>

   <version>5.1.40</version>

 </dependency>

 

  <!-- 添加junit依赖 -->

 <dependency>

   <groupId>junit</groupId>

   <artifactId>junit</artifactId>

   <version>4.12</version>

 </dependency>

 

注意:

1) 添加依赖时注意groupId的选择?(正规的)

2) 添加依赖以后pom.xml文件假如有错什么原因? 检测网络,检测maven配置(setting.xml)

1.2.3. 添加配置及映射文件

src/main/resources目录下创建配置文件mybatis-configs.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>

  <!-- 配置初始化环境(连接) -->

  <environments default="development">

    <environment id="development">

      <transactionManager type="JDBC"/>

      <dataSource type="POOLED">

        <property name="driver" value="com.mysql.jdbc.Driver"/>

        <property name="url"  value="jdbc:mysql:///cgb1711"/>

        <property name="username" value="root"/>

        <property name="password" value="root"/>

      </dataSource>

    </environment>

  </environments>

  <!-- 配置mapper文件路径 -->

  <mappers>

     <mapper resource="mapper/BlogMapper.xml"/>

  </mappers>

</configuration>

 

说明:

1)配置文件的头官方文档进行拷贝.

2)配置文件元素没有提示什么原因? 对应dtd文件取不到

 

step02:src/main/resources/mapper目录下创建映射文件BlogMapper.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.jt.blog.BlogDao">

</mapper>


说明:

1) 映射文件的命名空间用于约束元素id的唯一性.

2) 映射文件的格式最好包结构形式

3) 映射文件内部可以定义很多元素,每个元素必须有一个唯一id,例如select

 

mapper文件中添加如下元素:

查询所有blog数据

<select id="findBlogs" resultType="map">

         select * from blog

</select>

根据id查询blog数据

<select id="findBlogById" resultType="map">

         select *

         from blog 

         where id=#{id}

</select>

限制查询blog元素

<select id="findPageBlogs"

            resultType="map">

          select * from blog

          limit #{array[0]},#{array[1]}

</select>

 

表中插入数据元素定义

   <insert id="insertObject">

          insert into blog

          (id,title,content,createdTime)

          values

          (null,#{array[0]},#{array[1]},now())

    </insert>

 

修改表中数据元素定义

<update id="updateObject">

         update blog 

         set title=#{array[0]},

             content=#{array[1]}

         where id=#{array[2]}

    </update>

 

删除表中元素元素定义

  <delete id="deleteObject">

         delete

         from blog

         where id=#{id}

    </delete>

 

1.2.4. 编写代码执行查询测试

基于BlogMapper.xml文件中元素的定义,添加测试类及相关方法.

 

编写测试类添加测试方法

public class TestBlog01 {

private SqlSessionFactory factory;

}

测试类中添加初始化factory的方法

@Before

public void init()throws IOException{

//初始化SqlSessionFactory

factory=new SqlSessionFactoryBuilder()

.build(Resources.getResourceAsStream(

"mybatis-configs.xml"));

}

 

测试类中添加查询所有blogs的方法

@Test

public void testFindBlogs(){

//1.创建SqlSession对象(相当于创建一个连接)

SqlSession session=factory.openSession();

//2.执行查询操作(selectList("命名空间"+"元素id"))

List<Object> list=session.selectList(

"com.jt.blog.BlogDao.findBlogs");

for(Object o:list){

System.out.println(o);

}

//3.释放资源(类似关闭连接)

session.close();

}

 

测试类中添加根据id执行查询方法

@Test

public void testFindBlogById(){

//1.创建session对象

SqlSession session=

factory.openSession();

//2.执行sql操作

String statement="com.jt.blog.BlogDao.findBlogById";

Map<String,Object> map=

session.selectOne(statement,1);

System.out.println(map);

//3.释放资源(关闭session对象)

session.close();

}

 

测试类中添加分页查询方法

@Test

public void testFindPageBlogs(){

//1.创建session对象

SqlSession session=

factory.openSession();

//2.执行sql操作?????

String statement="com.jt.blog.BlogDao.findPageBlogs";

Object parameter=new Object[]{0,4};

List<Map<?,?>> list=

session.selectList(statement, parameter);

for(Map<?,?>map:list){

System.out.println(map);

}

//3.释放资源(关闭session对象)

    session.close();

};

 

测试类中添加插入数据的方法

@Test

public void testInsertObject(){

//1.创建session

SqlSession session=factory.openSession();

//2.执行sql

String statement="com.jt.blog.BlogDao.insertObject";

Object parameter=new Object[]{"te","te..."};

int rows=session.insert(statement, parameter);

System.out.println("insert.rows="+rows);

session.commit();

//3.关闭session

session.close();

}

 

测试类中添加修改方法

@Test

public void testUpdateObject(){

//1.创建session

SqlSession session=factory.openSession();

//2.执行sql

String statement="com.jt.blog.BlogDao.updateObject";

Object parameter=new Object[]{"taa","taa...",1};

int rows=session.update(statement, parameter);

System.out.println("update.rows="+rows);

session.commit();

//3.关闭session

session.close();

}

 

测试类中添加删除方法

@Test

public void testDeleteObject(){

//1.创建session

SqlSession session=factory.openSession();

//2.执行sql

String statement="com.jt.blog.BlogDao.deleteObject";

Object parameter=7;

int rows=session.delete(statement, parameter);

session.commit();

System.out.println("delete.rows="+rows);

//3.关闭session

session.close();

}

 

2. MyBatis 编程进阶

小节中会从mybatis编程的另一个角度(例如基于接口方式)实现对数据库数据的操作.

2.1. 基本步骤

Step01: 创建maven桌面项目添加依赖

Step02: 创建配置文件config.propertis(内容为数据库相关)

Step03: 创建mybatis核心配置文件mybatis-configs.xml文件

Step04: 配置Mybatis基础数据服务(properties,datasource,mapper)

Step05: 创建映射文件BlogMapper.xml

Step06: 创建实体类Blog(对应,可用于封装表中数据)

Step07: 创建BlogDao接口,添加相关方法.

Step08: 配置BlogMapper映射文件,添加相关元素.

Step09: 基于BlogDao接口与映射文件实现CRUD操作

2.2. 编程实现

2.2.1. 创建Maven桌面项目

创建maven桌面项目添加依赖

<!-- 添加mybatis依赖 -->

 <dependency>

  <groupId>org.mybatis</groupId>

  <artifactId>mybatis</artifactId>

  <version>3.2.8</version>

 </dependency>

 <!-- 添加mysql驱动依赖 -->

 <dependency>

   <groupId>mysql</groupId>

   <artifactId>mysql-connector-java</artifactId>

   <version>5.1.40</version>

 </dependency>

  <!-- 添加junit依赖 -->

 <dependency>

   <groupId>junit</groupId>

   <artifactId>junit</artifactId>

   <version>4.12</version>

 </dependency>

 

2.2.2. 创建config.properties文件

src/main/resource目录下创建config.properties文件,文件中定义

系统中的一些常用配置信息,例如访问数据库的相关信息,其内容如下

driver=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/cgb1711

username=root

password=root

 

2.2.3. 创建mybatis核心配置文件

src/main/resources目录下创建mybatis-configs.xml文件,并配置数据源等相关信息,数据信息从config.properties文件读取.

<?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文件-->

  <properties resource="config.properties"/>

  <!-- 配置初始化环境(连接) -->

  <environments default="development">

    <environment id="development">

      <transactionManager type="JDBC"/>

      <dataSource type="POOLED">

        <property name="driver" value="${driver}"/>

        <property name="url"  value="${url}"/>

        <property name="username" value="${username}"/>

        <property name="password" value="${password}"/>

      </dataSource>

    </environment>

  </environments>

</configuration>

 

2.2.4. 创建Blog实体对象

创建Blog实现与数据库中Blog实现映射.

public class Blog {

private Integer id;

private String title;

private String content;

private Date createdTime;

public Integer getId() {return id;}

public void setId(Integer id) {this.id = id;}

public String getTitle() {return title;}

public void setTitle(String title) {this.title = title;}

public String getContent() {return content; }

public void setContent(String content) {this.content = content;}

public Date getCreatedTime() {return createdTime; }

public void setCreatedTime(Date createdTime) {this.createdTime = createdTime; }

@Override

public String toString() {

return "Blog [id=" + id + ", title=" + title + ", content=" + content + ", createdTime=" + createdTime + "]";}

}

 

2.2.5. 创建BlogDao接口

创建数据访问接口,并添加相关方法

package com.jt.dao;

import java.util.List;

import org.apache.ibatis.annotations.Param;

import com.jt.entity.Blog;

public interface BlogDao {

 /***

  * 根据id进行对象查找

  */

 Blog findBlogById(Integer id);

 List<Blog> findPageBlogs(

     @Param("offset")Integer offset,

     @Param("pageSize")Integer pageSize);

 int insertObject(Blog blog);

 int updateObject(Blog blog);

 int deleteObject(Integer id);

}

 

2.2.6. 创建BlogMapper映射文件

<?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.jt.dao.BlogDao">

</mapper>

 

BlogMapper文件中添加BlogDao接口对应的映射元素

添加基于ID进行查询的元素

<select id="findBlogById"

           parameterType="int"

           resultType="blog">

           select *    from blog  where id=#{id}

   </select>

添加分页查询元素

  <select id="findPageBlogs"

           resultType="blog">

           select *

           from blog

           limit #{offset},#{pageSize}

   </select>

添加insert元素

   <insert id="insertObject"

           parameterType="blog">

           insert into blog

           (id,title,content,createdTime)

           values

           (null,#{title},#{content},now())

   </insert>

添加更新元素

   <update id="updateObject"

           parameterType="blog">

           update blog

           set title=#{title},content=#{content}

           where id=#{id}

   </update>

添加删除元素

<delete id="deleteObject"

           parameterType="int">

           delete from blog where id=#{id}

</delete>

mybatis-configs.xml添加BlogMapper文件

 

2.2.7. 创建单元测试类执行测试

创建单元测试类,并添加相关方法实现基于Dao接口方式的数据库操作.

public class TestBlog01 {

private SqlSessionFactory factory

@Before

public void init()throws IOException{

factory=new SqlSessionFactoryBuilder()

.build(Resources.getResourceAsStream(

"mybatis-configs.xml"));

}

@Test

public void testFindBlogById(){

//1.创建session

    SqlSession session=factory.openSession();

//2.执行sql

    //2.1获取dao对象

    BlogDao dao=

    session.getMapper(BlogDao.class);

    //2.2执行dao中方法

    Blog blog=dao.findBlogById(1);

    System.out.println(blog);

//3.关闭session

    session.close();

}

@Test

public void testFindPageBlogs(){

//1.创建session

SqlSession session=factory.openSession();

//2.执行sql

//2.1获取dao对象

BlogDao dao=

session.getMapper(BlogDao.class);

//2.2执行dao中方法

List<Blog> list=dao.findPageBlogs(0, 2);

for(Blog b:list){

System.out.println(b);

}

//3.关闭session

session.close();

}

@Test

public void testInsertObject(){

//1.创建session

SqlSession session=factory.openSession();

//2.执行sql

//2.1获取dao对象

BlogDao dao=

session.getMapper(BlogDao.class);

//2.2执行dao中方法

Blog blog=new Blog();

blog.setTitle("te");

blog.setContent("te...");

dao.insertObject(blog);

session.commit();

//3.关闭session

session.close();

}

}

2.3. 业务增强

 

2.3.1. 动态排序策略

 

1. 如何按照用户指定业务数据进行排序?

例如:

1) 博客系统

a) 按照创建时间对博客信息进行排序查询

b) 按照博客访问量对信息进行排序查询

2) 电商系统

a) 按照商品价格对商品信息排序

b) 按照商品销量商品信息排序

c) 按照商品好评对商品信息排序

 

解决方案:

1) 多个sql映射

2) 一个sql 映射,然后动态传参,借助${}表达式获取参数

例如

接口中方法定义

List<Blog> findBlogs(

 @Param("column") String column,

@Param("seq") String seq);

映射文件中的实现

<select id="findBlogs" 

           resultType="blog">

         select *

         from blog

         order by ${column} ${seq}

</select>

拓展:

MyBatis$#有什么不同?

${}表达式主要用于获取配置文件数据,DAO接口中的参数信息,$出现在映射文件SQL语句中时创建的不是预编译的SQL,而是字符串的拼接,有可能会导致SQL注入问题.所以一般使用$接收dao参数时,这些参数一般是字段,表名等,例如order by {column}.

#{}表达式主要用户获取DAO中的参数数据,在映射文件SQL语句出现#{}表达式,底层会创建预编译SQL.性能会相对较好.

${}获取DAO参数数据时,参数必须使用@param注解进行修饰.

#{}获取DAO参数数据时,假如参数个数一个有选择的使用@param.

 

2.3.2. ID应用策略

1.保存数据时获取数据在数据库对应的主键值?

例如

1) 订单系统?

保存订单信息时候,获取订单数据库中主键id?

2) 权限系统

保存用户信息,获取用户信息在数据库中的主键?

   解决方案: 当对象对应的表中的记录为自增长时,可以采用如下方案

      <insert id="insertObject"

           parameterType="blog"

           useGeneratedKeys="true"

           keyProperty="id">

           insert into blog

           (id,title,content,createdTime)

           values

           (null,#{title},#{content},now())

   </insert>

其中:keyProperty属性用于指定参数中的id属性.


2. 多线程并发的向表中写入数据时,假如id使用自增长可能存在线程安全问题?

例如:

1) 秒杀系统

2) 订票系统

3) ....

解决方案:可将自增长的id设置为随机数,当然有些数据库根本就不支持自增长,此时也可以选择随机数.

数据准备:创建Author

create table Author(

  id varchar(200) primary key,

  username varchar(100) unique not null,

  password varchar(300) not null,

  email varchar(50) unique

)engine=InnoDB;

借助mybatis 应用向表中写入数据,主键值要求通过UUID生成.映射文件参考

<insert id="insertObject"

           parameterType="author">

      <selectKey keyProperty="id" 

                 resultType="string"

                 order="BEFORE">

          select replace(uuid(),'-','')

      </selectKey>

       insert into author

       (id,username,password,email)

       values

       (#{id},#{username},#{password},#{email})

</insert>

 

3. MyBatis 高级应用

3.1. 日志配置应用

Mybatis内置的日志工厂提供日志功能,具体的日志实现有以下几种工具:

1)SLF4J(日志框架标准,类似JDBC标准)

2)Apache Commons Logging

3)Log4j 2 (log4j的升级版,配置文件升级为xml格式了)

4)Log4j(日志处理库,配置文件格式为.properties)

5)JDK logging

项目mybatis通常会借助三方日志库进行日志的处理,例如log4j.

配置步骤:(log4j为例)

1. 添加log4j依赖(一代)

  <dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<version>1.2.17</version>

  </dependency>

 

2.添加log4j.properties 配置(可以其它项目中拷贝)

log4j.rootLogger=INFO,stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d [%-5p] %c - %m%n

log4j.logger.com.mybatis3=DEBUG

log4j.logger.com.jt=DEBUG

 

3. 设置mybatis日志实现(mybatis-configs.xml)

  <settings>

     <setting name="logImpl" value="log4j"/>

  </settings>

 

其中name属性值为固定写法,value的值要依托于使用的日志处理库.

说明:课后了解常用的日志处理库.

3.2. 缓存配置应用

1. 缓存是什么? 内存中的一个对象(容器).

2. 缓存对象的作用?提高程序的性能(主要的的访问效率)

3. MyBatis 中缓存概述?

MyBatis 框架提供了非常强大的缓存特性提高查询性能,通常分为一级缓存(SqlSession级别)和二级(SqlSessionFactory).

4. MyBatis 缓存应用.

MyBatis中一级缓存默认是开启.需要任何配置.例如:

 

@Test

public void testFindObjects(){

SqlSession session=factory.openSession();

AuthorDao dao=

session.getMapper(AuthorDao.class);

//==============

List<Author> list=

dao.findObjects();

session.close();

session=factory.openSession();

dao=session.getMapper(AuthorDao.class);

list=dao.findObjects();

//==============

session.close();

}

 

MyBatis 二级缓存默认是没有开启的,需要在映射文件中加上<Cache/>元素

MyBatis 二级缓存应用步骤:

Step01: 修改mybatis核心配置文件,添加缓存设置.

<settings>

     <setting name="cacheEnabled" value="true"/>

  </settings>

 

Step02: 映射文件中配置Cache策略.

   <cache

     eviction="LRU"

     flushInterval="60000"

     size="512"

     readOnly="true"/>

 

这个表示创建了一个 LRU缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会 导致冲突。其中:

1) eviction 表示回收策略(例如LRU,FIFO等,默认为LRU)

2) flushInterval 表示刷新间隔

3) size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的 可用内存资源数目。默认值是 1024

4) readOnly(只读)属性可以被设置为 true false。只读的缓存会给所有调用者返回缓存对象的相同实例。可读写的缓存会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全,因此默认是 false

Step03: 使用二级缓存.

@Test

public void testFindObjectById(){

SqlSession session=factory.openSession();

AuthorDao dao=session.getMapper(AuthorDao.class);

String id="c6dad9d622a311e88271408d5c85e6b9";

Author a1=dao.findObjectById(id);

System.out.println("a1="+a1);

session.close();

session=factory.openSession();

dao=session.getMapper(AuthorDao.class);

Author a2=dao.findObjectById(id);

a2.setUsername("tedu-10");

System.out.println("a2="+a2);

//System.out.println(a1==a2);

session.close();

session=factory.openSession();

dao=session.getMapper(AuthorDao.class);

Author a3=dao.findObjectById(id);

System.out.println("a3="+a3);

session.close();

}

readOnly说明:

readOnly值为true,缓存中保存的是堆内存中对象的引用.每次缓存数据都是获得的同一个对象.readOnlyfalse,首先会将查询到的对象,拷贝到缓存一份(对象需要实现序列化接口),然后从缓存取数据每次都是执行对象的拷贝.

 

3.3. 高级映射应用

MyBatis中的高级映射一般要借助select元素中的resultMap属性进行实现,通过此属性配置实现一对一,一对多等关系映射的实现.

1. 如何实现one2one映射?

2. 如何实现one2many映射?

3. 如何实现many2many映射?

延伸:

1) 查询博客信息时,将作者信息查询出来?(many2one)

2) 查询某个用户的同时,将其对应的博客列表信息查询出来(one2many)

3) .....

 

1) blog中添加一个字段,名字为authorId,类型为string.

2) blog表中的authorId字段赋值,其值为author表中某些记录的主键值.

3) 查询某个blog信息,并将其关联的author对象信息查询出来,

 

3.4. 延迟加载应用

关联查询中的关联对象数据进行延迟加载(何时需要何时加载).提高内存的使用效率.

具体如何配置?(参考官方文档)

 

3.5. 动态SQL应用

如何动态删除客户端选择记录,用户可能会选择一个记录,可能会选择多个记录然后进行删除.那么在mybatis的映射文件中该如何配置,如何实现或者说解决这种动态需问题?

了解:动态sql.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值