Mybatis初级讲解

1. 总结 jdbc 开发的问题
1.       频繁创建数据库连接对象、释放,容易造成系统资源浪费,影响系统性能。企业项目中可以使用连接池解决这个问题,但是使用Jdbc 需要自己实现连接池。mybatis 已经提供了连接池。
2.       sql 语句定义、参数设置、结果集处理存在硬编码。企业项目中,sql 语句变化的可能性较大,一旦发生变化,需要修改Java 代码,系统需要重新编译,重新发布。不好维护。
3.       结果集处理存在重复代码,处理麻烦。如果可以映射为java 对象会比较方便。
 
2.    mybatis 介绍
mybatis Apache 软件基金会下的一个开源项目,前身是Ibatis 框架。2010 年这个项目由apache 软件基金会迁移到google code 下,改名为mybatis 2013 11 月又迁移到了github https://github.com/mybatis/mybatis-3/releases )。
mybatis 是一个 持久层 的框架,是对JDBC 操作数据库的封装,使开发者 只需要 关注业务本身, 不需要 花费精力去处理加载驱动、创建数据库连接对象、创建statement 语句对象、参数设置、结果集处理等一系列 繁杂的 过程代码。
mybatis 通过xml 或注解进行配置,将java 对象与sql 语句中的参数 自动映射 生成最终执行的sql 语句,并将sql 语句执行结果 自动映射 java 对象,返回给业务层(service )应用。
 
3.    mybatis 入门程序
3.1. 需求
实现用户表(user )增、删、改、查操作。
1.       根据用户Id 查询用户
2.       根据用户名称模糊查询用户
3.       新增用户
4.       根据用户Id 修改用户
5.       根据用户Id 删除用户
 
3.2. 需求实现
3.2.1. 配置 pom.xml 文件,加入 mybatis 依赖
< project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
< modelVersion > 4.0.0 </ modelVersion >
 
< groupId > cn.itheima </ groupId >
< artifactId > mybatis -first </ artifactId >
< version > 0.0.1-SNAPSHOT </ version >
 
< packaging > jar </ packaging >
 
< name > mybatis -first </ name >
< url > http://maven.apache.org </ url >
 
< properties >
     < project.build.sourceEncoding > UTF-8 </ project.build.sourceEncoding >
     <!-- mysql 版本 -->
     < mysql.version > 5.1.30 </ mysql.version >
     <!-- junit 版本 -->
     < junit.version > 4.12 </ junit.version >
     <!-- mybatis 版本号 -->
     <mybatis.version>3.4.5</mybatis.version>
     <!-- log4j日志包版本 -->
     <slf4j.version>1.7.7</slf4j.version>
     <log4j.version>1.2.17</log4j.version>
</ properties >
 
< dependencies >
     <!-- mysql 数据库依赖 -->
     < dependency >
         < groupId > mysql </ groupId >
         < artifactId > mysql -connector-java </ artifactId >
         < version > ${mysql.version} </ version >
     </ dependency >
     <!-- mybatis 核心包 -->
     <dependency>
         <groupId>org.mybatis</groupId>
         <artifactId> mybatis </artifactId>
         <version>${mybatis.version}</version>
     </dependency>
     <!-- log4j日志包 -->
     <dependency>
         <groupId>log4j</groupId>
         <artifactId>log4j</artifactId>
         <version>${log4j.version}</version>
     </dependency>
     <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j- api </artifactId>
         <version>${slf4j.version}</version>
     </dependency>
     <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-log4j12</artifactId>
         <version>${slf4j.version}</version>
     </dependency>
     <!-- junit 依赖 -->
     < dependency >
         < groupId > junit </ groupId >
         < artifactId > junit </ artifactId >
         < version > ${junit.version} </ version >
         < scope > test </ scope >
     </ dependency >
</ dependencies >
</ project >
 
3.2.2. 准备配置文件
3.2.2.1. sqlMapConfig.xml
说明:mybatis 框架核心配置文件。
<? 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 >
 
<!-- 运行环境配置 -->
<!-- default属性:指定使用哪一个运行环境 -->
< environments default = "development" >
     <!-- id属性:唯一标识一个运行环境 -->
     < environment id = "development" >
         <!-- 事务管理器配置,JDBC:mybatis默认使用 jdbc 事务 -->
        < transactionManager type = "JDBC" />
        
         <!-- 数据源配置,POOLED:mybatis提供的连接池 -->
         < dataSource type = "POOLED" >
             < property name = "driver" value = "com.mysql.jdbc.Driver" />
             < property name = "url" value = "jdbc:mysql://127.0.0.1:3306/mybatis" />
             < property name = "username" value = "root" />
             < property name = "password" value = "admin" />
         </ dataSource >
     </ environment >
</ environments >
</ configuration >
 
3.2.2.2. log4j.properties
# Global logging configuration
log4j.rootLogger= DEBUG, stdout
 
# Console output...
log4j.appender.stdout= org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout= org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= %5p [%t] - %m%n
 
3.2.3. 准备用户 pojo
public class User {
  private Integer id ; // int (11) NOT NULL AUTO_INCREMENT,
  private String username ; // varchar (32) NOT NULL COMMENT '用户名称',
  private Date birthday ; // date DEFAULT NULL COMMENT '生日',
  private String sex ; // char(1) DEFAULT NULL COMMENT '性别',
  private String address ; // varchar (256) DEFAULT NULL COMMENT '地址',
/**
 * @return the id
 */
public Integer getId() {
     return id ;
}
/**
 * @param id the id to set
 */
public void setId(Integer id) {
     this . id = id;
}
/**
 * @return the username
 */
public String getUsername() {
     return username ;
}
/**
 * @param username the username to set
 */
public void setUsername(String username) {
     this . username = username;
}
/**
 * @return the birthday
 */
public Date getBirthday() {
     return birthday ;
}
/**
 * @param birthday the birthday to set
 */
public void setBirthday(Date birthday) {
     this . birthday = birthday;
}
/**
 * @return the sex
 */
public String getSex() {
     return sex ;
}
/**
 * @param sex the sex to set
 */
public void setSex(String sex) {
    this . sex = sex;
}
/**
 * @return the address
 */
public String getAddress() {
     return address ;
}
/**
 * @param address the address to set
 */
public void setAddress(String address) {
     this . address = address;
}
/* (non- Javadoc )
 * @see java.lang.Object#toString()
 */
@Override
public String toString() {
     return "User [id=" + id + ", username=" + username + ", birthday="
             + birthday + ", sex=" + sex + ", address=" + address + "]" ;
}
 
 
 
}
 
3.2.4. 准备 sql 语句
select * from `user` where id=24
 
3.2.5. 准备 mapper 映射文件
说明:用于配置java 对象,与sql 语句的对应关系。
<? 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" >
<!-- namespace 属性:名称空间,相当于java中的package,用于放置 sql 语句冲突 -->
< mapper namespace = "test" >
<!--说明: mybatis 框架针对每一种 sql 语句:新增/修改/删除/查询,提供了对应的标签:
insert/update/delete/select来放置  -->
 
<!-- 根据用户Id查询用户,说明:
 select标签:用于放置查询 sql 语句
 id属性:唯一标识一条 sql 语句
 parameterType属性:输入参数类型
 resultType属性:返回值类型
 #{id}:占位符,相当于 jdbc 中的问号:?-->
< select id = "queryUserById" parameterType = "int" resultType = "cn.itheima.mybatis.po.User" >
     select * from `user` where id=#{id}
</ select >
 
</ mapper >
 
 
3.2.6. sqlMapcConfig.xml 文件中,加载 User.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 >
 
<!-- 运行环境配置 -->
<!-- default属性:指定使用哪一个运行环境 -->
< environments default = "development" >
     <!-- id属性:唯一标识一个运行环境 -->
     < environment id = "development" >
         <!-- 事务管理器配置,JDBC:mybatis默认使用 jdbc 事务 -->
         < transactionManager type = "JDBC" />
        
         <!-- 数据源配置,POOLED:mybatis提供的连接池 -->
         < dataSource type = "POOLED" >
             < property name = "driver" value = "com.mysql.jdbc.Driver" />
             < property name = "url" value = "jdbc:mysql://127.0.0.1:3306/mybatis" />
             < property name = "username" value = "root" />
             < property name = "password" value = "admin" />
         </ dataSource >
     </ environment >
</ environments >
<!-- 加载 mapper 映射文件 -->
<mappers>
     <!--加载User.xml文件,说明:
       resource属性:指定配置文件的位置-->
     <mapper resource= "sqlmap/User.xml" />
</mappers>
</ configuration >
 
3.2.7. 编写测试代码
public class MybatisTest {
// 1.测试根据用户Id查询用户
@Test
public void queryUserByIdTest() throws IOException{
    
     // 1.加载核心配置文件:sqlMapConfig.xml
     // resource属性:指定核心配置文件位置
     InputStream inputStream = Resources. getResourceAsStream ( "sqlMapConfig.xml" );
    
     // 2.读取配置文件内容
     SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
     // SqlSessionFactory对象: mybatis 框架的核心对象,一个项目中只需要一个(单例设计模式)
     SqlSessionFactory sqlSessionFactory = builder.build(inputStream);
    
     // 3.使用SqlSessionFactory对象,创建sqlSession对象
     // sqlSession对象:
     // 3.1相当于 jdbc 中的connection对象
     // 3.2 sqlSession对象是线程不安全,每一个执行操作的方法,都需要创建一个sqlSession对象
     SqlSession sqlSession = sqlSessionFactory.openSession();
    
     // 4.使用sqlSession对象,调用方法执行
     // selectOne方法:查询单条记录
     // statement参数:执行的 sql 语句(名称空间+ sql 语句Id)
     // parameter参数:传入的参数值
     Object user = sqlSession.selectOne( "test.queryUserById" , 24);
     System. out .println(user);
    
     // 5.释放资源
     sqlSession.close();
    
}
 
}
 
 
3.3. 其他需求实现
3.3.1. 根据用户名称模糊查询用户
3.3.1.1. 准备 sql 语句
select * from `user` where username like '% 小明 %'
 
 
3.3.1.2. 配置映射文件
<!-- 根据用户名称模糊查询用户,说明 -->
< select id = "queryUserByName" parameterType = "string" resultType = "cn.itheima.mybatis.po.User" >
     select * from `user` where username like #{ username }
</ select >
 
3.3.1.3. 编写测试代码
// 2.测试根据用户名称模糊查询用户
@Test
public void queryUserByNameTest () throws IOException{
     // 1.加载核心配置文件
     InputStream inputStream = Resources. getResourceAsStream ( "sqlMapConfig.xml" );
    
     // 2.读取配置文件内容
     SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
     SqlSessionFactory sqlSessionFactory = builder.build(inputStream);
    
     // 3.使用sqlSessionFactory对象,创建sqlSession对象
     SqlSession sqlSession = sqlSessionFactory.openSession();
    
     // 4.使用sqlSession对象,调用方法执行
     // selectList方法:查询多条记录
     // statement参数:执行的 sql 语句(名称空间+ sql 语句Id)
     // parameter参数:传入的参数值
     List<Object> list = sqlSession.selectList( "test.queryUserByName" , "%小明%" );
     for (Object o :list){
         System. out .println(o);
     }
    
    // 5.释放资源
     sqlSession.close();
}
 

 
3.3.1.4. 使用字符串拼接符 ${} ,拼接参数
<!-- 根据用户名称模糊查询用户,说明 -->
< select id = "queryUserByName" parameterType = "string" resultType = "cn.itheima.mybatis.po.User" >
     <!-- select * from `user` where username like #{ username } -->
    
     <!--  where username like '%小明%',说明:
     使用字符串拼接符${},拼接参数 -->
     select * from `user` where username like '%${value}%'
</ select >
 

 
3.3.1.5. 占位符 #{} 与字符串拼接符 ${} 区别
1.             占位符#{} ,相当于jdbc 中的问号? ,当参数传递的是 java 简单类型 的时候,花括号中的内容可以是任意字符串。
2.             字符串拼接符 ${} ,当参数传递的是 java 简单类型 的时候,花括号中的内容只能是:value
3.             sql 语句中使用字符串拼接符${} ,可能引起sql 注入的问题。但是mybatis 中字符串拼接符可以使用,原因是是后端dao 层的开发,项目中参数传递经过表现层(action ),业务层(service )已经处理好。
 
3.3.2. 新增用户
3.3.2.1. 准备 sql 语句
insert into `user`(id,username,birthday,sex,address) values(2,' 小李飞刀 ','2017-11-06','1',' 来自明朝 ')
 
3.3.2.2. 配置映射文件
<!-- 新增用户,说明
insert标签:用于放置新增 sql 语句
#{id}:占位符,当参数传递的是 pojo 的时候,换括号中的内容是 pojo 的属性 -->
  < insert id = "insertUser" parameterType = "cn.itheima.mybatis.po.User" >
    insert into `user`(id, username ,birthday,sex,address)
    values(#{id},#{ username },#{birthday},#{sex},#{address})
  </ insert >
 
3.3.2.3. 编写测试代码
// 3.测试新增用户
@Test
public void insertUserTest (){
     // 1.创建sqlSession对象
     SqlSession sqlSession = sqlSessionFactory .openSession();
    
     // 2.使用sqlSession对象,调用方法执行
     // insert方法:新增记录
     // statement参数:执行的 sql 语句(名称空间+ sql 语句Id)
     // parameter参数:传入的参数值
     // 创建用户对象
     User user  = new User();
     user.setId(3);
     user.setUsername( "林诗音" );
     user.setBirthday( new Date());
     user.setSex( "2" );
     user.setAddress( "来自大明朝" );
    
     sqlSession.insert( "test.insertUser" , user);
    
     // 3.释放资源
     sqlSession.close();
    
}
 

 
问题: java 程序执行成功,但是数据库中并没有林诗音的数据,原因是没有提交事务。
 
 
3.3.2.4. 提交事务
3.3.2.4.1. 方式一
// 3.测试新增用户
@Test
public void insertUserTest (){
     // 1.创建sqlSession对象
     SqlSession sqlSession = sqlSessionFactory .openSession();
    
     // 2.使用sqlSession对象,调用方法执行
     // insert方法:新增记录
     // statement参数:执行的 sql 语句(名称空间+ sql 语句Id)
     // parameter参数:传入的参数值
     // 创建用户对象
     User user  = new User();
     user.setId(3);
     user.setUsername( "林诗音" );
     user.setBirthday( new Date());
     user.setSex( "2" );
     user.setAddress( "来自大明朝" );
    
     sqlSession.insert( "test.insertUser" , user);
    
     // 数据库提交事务:commit
     sqlSession.commit();
    
     // 3.释放资源
     sqlSession.close();
    
}
 
3.3.2.4.2. 方式二
// 3.测试新增用户
@Test
public void insertUserTest (){
     // 1.创建sqlSession对象
     //SqlSession sqlSession = sqlSessionFactory.openSession();
    
     // 创建sqlSession对象,指定自动提交事务。true:表示提交;false:表示不提交。默认是false
     SqlSession sqlSession =  this .sqlSessionFactory.openSession( true );
    
     // 2.使用sqlSession对象,调用方法执行
     // insert方法:新增记录
     // statement参数:执行的 sql 语句(名称空间+ sql 语句Id)
     // parameter参数:传入的参数值
     // 创建用户对象
     User user  = new User();
     user.setId(4);
     user.setUsername( "林诗音" );
     user.setBirthday( new Date());
     user.setSex( "2" );
     user.setAddress( "来自大明朝" );
    
     sqlSession.insert( "test.insertUser" , user);
    
     // 数据库提交事务:commit
     //sqlSession.commit();
    
     // 3.释放资源
     sqlSession.close();
    
}
 
 
问题:用户表中 id 是自增长,不需要传递,但是 mybatis 中如何获取到新增以后的用户 Id ???
 
mysql 数据库查询新增Id
select LAST_INSERT_ID()
 
3.3.2.5. 获取新增的用户 Id
3.3.2.5.1. 方式一
<!-- 新增用户,说明
insert标签:用于放置新增 sql 语句
#{id}:占位符,当参数传递的是 pojo 的时候,换括号中的内容是 pojo 的属性-->
  < insert id = "insertUser" parameterType = "cn.itheima.mybatis.po.User" >
    <!-- insert into `user`(id, username ,birthday,sex,address)
    values(#{id},#{ username },#{birthday},#{sex},#{address}) -->
   
    <!-- selectKey标签:查询主键id,说明
     keyColumn属性:主键字段(表)
     keyProperty属性:主键属性( pojo
     resultType属性:指定主键字段类型
     order属性:指定在insert语句之前,还是之后获取主键值.
     BEFORE:在insert语句前;AFTER:在insert语句之后-->
    <selectKey keyColumn= "id" keyProperty= "id" resultType= "int" order= "AFTER" >
        select LAST_INSERT_ID()
    </selectKey>
    insert into `user`( username ,birthday,sex,address)
    values(#{ username },#{birthday},#{sex},#{address})
  </ insert >
 

 
3.3.2.5.2. 方式二
<!-- 新增用户,说明
insert标签:用于放置新增 sql 语句
#{id}:占位符,当参数传递的是 pojo 的时候,换括号中的内容是 pojo 的属性-->
  < insert id = "insertUser" parameterType = "cn.itheima.mybatis.po.User"
  useGeneratedKeys= "true" keyColumn= "id" keyProperty= "id" >
    <!-- insert into `user`(id, username ,birthday,sex,address)
    values(#{id},#{ username },#{birthday},#{sex},#{address}) -->
   
    <!-- selectKey标签:查询主键id,说明
     keyColumn属性:主键字段(表)
     keyProperty属性:主键属性( pojo
     resultType属性:指定主键字段类型
     order属性:指定在insert语句之前,还是之后获取主键值.
     BEFORE:在insert语句前;AFTER:在insert语句之后-->
    <!-- <selectKey keyColumn="id" keyProperty="id" resultType=" int " order="AFTER">
        select LAST_INSERT_ID()
    </selectKey> -->
    insert into `user`( username ,birthday,sex,address)
    values(#{ username },#{birthday},#{sex},#{address})
  </ insert >
 

 
3.3.3. 根据用户 Id 修改用户
3.3.3.1. 准备 sql 语句
update `user` set username=' 小李飞刀和林诗音 ',sex='2' where id=2
 
 
3.3.3.2. 配置映射文件
<!-- 根据用户id修改用户,说明:
  update标签:用于放置修改 sql 语句-->
  < update id = "updateUserById" parameterType = "cn.itheima.mybatis.po.User" >
    update `user`
    set username =#{ username },sex=#{sex} where id=#{id}
  </ update >
 
 
3.3.3.3. 编写测试代码
// 4.测试根据用户Id修改用户
@Test
public void updateUserByIdTest (){
     // 1.创建sqlSession对象
     SqlSession sqlSession = this . sqlSessionFactory .openSession( true );
    
     // 2.使用sqlSession对象,调用方法执行
     // update方法:修改记录
     // statement参数:执行的 sql 语句(名称空间+ sql 语句Id)
     // parameter参数:传入的参数值
     // 创建用户对象
     User user = new User();
     user.setId(3);
     user.setUsername( "林诗音和小李飞刀" );
     user.setSex( "1" );
    
     sqlSession.update( "test.updateUserById" , user);
    
     // 3.释放资源
     sqlSession.close();
}
 

 
3.3.4. 根据用户 Id 删除用户
3.3.4.1. 准备 sql 语句
delete from `user` where id=4
 
 
3.3.4.2. 配置映射文件
  <!-- 根据用户id删除用户,说明:
   delete标签:用于放置删除的 sql 语句-->
   < delete id = "deleteUserById" parameterType = "int" >
        delete from `user` where id=#{id}
   </ delete >
 
 
3.3.4.3. 编写测试代码
// 5.测试根据用户Id删除用户
@Test
public void deleteUserByIdTest (){
     // 1.创建sqlSession对象
     SqlSession sqlSession = this . sqlSessionFactory .openSession( true );
    
     // 2.使用sqlSession对象,调用方法执行
     // delete方法:删除记录
     // statement参数:执行的 sql 语句(名称空间+ sql 语句Id)
     // parameter参数:传入的参数值
     sqlSession.delete( "test.deleteUserById" , 35);
    
     // 3.释放资源
     sqlSession.close();
}
 

 
4.    mybatis 框架原理

1.       Configuration 配置对象:sqlMapConfig.xl User.xml......
2.       MappedStatement 对象:负责输入输出映射,ParameterType 参数输入,ResultType 返回值输出
3.       Executor 执行器对象:负责执行数据库的CRUD 操作
 
5.    mybatis 两种开发方法
1.       原始的dao 开发方法
2.       mapper 代理开发方法
 
 
5.1. 原始的 dao 开发方法
5.1.1. 需求
1.       根据用户Id 查询用户
2.       新增用户
 
5.1.2. 需求实现
5.1.2.1. 准备用户 dao 接口
public interface UserDao {
//   1.根据用户Id查询用户
User queryUserById(Integer id);
//   2.新增用户
void insertUser (User user);
 
}
 
 
5.1.2.2. 实现用户 dao 接口
public class UserDaoImpl implements UserDao {
// 定义sqlSessionFactory对象
private SqlSessionFactory sqlSessionFactory;
 
/**
 *
 */
public UserDaoImpl() {
     super ();
}
 
/**
 * @param sqlSessionFactory
 */
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
     super ();
     this . sqlSessionFactory = sqlSessionFactory;
}
 
/* (non- Javadoc )
 * @see cn.itheima.mybatis.dao.UserDao#queryUserById(java.lang.Integer)
 */
public User queryUserById(Integer id) {
     // TODO Auto-generated method stub
     // 1.创建sqlSession对象
     SqlSession sqlSession = this . sqlSessionFactory .openSession();
    
     // 2.使用sqlSession对象,调用方法执行
     Object user = sqlSession.selectOne( "test.queryUserById" , id);
    
     // 3.释放资源
     sqlSession.close();
    
     return (User) user;
}
 
/* (non- Javadoc )
 * @see cn.itheima.mybatis.dao.UserDao#insertUser(cn.itheima.mybatis.po.User)
 */
public void insertUser(User user) {
     // TODO Auto-generated method stub
     // 1.创建sqlSession对象
     SqlSession sqlSession = this . sqlSessionFactory .openSession( true );
    
     // 2.使用sqlSession对象,调用方法执行
     sqlSession.insert( "test.insertUser" , user);
    
     // 3.释放资源
     sqlSession.close();
 
}
 
}
 
5.1.2.3. 编写测试代码
public class UserDaoTest {
private SqlSessionFactory sqlSessionFactory = null ;
@Before
public void init() throws IOException{
    // 1.加载核心配置文件:sqlMapConfig.xml
     // resource属性:指定核心配置文件位置
     InputStream inputStream = Resources. getResourceAsStream ( "sqlMapConfig.xml" );
    
     // 2.读取配置文件内容
     SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
     // SqlSessionFactory对象: mybatis 框架的核心对象,一个项目中只需要一个(单例设计模式)
     sqlSessionFactory = builder.build(inputStream);
}
// 测试根据用户Id查询用户
@Test
public void queryUserByIdTest(){
    
     // 1.创建用户 dao 对象
     UserDao userDao = new UserDaoImpl( sqlSessionFactory );
    
     // 2.使用userDao对象,调用方法执行
     User user = userDao.queryUserById(2);
     System. out .println(user);
    
}
 
}
 

 
测试新增用户:
// 测试新增用户
@Test
public void insertUserTest (){
     // 1.创建用户 dao 对象
     UserDao userDao = new UserDaoImpl( sqlSessionFactory );
    
     // 2.使用userDao对象,调用方法执行
     // 创建用户对象
     User user = new User();
     user.setUsername( "阿飞" );
     user.setSex( "1" );
     user.setBirthday( new Date());
     user.setAddress( "来自大明朝" );
    
     System. out .println( "执行前:" +user);
     userDao.insertUser(user);
     System. out .println( "执行后:" +user);
}
 

 
5.2. mapper 代理开发方法
 
5.2.1. 注意事项
1.       要求mapper 映射文件中namespace 属性值,必须是mapper 接口的全路径(包名称+ 接口名称)
2.       要求mapper 映射文件中sql 语句的声明,与mapper 接口方法的声明一致
2.1.mapper 接口返回值类型,与sql 语句标签的resultType 属性指定的类型一致
2.2.mapper 接口的方法名称,与sql 语句id 属性值一致
2.3.mapper 接口的方法的形参,与sql 语句的parameterType 属性指定的类型一致
 
5.2.2. 需求
1.       根据用户Id 查询用户
2.       新增用户
 
5.2.3. 需求实现
5.2.3.1. 准备用户 mapper 接口
public interface UserMapper {
//   1.根据用户Id查询用户
User queryUserById(Integer id);
//   2.新增用户
void insertUser(User user );
 
}
 
5.2.3.2. 准备用户 mapper 映射文件
<? 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" >
<!-- namespace 属性:名称空间,相当于java中的package,用于放置 sql 语句冲突 -->
<!-- mapper 代理开发方法中, namespace 属性值,必须是 mapper 接口的全路径  -->
< mapper namespace = "cn.itheima.mybatis.mapper.UserMapper" >
 
<!-- 根据用户Id查询用户,说明:
 select标签:用于放置查询 sql 语句
 id属性:唯一标识一条 sql 语句
 parameterType属性:输入参数类型
 resultType属性:返回值类型
 #{id}:占位符,相当于 jdbc 中的问号:?-->
< select id = "queryUserById" parameterType = "int" resultType = "cn.itheima.mybatis.po.User" >
     select * from `user` where id=#{id}
</ select >
<!-- 新增用户,说明
insert标签:用于放置新增 sql 语句
#{id}:占位符,当参数传递的是 pojo 的时候,换括号中的内容是 pojo 的属性-->
  < insert id = "insertUser" parameterType = "cn.itheima.mybatis.po.User"
  useGeneratedKeys = "true" keyColumn = "id" keyProperty = "id" >
    insert into `user`( username ,birthday,sex,address)
    values(#{ username },#{birthday},#{sex},#{address})
  </ insert >
 
</ mapper >
 
 
5.2.3.3. sqlMapConfig.xml ,加载 UserMapper.xml 文件
<!-- 加载 mapper 映射文件 -->
< mappers >
     <!--加载User.xml文件,说明:
       resource属性:指定配置文件的位置-->
     < mapper resource = "sqlmap/User.xml" />
     <!-- 加载UserMapper.xml文件 -->
     <mapper resource= "sqlmap/UserMapper.xml" />
</ mappers >
 
 
5.2.3.4. 编写测试代码
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory = null ;
@Before
public void init() throws IOException{
     // 1.加载核心配置文件:sqlMapConfig.xml
     // resource属性:指定核心配置文件位置
     InputStream inputStream = Resources. getResourceAsStream ( "sqlMapConfig.xml" );
    
     // 2.读取配置文件内容
     SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
     // SqlSessionFactory对象: mybatis 框架的核心对象,一个项目中只需要一个(单例设计模式)
     sqlSessionFactory = builder.build(inputStream);
}
// 测试根据用户Id查询用户
@Test
public void queryUserByIdTest(){
    
     // 1.创建sqlSession对象
     SqlSession sqlSession = this . sqlSessionFactory .openSession();
    
     // 2.使用sqlSession对象,获取 mapper 代理对象
     // getMapper方法:获取 mapper 代理对象
     // type参数: mapper 接口的class
     UserMapper mapper = sqlSession.getMapper(UserMapper. class );
    
     // 3.使用 mapper 代理对象,调用方法执行
     User user = mapper.queryUserById(2);
     System. out .println(user);
    
     // 4.释放资源
     sqlSession.close();
}
 
}
 

 
测试新增用户:
// 测试新增用户
@Test
public void insertUserTest (){
     // 1.创建sqlSession对象
     SqlSession sqlSession = this . sqlSessionFactory .openSession( true );
    
     // 2.使用sqlSession对象,获取 mapper 代理对象
     UserMapper mapper = sqlSession.getMapper(UserMapper. class );
    
     // 3.使用 mapper 对象,调用方法执行
     // 创建用户对象
     User user = new User();
     user.setUsername( "天机老人" );
     user.setSex( "1" );
     user.setBirthday( new Date());
     user.setAddress( "来自大明朝" );
    
     mapper.insertUser(user);
    
     // 4.释放资源
     sqlSession.close();
}
 
5.3. 两种开发方法总结
1.       原始的dao 开发方法:需要开发接口和实现类
2.       mapper 代理开发方法:只需要开发接口
3.       企业项目中,推荐使用mapper 代理开发
 
6.    mybatis 核心配置文件
sqlMapConfig.xml :配置运行环境(数据源),mapper 映射文件。
顺序
配置标签名称
说明
1
properties
属性
2
settings
配置全局参数
3
typeAliases
类型别名
4
typeHandlers
类型处理器
5
objectFactory
对象工厂
6
plugins
插件
7
environments
环境集合属性对象
8
databaseIdProvider
多数据库支持
9
mappers
映射器
说明:
1.         红色字体内容要求掌握
2.         sqlMapConfig.xml 必须 是从上往下的配置顺序
 
6.1. properties (属性)
作用:加载属性文件(比如db.properties )和定义属性
 
6.1.1. 准备 db.properties 文件

db.driver= com.mysql.jdbc.Driver
db.url= jdbc:mysql://127.0.0.1:3306/ mybatis
db.username= root
db.password= admin
 
6.1.2. 加载 db.properties 属性文件
<!--加载属性文件,说明:
 1.resource属性:指定本地配置文件的位置
 2. url 属性:指定网络上的配置文件位置-->
< properties resource = "db.properties" >
   </ properties >
 
 
6.1.3. 使用 db.propertis 属性文件中的属性
<!-- 运行环境配置 -->
<!-- default属性:指定使用哪一个运行环境 -->
< environments default = "development" >
     <!-- id属性:唯一标识一个运行环境 -->
     < environment id = "development" >
         <!-- 事务管理器配置,JDBC:mybatis默认使用 jdbc 事务 -->
         < transactionManager type = "JDBC" />
        
         <!-- 数据源配置,POOLED:mybatis提供的连接池 -->
         < dataSource type = "POOLED" >
             <!-- <property name="driver" value="com.mysql.jdbc.Driver" />
             <property name=" url " value="jdbc:mysql://127.0.0.1:3306/ mybatis " />
             <property name=" username " value="root" />
             <property name="password" value=" admin " /> -->
            
             <!-- 使用db.properties属性文件的属性 -->
             <property name= "driver" value= "${db.driver}" />
             <property name= "url" value= "${db.url}" />
             <property name= "username" value= "${db.username}" />
             <property name= "password" value= "${db.password}" />
         </ dataSource >
     </ environment >
   </ environments >
 
6.1.4. 使用内部 property 标签定义属性
<!--加载属性文件,说明:
 1.resource属性:指定本地配置文件的位置
 2. url 属性:指定网络上的配置文件位置
 3.使用内部property标签定义属性
  4.加载顺序:首先加载内部property标签定义的属性,再加载属性文件中的属性,
 如果有相同的属性,属性文件中的属性,覆盖内部property标签的属性 -->
< properties resource = "db.properties" >
     < property name = "db.username" value = "root123" />
     < property name = "db.password" value = "admin" />
   </ properties >
 
6.2. typeAliases (类型别名)
作用:简称。比如中华人民共和国,简称中国。
6.2.1. 内置别名
别名
映射类型
_byte
byte
_long
long
_short
short
_int
int
_integer
int
_double
double
_float
float
_boolean
boolean
string
String
byte
Byte
long
Long
short
Short
int
Integer
integer
Integer
double
Double
float
Float
boolean
Boolean
date
Date
decimal
BigDecimal
bigdecimal
BigDecimal
object
Object
map
Map
hashmap
HashMap
list
List
arraylist
ArrayList
collection
Collection
iterator
Iterator
 
说明:
1.       内置别名可以直接使用
2.       别名不区分大小写
 
6.2.2. 自定义别名
6.2.2.1. 自定义别名方式一
<!-- 自定义别名配置 -->
< typeAliases >
     <!-- 自定义用户别名配置,说明:
     1.type属性:别名的类型
     2.默认使用类名称,作为别名
     3.alias属性:指定别名的名称 -->
     < typeAlias type = "cn.itheima.mybatis.po.User" alias = "user" />
</ typeAliases >
 
6.2.2.2. 自定义别名方式二
<!-- 自定义别名配置 -->
< typeAliases >
     <!-- 自定义用户别名配置,说明:
     1.type属性:别名的类型
     2.默认使用类名称,作为别名
     3.alias属性:指定别名的名称 -->
     <!-- <typeAlias type="cn.itheima.mybatis.po.User" alias="user"/> -->
    
     <!--包扫描方式配置别名,说明:
      1.name属性:指定扫描的包
      2.默认使用类名称,作为别名
      3.如果有多个包,配置多个package
      4.企业项目中,推荐使用包扫描方式 -->
     <package name= "cn.itheima.mybatis.po" />
</ typeAliases >
 
6.3. mappers (映射器)
作用:加载mapper 映射文件。
 
6.3.1. 加载 mapper 映射文件方式一
<!-- 加载 mapper 映射文件 -->
< mappers >
     <!--加载User.xml文件,说明:
       resource属性:指定配置文件的位置-->
     < mapper resource = "sqlmap/User.xml" />
     <!-- 加载UserMapper.xml文件 -->
     < mapper resource = "sqlmap/UserMapper.xml" />
   </ mappers >
 
 
6.3.2. 加载 mapper 映射文件方式二
<!-- 加载 mapper 映射文件 -->
< mappers >
     <!--加载User.xml文件,说明:
       resource属性:指定配置文件的位置-->
     < mapper resource = "sqlmap/User.xml" />
     <!-- 加载UserMapper.xml文件 -->
     <!-- <mapper resource=" sqlmap /UserMapper.xml"/> -->
    
     <!-- 包扫描方式加载 mapper 映射文件,说明:
     1.前提必须是 mapper 代理开发方法
     2.要求 mapper 映射文件,与 mapper 接口在同一个目录
     3.要求 mapper 映射文件的名称,与 mapper 接口的名称一致 -->
     <package name= "cn.itheima.mybatis.mapper" />
   </ mappers >
 
 
7.    mybatis hibernate 比较
7.1. 相同点
都是对jdbc 的封装,都是持久层的框架,都用于dao 层的开发。
 
7.2. 不同点
1.       hibernate 是对sql 语句做了封装,提供HQL 语言操作数据库,数据库无关性支持好,在项目需要支持多种数据库的情况下,代码开发量较少,sql 语句优化困难;mybatis 是直接使用sql 语句操作数据库,不支持数据库无关性,在项目需要支持多种数据库的情况下,代码开发量较多,sql 语句优化容易。
2.       hibernate 是配置java 对象与数据库表的对应关系,多表关联关系配置复杂。mybatis 是配置java 对象,与sql 语句对应关系,多表关联关系配置容易。
3.       hibernate 是重量级的框架,学习使用门槛高,适合于需求相对稳定,中小型的项目,比如:办公自动化系统(OA );mybatis 是轻量级的框架,学习使用门槛低,适合于需求变化频繁,大型的项目,比如:互联网电子商务网站项目。目前在企业项目中,mybatis 框架使用更多一些。
 
8.    扩展
8.1. 注解开发
//   3.根据用户Id查询用户,使用注解开发实现
@Select ( "select * from `user` where id=#{id}" )
User queryUserById_1(Integer id);
 
// 测试根据用户Id查询用户,测试注解开发
@Test
public void queryUserById_1Test(){
    
     // 1.创建sqlSession对象
     SqlSession sqlSession = this . sqlSessionFactory .openSession();
    
     // 2.使用sqlSession对象,获取 mapper 代理对象
     // getMapper方法:获取 mapper 代理对象
     // type参数: mapper 接口的class
     UserMapper mapper = sqlSession.getMapper(UserMapper. class );
    
     // 3.使用 mapper 代理对象,调用方法执行
     User user = mapper.queryUserById_1(2);
     System. out .println(user);
    
     // 4.释放资源
     sqlSession.close();
   }
 
说明:注解开发,只做了解,企业项目中不推荐使用。
 
8.2. 缓存
8.2.1. 一级缓存( sqlSession 级别)
// 测试根据用户Id查询用户,测试一级缓存
@Test
public void oneCacheTest (){
    
     // 1.创建sqlSession对象
     SqlSession sqlSession = this . sqlSessionFactory .openSession();
    
     // 2.使用sqlSession对象,获取 mapper 代理对象
     // getMapper方法:获取 mapper 代理对象
     // type参数: mapper 接口的class
     UserMapper mapper = sqlSession.getMapper(UserMapper. class );
    
     // 3.使用 mapper 代理对象,调用方法执行
     User user = mapper.queryUserById(2);
     System. out .println(user);
    
     System. out .println( "-------------------------------------" );
    
     User user1 = mapper.queryUserById(2);
     System. out .println(user1);
    
    
     // 4.释放资源
     sqlSession.close();
   }
 

 
说明:一级缓存 mybatis 框架就已经默认使用,不需要关心。
 
8.2.2. 二级缓存( mapper 级别缓存,在多个 SqlSession 之间共享)
8.2.2.1. sqlMapConfig.xml 中,配置开启二级缓存
<!-- 全局参数配置 -->
< settings >
     <!-- 配置开启二级缓存 -->
     < setting name = "cacheEnabled" value = "true" />
</ settings >
 
 
8.2.2.2. 修改用户 pojo ,实现序列化接口
public class User implements java.io.Serializable {
  private Integer id ; // int (11) NOT NULL AUTO_INCREMENT,
  private String username ; // varchar (32) NOT NULL COMMENT '用户名称',
  private Date birthday ; // date DEFAULT NULL COMMENT '生日',
  private String sex ; // char(1) DEFAULT NULL COMMENT '性别',
  private String address ; // varchar (256) DEFAULT NULL COMMENT '地址',
 
8.2.2.3. UserMapper.xml 中,开启使用二级缓存

 
8.2.2.4. 测试二级缓存
// 测试根据用户Id查询用户,测试二级缓存
@Test
public void twoCacheTest(){
    
     // 1.创建sqlSession对象
     SqlSession sqlSession = this . sqlSessionFactory .openSession();
    
     // 2.使用sqlSession对象,获取 mapper 代理对象
     // getMapper方法:获取 mapper 代理对象
     // type参数: mapper 接口的class
     UserMapper mapper = sqlSession.getMapper(UserMapper. class );
    
     // 3.使用 mapper 代理对象,调用方法执行
     User user = mapper.queryUserById(2);
     System. out .println(user);
 
     // 4.释放资源
     sqlSession.close();
    
     System. out .println( "-----------------------------------------" );
    
     //  5.创建sqlSession对象
     SqlSession sqlSession1 = this . sqlSessionFactory .openSession();
    
     // 6.使用sqlSession对象,获取 mapper 代理对象
     // getMapper方法:获取 mapper 代理对象
     // type参数: mapper 接口的class
     UserMapper mapper1 = sqlSession1.getMapper(UserMapper. class );
    
     // 7.使用 mapper 代理对象,调用方法执行
     User user1 = mapper1.queryUserById(2);
     System. out .println(user1);
 
     // 8.释放资源
     sqlSession1.close();
}

说明: mybatis 框架的二级缓存,只做了解,企业项目中不推荐使用。原因是 mybatis 框架的二级缓存不能实现 细粒度 的控制。
 
 







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值