Mybatis笔记(一)


什么是 MyBatis?

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

MyBatis第一个程序

  1. 创建数据库
  2. 创建一个maven项目在主配置文件pom.xml中导入MyBatis相关 jar 包如下:

   org.mybatis
   mybatis
   3.5.2


   mysql
   mysql-connector-java
   5.1.47

      3.编写MyBatis核心配置文件

<?xml version="1.0" encoding="UTF-8" ?>


   
       
           
           
               
               
               
               
           
       
   
   
       
   

4.创建实体类

public class User implements Serializable {

    private Integer userId;
    private String userName;
    private String userAddress;
    private String userSex;
    private Date userBirthday;
    //构造函数
    //get set方法

5.编写Mapper接口

IUserDao 接口就是我们的持久层接口(也可以写成 UserDao 或者 UserMapper)

public interface IUserDao {
List findAll();
}

6.编写Mapper接口对应的xml文件

  • namespace 十分重要,不能写错!

  • namespace命名空间

    它的包名必须与mapper接口名一致

    namespace="com.itheima.dao.IUserMapper"

  • 编写持久层接口的映射文件 IUserDao.xml

    创建位置:必须和持久层接口在相同的包中。

    名称:必须以持久层接口名称命名文件名,扩展名是.xml

<?xml version="1.0" encoding="UTF-8" ?>


 

 7.编写测试类

public class MybatisTest {

    private InputStream in;
    private SqlSession sqlSession;
    private IUserDao userDao;

    @Before//用于在测试方法执行之前执行
    public void init()throws Exception{
        //1.读取配置文件,生成字节输入流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.获取SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //3.获取SqlSession对象
        sqlSession = factory.openSession();
        //4.获取dao的代理对象
        userDao = sqlSession.getMapper(IUserDao.class);
    }
	@Test
    public void testFindAll(){
        List user = UserMapper.FindAll();
        for(User role : user){
            System.out.println(role);

        }
    }
    @After//用于在测试方法执行之后执行
    public void destroy()throws Exception{
        //提交事务
        sqlSession.commit();
        //6.释放资源
        sqlSession.close();
        in.close();
    }

可能出现问题说明:Maven静态资源过滤问题


   
       src/main/java
       
           **/*.properties
           **/*.xml
       
       false
   
   
       src/main/resources
       
           **/*.properties
           **/*.xml
       
       false
   

Mybatis的CRUD

select

  • select标签是mybatis中最常用的标签之一

  • select语句有很多属性可以详细配置每一条SQL语句

    • SQL语句返回值类型。【完整的类名或者别名】

    • 传入SQL语句的参数类型 。【万能的Map,可以多尝试使用】

    • 命名空间中唯一的标识符

    • 接口中的方法名与映射文件中的SQL语句ID 一一对应

    • id    //方法名

    • parameterType   //参数类型

    • resultType         //返回值类型

需求:根据id查询用户

1、在UserMapper中添加对应方法

public interface UserMapper {
   //查询全部用户
   List selectUser();
   //根据id查询用户
   User selectUserById(int id);
}

2、在UserMapper.xml中添加Select语句

3、编写测试

@Test
public void tsetSelectUserById() {
   User user = mapper.selectUserById(1);
   System.out.println(user);  
}

万能的Map(方法二)

1、在接口方法中,参数直接传递Map;

User selectUserByNP2(Map map);

2、编写sql语句的时候,需要传递参数类型,参数类型为map

3、在使用方法的时候,Map的 key 为 sql中取的值即可,没有顺序要求!

Map map = new HashMap();
map.put("username","小明");
map.put("pwd","123456");
User user = mapper.selectUserByNP2(map);

总结:如果参数过多,我们可以考虑直接使用Map实现,如果参数比较少,直接传递参数即可!

Insert

需求:给数据库增加一个用户

1、在UserMapper接口中添加对应的方法

//添加一个用户
int addUser(User user);

2、在UserMapper.xml中添加insert语句


    insert into user (id,name,pwd) values (#{id},#{name},#{pwd})

 3、测试

@Test
public void testAddUser() {  
   User user = new User(5,"王五","zxn");
   int i = mapper.addUser(user);
   System.out.println(i);
   
}

Update

需求:修改用户的信息

1、编写接口方法

//修改一个用户
int updateUser(User user);

2、编写对应的配置文件SQL


  update user set name=#{name},pwd=#{pwd} where id = #{id}

3、测试

@Test
public void testUpdateUser() {
   User user = mapper.selectUserById(1);
   user.setPwd("asdfgh");
   int i = mapper.updateUser(user);
   System.out.println(i);
   
}

delete

需求:根据id删除一个用户

1、编写接口方法

//根据id删除用户
int deleteUser(int id);

2、编写对应的配置文件SQL


  delete from user where id = #{id}

3、测试

@Test
public void testDeleteUser() {
   
   int i = mapper.deleteUser(5);
   System.out.println(i);
  
}

模糊查询

1. **(常用)**

  `
  2.` 
  `
  我们在上面将原来的#{}占位符,改成了${value}。注意如果用模糊查询的这种写法,那么${value}的写法就是固定的,不能写成其它名字。

配置解析

核心配置文件

  • mybatis-config.xml 系统核心配置文件

  • MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。

  • 能配置的内容如下:

configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

environments元素


 
   
     
   
   
     
     
     
     
   
 
  • 配置MyBatis的多套运行环境,将SQL映射到多个不同的数据库上,必须指定其中一个为默认运行环境(通过default指定)

  • 子元素节点:environment

    • dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。

    • 数据源是必须配置的。

    • 有三种内建的数据源类型

      type="[UNPOOLED|POOLED|JNDI]")
    • unpooled:这个数据源的实现只是每次被请求时打开和关闭连接。

    • pooled:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来 , 这是一种使得并发 Web 应用快速响应请求的流行处理方式。

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

    • 数据源也有很多第三方的实现,比如dbcp,c3p0,druid等等....

    • 这两种事务管理器类型都不需要设置任何属性。

    • 具体的一套环境,通过设置id进行区别,id保证唯一!

    • 子元素节点:transactionManager - [ 事务管理器 ]

      
      
    • 子元素节点:数据源(dataSource)

mappers元素

mappers

  • 映射器 : 定义映射SQL语句文件

  • 既然 MyBatis 的行为其他元素已经配置完了,我们现在就要定义 SQL 映射语句了。但是首先我们需要告诉 MyBatis 到哪里去找到这些语句。Java 在自动查找这方面没有提供一个很好的方法,所以最佳的方式是告诉 MyBatis 到哪里去找映射文件。你可以使用相对于类路径的资源引用, 或完全限定资源定位符(包括 file:/// 的 URL),或类名和包名等。映射器是MyBatis中最核心的组件之一,在MyBatis 3之前,只支持xml映射器,即:所有的SQL语句都必须在xml文件中配置。而从MyBatis 3开始,还支持接口映射器,这种映射器方式允许以Java代码的方式注解定义SQL语句,非常简洁。

引入资源方式



 


 


 


 

Mapper文件

<?xml version="1.0" encoding="UTF-8" ?>


   
  • namespace中文意思:命名空间,作用如下:

    • namespace的命名必须跟某个接口同名

    • 接口中的方法与映射文件中sql语句id应该一一对应

    1. namespace和子元素的id联合保证唯一  , 区别不同的mapper

    2. 绑定DAO接口

    3. namespace命名规则 : 包名+类名

MyBatis 的真正强大在于它的映射语句,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 为聚焦于 SQL 而构建,以尽可能地为你减少麻烦。

Properties优化

数据库这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。具体的官方文档

我们来优化我们的配置文件

第一步 ; 在资源目录下新建一个db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8
username=root
password=123456

第二步 : 将文件导入properties 配置文件


   
   

   
       
           
           
               
               
               
               
           
       
   
   
       
   

typeAliases优化

类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。



   

当这样配置时,User可以用在任何使用com.han.pojo.User的地方。

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:


   

每一个在包 com.kuang.pojo 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。

若有注解,则别名为其注解值。见下面的例子:

@Alias("user")
public class User {
  ...
}

去官网查看一下Mybatis默认的一些类型别名!

ResultMap及分页

ResultMap主要解决的问题是字段名和属性名不一致的问题!

解决方案:

方案一:

为列名起别名保证列名和java实体类属性名一致

方案二:

ResultMap结果集映射


   
   
   
   
   


其中: id 标签:用于指定主键字段

  result 标签:用于指定非主键字段

  column 属性:用于指定数据库列名

  property 属性:用于指定实体类属性名称

分页查询

limit实现分页

#语法
SELECT * FROM table LIMIT stratIndex,pageSize

SELECT * FROM table LIMIT 5,10; // 检索记录行 6-15  

#为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1:   
SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last.  

#如果只给定一个参数,它表示返回最大的记录行数目:   
SELECT * FROM table LIMIT 5; //检索前 5 个记录行  

#换句话说,LIMIT n 等价于 LIMIT 0,n。 

步骤:

1、修改Mapper文件

2、Mapper接口,参数为map

//选择全部用户实现分页
List selectUser(Map map);

3、在测试类中传入参数测试

  • 推断:起始位置 =  (当前页面 - 1 ) * 页面大小

//分页查询 , 两个参数startIndex , pageSize
@Test
public void testSelectUser() {
   SqlSession session = MybatisUtils.getSession();
   UserMapper mapper = session.getMapper(UserMapper.class);

   int currentPage = 1;  //第几页
   int pageSize = 2;  //每页显示几个
   Map map = new HashMap();
   map.put("startIndex",(currentPage-1)*pageSize);
   map.put("pageSize",pageSize);

   List users = mapper.selectUser(map);

   for (User user: users){
       System.out.println(user);
  }

   session.close();
}

RowBounds分页

步骤:

1、mapper接口

//选择全部用户RowBounds实现分页
List getUserByRowBounds();

2、mapper文件

3、测试类

在这里,我们需要使用RowBounds类

@Test
public void testUserByRowBounds() {
   SqlSession session = MybatisUtils.getSession();

   int currentPage = 2;  //第几页
   int pageSize = 2;  //每页显示几个
   RowBounds rowBounds = new RowBounds((currentPage-1)*pageSize,pageSize);

   //通过session.**方法进行传递rowBounds,[此种方式现在已经不推荐使用了]
   List users = session.selectList("com.kuang.mapper.UserMapper.getUserByRowBounds", null, rowBounds);

   for (User user: users){
       System.out.println(user);
  }
   session.close();
}