MyBatis快速入门(第一天)

一、MyBatis快速入门

(一)开发步骤介绍

1、创建MyBatis_db数据库和person

2、创建java项目,引入MyBatis坐标

3、创建User实体类

4、编写映射文件PersonMapper.xml

5、编写配置文件SqlMapConfig.xml

6、编写测试类

(二) 代码实现

1、创建对应的数据库的表 person

  create table person(

       id int primary key auto_increment,

       name varchar(32),

       bir date ,

       address varcahr(32)

);

2、导入MyBatis框架依赖

 <dependencies>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>

    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.2</version>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.32</version>
    </dependency>

</dependencies>

<build>

    <!--规定  java包下的配置文件 编译之后照样生效-->
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>

</build>

 

3、创建数据模型

public class Person implements Serializable {

 private int id;

 private String name;

 private Date bir;

 private String address; 

  //提供set和get方法部分省略

}

 

4、创建接口对应映射文件PersonMapper.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="PersonMapper">   

     <select id="findAll" resultType="com.offcn.bean.Person">

          select * from  person

     </select>      

</mapper>

 

5、在src下创建MyBatis的核心配置文件 SqlMapConfig.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="MySQL">

<!--使用MySQL环境-->

<environment id="MySQL">

<!--使用JDBC类型事务管理器-->

<transactionManager type="JDBC"></transactionManager>

<!--使用连接池-->

<dataSource type="POOLED">

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

<property name="url" value="jdbc:MySQL://localhost:3306/0423dbs"/>  

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

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

</dataSource>

</environment>

</environments>

<!--加载映射配置-->

<mappers>

<mapper resource="com/offcn/mapper/PersonMapper.xml"></mapper>

</mappers>

</configuration>

 

6、编码测试

@Test

public void testFindAll() throws Exception {

// 加载核心配置文件

InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");

// 获取SqlSessionFactory工厂对象

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

// 获取SqlSession会话对象

SqlSession sqlSession = sqlSessionFactory.openSession();

// 执行sql

List<User> list = sqlSession.selectList("PersonMapper.findAll");

for (Person person: list) {

 System.out.println(person);

 }

// 释放资源

sqlSession.close();

}

(三) 配置文件概述    

1SqlMapConfig.xml配置文件

   这个配置文件是整个Mybatis的核心配置文件,在这个配置文件中我们主要进行了整个数据库交互的整体配置,例如数据库的连接,事务的管理,映射文件的加载,这个配置文件我们只需要操作一次即可,不需要频繁改动。

 

2PersonMapper.xml配置文件

 <mapper namespace="PersonMapper">   

     <select id="findAll" resultType="com.offcn.bean.Person">

          select * from  person

     </select>      

</mapper>

namespace属性:属性的值我们可以任意定义的一个字符串(做到见名知意),用来作为映射sql的一个部分,

id:我们sql语句的唯一标记

resultType:我们查询数据的结果类型。

二、MyBatis增删改查

(一) 使用MyBatis完成增删改操作

1、新增操作

 

编写映射文件PersonMapper.xml

<mapper namespace="PersonMapper">

<!--新增-->

<insert id="insert" parameterType="com.offcn.bean.Person">

insert into user(name,bir,address) values(#{name},#{bir},#{address})

</insert>

</mapper>

 

编写测试类

@Test

public void save() throws Exception {

// 加载核心配置文件

InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");

// 获取SqlSessionFactory工厂对象

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

// 获取SqlSession会话对象

SqlSession sqlSession = sqlSessionFactory.();

Person person = new Person();

person.setName(“张三”);

person.setBir(new java.util.Date());

person.setAddress(“上海”);

// 执行sql

sqlSession.insert("PersonMapper.insert", person);

//提交事务

sqlSession.commit();

// 释放资源

sqlSession.close();

}

2、更新操作

<mapper namespace="PersonMapper">

<!--修改-->

 <update id="update" parameterType="com.offcn.bean.Person">

update person set name= #{name},bir= #{bir},address = #{address} where id = #{id}

 </update>

 </mapper>

 

编写测试类

@Test

public void updateInfo() throws Exception {

// 加载核心配置文件

InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");

// 获取SqlSessionFactory工厂对象

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

// 获取SqlSession会话对象

SqlSession sqlSession = sqlSessionFactory.();

Person person = new Person();

person.setName(“李四”);

person.setBir(new java.util.Date());

person.setAddress(“北京”);

// 执行sql

sqlSession.update("PersonMapper.update", person);

//提交事务

sqlSession.commit();

// 释放资源

sqlSession.close();

}

 

3、删除操作

<mapper namespace="PersonMapper">

<!--删除--> <delete id="delete" parameterType="java.lang.Integer">

    delete from person where id = #{id}

</delete>

</mapper>

 

编写测试类

@Test

public void updateInfo() throws Exception {

// 加载核心配置文件

InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");

// 获取SqlSessionFactory工厂对象

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

// 获取SqlSession会话对象

SqlSession sqlSession = sqlSessionFactory.();

// 执行sql

sqlSession.delete("PersonMapper.delete", 50);

//提交事务

sqlSession.commit();

// 释放资源

sqlSession.close();

}

(二)使用抽取的工具类完成操作

1、制作统一的工具类

public class MyBatisUtils {

private static SqlSessionFactory sqlSessionFactory = null;

static {

try {

// 加载核心配置文件

InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");

// 获取SqlSessionFactory工厂对象

sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

} catch (IOException e) {

 throw new RuntimeException("加载Mybatis配置文件失败");

}

}

// 获取SqlSession会话对象

public static SqlSession openSession() {

return sqlSessionFactory.openSession();

}

}

2、抽取测试类代码基类

public class TestBaseMapper {

protected SqlSession sqlSession = null;

 

@Before

 public void before() {

sqlSession = MyBatisUtils.openSession();

}

@After

public void after() {

sqlSession.commit();

sqlSession.close();

}

}

3、使用工具类完成操作

public class UserTest extends TestBaseMapper {

@Test public void testFindAll() throws Exception {

// 执行

sql List<User> list = sqlSession.selectList("PersonMapper.findAll");

for (User user : list) {

System.out.println(user);

}

}

 }

(三) MyBatis核心配置文件详解

1MyBatis核心配置文件层级关系

 

2environments标签

数据库环境的配置,支持多环境配置

 

(1) 其中,事务管理器(transactionManager)类型有两种:

* JDBC: 这个配置就是直接使用了JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。

* MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期。 例如:mybatisSpring整合后,事务交给Spring容器管理。

(2) 其中,数据源(dataSource)类型有三种:

* UNPOOLED: 这个数据源的实现只是每次被请求时打开和关闭连接。

* POOLED:这种数据源的实现利用的概念将 JDBC 连接对象组织起来。

* JNDI: 这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据 源,然后 放置一个 JNDI 上下文的引用

 

3mappers标签

该标签的作用是加载映射的,加载方式有如下几种:

(1) 使用相对于类路径的资源引用,

例如: <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>

(2) 使用完全限定资源定位符(URL),

例如: <mapper url="file:///var/mappers/AuthorMapper.xml"/>

(3) 使用映射器接口实现类的完全限定类名,

例如: <mapper class="org.mybatis.builder.AuthorMapper"/>

(4) 将包内的映射器接口实现全部注册为映射器,例如:

<package name="org.mybatis.builder"/>

 

4properties标签

实际开发中,习惯将数据源的配置信息单独抽取成一个properties文件,该标签可以加载额外配置的properties

<properties resource="org/mybatis/example/jdbc.properties">

 

5typeAliases标签

类型别名是为 Java 类型设置一个短的名字。

为了简化映射文件 Java 类型设置,mybatis框架为我们设置好的一些常用的类型的别名:

 

原来的类型名称配置如下:

 

 

配置typeAliases,为com.offcn.bean.Person定义别名为person,SqlMapConfig.xml配置别名:

<typeAliases>

  <typeAlias alias="person" type="com.offcn.bean.Person"/>

</typeAliases>

PersonMapper.xml中使用别名:

<select id="findAll" resultType="person">

    select * from  person

</select>

(四) MyBatis核心API概述

1Resources

加载mybatis的配置文件。

// 加载核心配置文件

InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");

 

2SqlSessionFactoryBuilder

利用Resources指定的资源,将配置信息加载到内存中,还会加载mybatis配置文件中指定的所有映射配置信息,并

用特定的对象实例进行保存,从而创建SqlSessionFactory对象。

// 构建SqlSessionFactory对象

SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(inputStream);

 

3SqlSessionFactory

这是一个工厂对象,对于这种创建和销毁都非常耗费资源的重量级对象,一个项目中只需要存在一个即可。 也就是说,它的生命周期跟项目的生命周期是一致的(项目不亡,我不销毁)

它的任务是创建SqlSession

// 默认开启一个事务,但事务不会自动提交,需要手动提交事务,DML语句才会持久化到数据库中

SqlSession openSession();

 // 参数为是否开启自动提交,如果设置为true,那么不需要手动提交事务

SqlSession openSession(boolean autoCommit);

 

4SqlSession

这是Mybatis的一个核心对象。我们基于这个对象可以实现对数据的CRUD操作。

对于这个对象应做到每个线程独有,每次用时打开,用完关闭。

执行语句的方法主要有:

<T> T selectOne(String statement, Object parameter);

<E> List<E> selectList(String statement, Object parameter);

int insert(String statement, Object parameter);

int update(String statement, Object parameter);

int delete(String statement, Object parameter);

 

(五) MyBatis的执行原理

 

详细流程如下:

1、加载mybatis全局配置文件(数据源、mapper映射文件等),解析配置文件,MyBatis基于XML配置文件生成Configuration,和一个个MappedStatement(包括了参数映射配置、动态SQL语句、结果映射配置),其对应着<select | update | delete | insert>标签项。

2SqlSessionFactoryBuilder通过Configuration对象生成SqlSessionFactory,用来开启SqlSession

3SqlSession对象完成和数据库的交互:

1用户程序调用mybatis接口层api(即Mapper接口中的方法)

2SqlSession通过调用apiStatement ID找到对应的MappedStatement对象

3通过Executor(负责动态SQL的生成和查询缓存的维护)将MappedStatement对象进行解析,sql参数转化、动态sql拼接,生成jdbc Statement对象

4JDBC执行sql

5借助MappedStatement中的结果映射关系,将返回结果转化成HashMapJavaBean等存储结构并返回。

三、MyBatis基于接口代理方式实现Dao层开发

(一)基于接口代理方式实现Dao的开发

1、介绍

采用 Mybatis 的基于接口代理方式实现 持久层 的开发,这种方式是我们后面进入企业的主流。

基于接口代理方式的开发只需要程序员编写 Mapper 接口,Mybatis 框架会为我们动态生成实现类的对象。

这种开发方式要求我们遵循一定的规范:

Mapper.xml映射文件中的namespacemapper接口的全限定名相同

Mapper接口方法名和Mapper.xml映射文件中定义的每个statementid相同

Mapper接口方法的输入参数类型和mapper.xml映射文件中定义的每个sqlparameterType的类型相同

Mapper接口方法的输出参数类型和mapper.xml映射文件中定义的每个sqlresultType的类型相同

 

2、实现步骤

1) 编写接口 PersonMapper

public interface UserMapper {

public List<User> findAll() throws Exception;

}

2) 编写PersonMapper.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.offcn.mapper.PersonMapper">

   <!--查询所有-->

   <select id="findAll" resultType="person">

select  *  from  person

   </select>

</mapper>

3)测试

@Test

public void testFindAll() throws Exception {

// 加载核心配置文件

InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");

// 获得SqlSessionFactory工厂对象

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

// 获得SqlSession会话对象

SqlSession sqlSession = sqlSessionFactory.openSession();

// 获得Mapper代理对象

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

// 执行查询

List<User> list = userMapper.findAll(); for (User user : list) {

System.out.println(user);

}

// 释放资源

sqlSession.close();

}

3、基于代理实现的内部执行原理

我们的持久层现在只有一个接口,而接口是不实际干活的,那么是谁在做findAll的实际工作呢?

下面通过追踪源码看一下:

1)通过追踪源码我们会发现,我们使用的mapper实际上是一个代理对象,是由MapperProxy代理产生的。

 

2)追踪MapperProxyinvoke方法会发现,其最终调用了mapperMethod.execute(sqlSession, args)

 

3)进入execute方法会发现,最终工作的还是sqlSession

 

(二) MyBatis高级查询

1ResultMap标签

如果数据库结果集中的列名和要封装的javaBean的属性名有不一致的情况下,我们查询的结果中不一致的属性值会为null,这个时候我们可以使用 resultMap 标签手动的建立映射关系,很好的解决数据不对应的问题。

 

(1) 编写接口PersonMapper

public interface PersonMapper {

public List<User> findAllResultMap();

}

(2) 编写PersonMapper.xml

<mapper namespace="com.offcn.mapper.PersonMapper">

<!--手动映射对象-->

<resultMap id="personResultMap" type="person">

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

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

<result column="bir" property="bir"></result>

<result column="address" property="address"></result>

</resultMap>

<!--查询所有 resultMap-->

<select id="findAllResultMap" resultMap="personResultMap">

select id as id, name, bir, address from person

</select>

</mapper>

(3) 测试

@Test

public void testFindAllResultMap() throws Exception {

PersonMapper personMapper = sqlSession.getMapper(PersonMapper .class);

List<Person> list = personMapper .findAllResultMap();

for (Person person : list) {

  System.out.println(person);

}

}

(三) MyBatis多参数处理

MyBatis中方法中出现了多个参数的处理方式:

 

1、第一种使用方法索引

使用java方法的默认规范,参数是有索引,我们需要在sql中指定参数的的索引位置

<select>

select * from person where id=#{参数索引} and name=#{参数索引}  

</select>

 

2、第二种mapkey

使用map集合的方式传入多个参数值,在sql中我们使用map中的key来映射值

<select>

select * from person where id=#{mapkey} and name=#{mapkey}

</select>

 

3、第三种使用注解

使用MyBatis的注解 @Param("定义参数在sql中的应用名称"),在定义方法的时候声明sql中使用参数的名字

<select>

select * from person where id=#{ddi} and name=#{nnmae}

</select>

 

3、 第四种 使用自身封装的对象

<select>

select * from person where id=#{id} and name=#{name}

</select>

(四) 模糊查询

1、占位符方式

1)构建PersonMapper接口

public interface PersonMapper {

public List<Person> findByName(String name);

}

 

2)构建PersonMapper.xml

<mapper namespace="com.offcn.mapper.PersonMapper">

<select id="findByName" parameterType="string" resultType="person">

  select * from person where name like #{name}

</select>

</mapper>

 

3)测试

@Test

public void testFindByUsername() throws Exception {

PersonMapper personMapper= sqlSession.getMapper(PersonMapper.class);

List<Person> list = personMapper.findByName("%%");

for (Person person: list) {

System.out.println(person);

}

}

2、字符串拼接方式

1)构建PersonMapper接口

public interface PersonMapper{

public List<Person> findByName(String name);

}

 

2)构建PersonMapper.xml

<mapper namespace="com.offcn.mapper.PersonMapper">

<!-- 不推荐使用,因为Oracle数据库 除了设置别名其余位置不能使用 双引号 -->

<select id="findByName" parameterType="string" resultType="person">

select * from person where name like "%"#{name}"%"

</select>

</mapper>

 

3)测试

@Test

public void testFindByUsername() throws Exception {

PersonMapper personMapper= sqlSession.getMapper(PersonMapper.class);

List<Person>  list = personMapper.findByName("");

for (Person person: list) {

System.out.println(person);

}

}

3$的拼接方式

(3)构建PersonMapper 接口

public interface PersonMapper {

public List<Person> findByName(String name);

}

 

构建PersonMapper.xml

<mapper namespace="com.offcn.mapper.PersonMapper ">

<!--不推荐使用,因为会出现sql注入问题-->

<select id="findByName" parameterType="string" resultType="person">

select * from person where name like '%${value}%'

</select>

</mapper>

测试

@Test

public void testFindByName() throws Exception {

PersonMapper personMapper= sqlSession.getMapper(PersonMapper.class);

List<Person>  list = personMapper.findByName("");

for (Person person: list) {

System.out.println(person);

}

}

4、使用函数拼接数据

1)构建PersonMapper 接口

public interface PersonMapper {

public List<Person> findByName(String name);

}

 

2)构建PersonMapper.xml

<mapper namespace="com.offcn.mapper.PersonMapper">

<!-- 推荐使用,concat() 字符串拼接函数 注意:在Oracle中,concat() 函数只能传递二次参数,我们解决方案是嵌套拼接 -->

<select id="findByName" parameterType="string" resultType="person">

select * from person where name like concat(concat('%',#{name}),'%');

</select>

</mapper>

 

3)测试

@Test

public void testFindByName() throws Exception {

PersonMapper personMapper= sqlSession.getMapper(PersonMapper.class);

List<Person>  list = personMapper.findByName("");

for (Person person: list) {

System.out.println(person);

}

}

 

总结:${} #{} 区别

#{} :表示一个占位符号

通过 #{} 可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。#{} 可以接收简单类型值或pojo属性值。

如果parameterType传输单个简单类型值, #{} 括号中可以是value或其它名称。

 

${} :表示拼接sql

通过 ${} 可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换,会出现sql注入问题。

${} 可以接收简单类型值或pojo属性值。如果parameterType传输单个简单类型值, ${} 括号中可以使任意名称

 

原文地址:https://www.cnblogs.com/masterhxh/p/13806928.html