MyBatis-入门

MyBatis是支持定制化SQL、存储过程以及高级映射的优秀持久层框架。MyBatis避免了几乎所有JDBC代码的手动设置参数已经获取结果集。MyBatis可以对配置和原生Map使用简单的XML或注解,将接口和Java的POJOs(普通的Java对象)映射成数据库中的记录。

MyBatis的引入和配置

在maven的pom.xml中引入:


        
            junit
            junit
            4.12
            test
        

        
            org.mybatis
            mybatis
            3.5.1
        

        
            mysql
            mysql-connector-java
            8.0.15
        
 

然后在resource中新建dbconfig.properties和mybatis-config.xml文件:

dbconfig.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/Dane?characterEncoding=utf-8
username=root
password=root

mybatis-config.xml文件:





    
    
        
            
            
                
                
                
                
            
        
    
    
        
    

这样就引入了MyBatis,其中mappers是与我们开发的userMapper.xml是与我们开发的bean对应,下面会举例。

MyBatis的增删改查

引入和配置了MyBatis后,先简单的封装下MyBatis,把通用操作简单封装:

这里有几个注意的点,如果你的mybatis-config.xml文件不是放在resource下,那就必须给它全路径,获取SqlSession时,mybatis默认执行SQL后是不自动提交的,需要自动提交需要sqlSessionFactory.openSession(true):

public class MyBatisUtil {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }

    public static SqlSession getSqlSession(boolean autoCommit){
        return sqlSessionFactory.openSession(autoCommit);
    }

    public static void close(SqlSession sqlSession){
        if(sqlSession != null){
            sqlSession.close();
        }
    }
}

然后写个User对象:

public class User {

    private String id;
    private String name;
    private String password;
    private String account;
    
    ...
}

接着在resource中新建mapper文件夹,并在里面创建UserMapper.xml:

parameterType为传入参数类型,resultType为返回类型





    

    

    

    

然后在mybatis-config.xml配置下:

 
        
    

接下来可以进行增删改查了:

sqlSession进行增删改查时,参数一对应的是UserMapper.xml中的命名空间和id,如查dane.selectUser

新建IUserDao以及实现类UserDaoImpl:

public interface IUserDao {

    public List selectUsers();

    public void insertUsers(User user);

    public void updateUsers(User user);

    public void  deleteUsers(int id);
}
public class UserDaoImpl implements IUserDao {


    public List selectUsers() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        List users = sqlSession.selectList("dane.selectUser");

        sqlSession.commit();;
        MyBatisUtil.close(sqlSession);
        return users;
    }

    public void insertUsers(User user) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        sqlSession.insert("dane.insertUser",user);
        sqlSession.commit();;
        MyBatisUtil.close(sqlSession);
    }

    public void updateUsers(User user) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        sqlSession.update("dane.updateUser",user);
        sqlSession.commit();
        MyBatisUtil.close(sqlSession);

    }

    public void deleteUsers(int id) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        sqlSession.delete("dane.deleteUser",id);
        sqlSession.commit();
        MyBatisUtil.close(sqlSession);
    }

然后进行增删改查测试

public class MyBatisTest {


    @Test
    public void selectUser(){

        IUserDao userDao = new UserDaoImpl();
        List users = userDao.selectUsers();
        for (User user : users) {
            System.out.println(user.getId());
            System.out.println(user.getName());
            System.out.println(user.getAccount());
            System.out.println(user.getPassword());

        }

    }

    @Test
    public void insertUser(){

        IUserDao userDao = new UserDaoImpl();
        User user = new User();
        user.setAccount("Dane小号");
        user.setPassword("123456");
        user.setName("Dane小号");
        userDao.insertUsers(user);

    }

    @Test
    public void updateUser(){

        IUserDao userDao = new UserDaoImpl();
        User user=new User();
        user.setId(2);
        user.setName("dane6666");
        userDao.updateUsers(user);

    }

    @Test
    public void deleteUser(){

        IUserDao userDao = new UserDaoImpl();
        userDao.deleteUsers(2);

    }
}

Mybatis Mapper代理

在上面的例子中,我们需要自己实现IUserDao,使用Mapper代理,可以无需自己实现。

首先,看修改后的UserMapper.xml,命名空间必须是IUserDao的引用路径,每个select的id必须是IUserDao的方法,包括参数要一一对应。





    

    

    

    

然后看下使用,查询为例:

   SqlSession sqlSession = MyBatisUtil.getSqlSession(true);
   IUserDao userDao = sqlSession.getMapper(IUserDao.class);
   List users = userDao.selectUsers();
   for (User user : users) {
       System.out.println(user.getId());
       System.out.println(user.getName());
       System.out.println(user.getAccount());
       System.out.println(user.getPassword());

   }
   MyBatisUtil.close(sqlSession);

Mybatis配置Log框架

首先要了解下slf4j日志框架并没真正的实现日志记录,而是一个日志标准或者说是抽象,它提供日志接口和提供获取具体日志对象的方法,所以真正实现日志的还要靠log4j等。

在Mybatis中只需要想pom.xml引入并在resource配置log4j.properties即可:


        
            org.slf4j
            slf4j-api
            1.7.25
        
        
        
            log4j
            log4j
            1.2.17
        
        
        
            org.slf4j
            slf4j-log4j12
            1.7.25
        

log4j.properties

log4j.rootLogger=debug, stdout, R

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

log4j.appender.stdout.layout.ConversionPattern=%5p - %m%n

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=hx.log

log4j.appender.R.MaxFileSize=100KB
log4j.appender.R.MaxBackupIndex=1

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

log4j.logger.com.codefutures=DEBUG

然后运行代码,会有如下图:
MyBatis-入门_第1张图片
image.png

使用MyBatis注解的方式

上面的SQL语句是放在UserMapper.xml文件中,MyBatis也可以使用注解的方式:

public interface IUserDao2 {

    @Select(" select * from User")
    public List selectUsers();

    @Insert("insert into user(account,password,name) values (#{account},#{password},#{name})")
    public void insertUsers(User user);

    @Update("update user set name = #{name} where id = #{id}")
    public void updateUsers(User user);

    @Delete("delete from User where id = #{id}")
    public void  deleteUsers(int id);
}

然后在mybatis-config.xml中配置,注意是class

 
        
    

然后就可以测试啦,查询为例:

  SqlSession sqlSession = MyBatisUtil.getSqlSession(true);
  IUserDao2 userDao = sqlSession.getMapper(IUserDao2.class);
  List users = userDao.selectUsers();
  for (User user : users) {
      System.out.println(user.getId());
      System.out.println(user.getName());
      System.out.println(user.getAccount());
      System.out.println(user.getPassword());
  }
   MyBatisUtil.close(sqlSession);

MyBatis输入输出参数进一步了解

假设客户端上来的数据封装成UserQueryVo,除了有User信息外,还有其他信息:

public class UserVo {

   private UserPo user;

   private List orderIds;

   ....
}

然后之前的User对象,改名成UserPo,PO表示持久对象,VO表示值对象:

package com.dane.mybatis.bean;

public class UserPo {

    private int id;
    private String name;
    private String password;
    private String account;

    ....
}

然后看下MyBatis这种情况参数怎么处理,这里我使用注解的方式:


public interface IUserDao3 {

    @Select("select account from User where name=#{user.name}")
    public List selectUsers(UserVo userVo);

}

别忘了配置Mapper:

 
        
 

然后测试下:

 SqlSession sqlSession = MyBatisUtil.getSqlSession(true);
 IUserDao3 userDao = sqlSession.getMapper(IUserDao3.class);
 UserVo userVo = new UserVo();
 UserPo user1 = new UserPo();
 user1.setName("dane");
 userVo.setUser(user1);
 List users = userDao.selectUsers(userVo);
 for (User user : users) {
     System.out.println(user.getAccount());
 }
 MyBatisUtil.close(sqlSession);

接下来是Map的方式,通过HashMap封装请求信息

@Select("select id,account from User where name=#{name} 
              and password=#{password}")    
public List selectUsersByHashMap(HashMap hashMap);

测试下:

 SqlSession sqlSession = MyBatisUtil.getSqlSession(true);
 IUserDao3 userDao = sqlSession.getMapper(IUserDao3.class);
 HashMap map = new HashMap();
 map.put("name","dane");
 map.put("password","123456");
 List users = userDao.selectUsersByHashMap(map);
 for (User user : users) {
     System.out.println(user.getAccount());
 }
 MyBatisUtil.close(sqlSession);

MyBatis表名与实体属性不一样的映射方法

假设数据库表Message字段为_id、_content,我们的实体类属性为id、content

SQL语句解决

@Select("SELECT _id id,_content content from Message where _id=#{id}")
public Message findMessageById(int id);
SqlSession sqlSession = MyBatisUtil.getSqlSession(true);
IUserDao3 userDao = sqlSession.getMapper(IUserDao3.class);
Message message  = userDao.findMessageById(1);
System.out.println(message.getContent());
MyBatisUtil.close(sqlSession);

配置映射解决

 @Select("SELECT _id ,_username,_psw,_sex FROM muser WHERE _id=#{id}")
 @Results({
        @Result(column="_id", property="id", id=true),
        @Result(column="_username", property="username"),
        @Result(column="_psw", property="psw"),
        @Result(column="_sex", property="sex")})
 public UserPo findUserById(int id);

非注解的方式:





    
        
        
    
    

MyBatis一对一表查询

根据User的name,找出User和对应的Home

public class User {

    private int id;
    private String name;
    private String password;
    private String mobile;
    private int home_id;
    private  Home home;

    .....
}

方法一:分开查询

@Select("select * from User where name = #{name}")
@Results(@Result(property = "home",column = "home_id",
        one = @One(select = "com.dane.mybatis.dao.IUserDao4.getHome"
)))
User getUser(String name);

@Select("select * from Home where id = #{id}")
Home getHome(int id);
SqlSession sqlSession = MyBatisUtil.getSqlSession(true);
IUserDao4 userDao = sqlSession.getMapper(IUserDao4.class);
User user = userDao.getUser("Dane");
System.out.println(user);
MyBatisUtil.close(sqlSession);

非注解方式:





    

    
        
        
        
        
        
        
    

    

方法二:联合查询
首先写好resultMap,并在mybatis-config中配置:





  
        
    

  
    
    
    
    

    
      
      
    
  


 @Select("select u.*, h.* from User u,Home h where u.name = #{name} and h.hid = u.home_id")
 @ResultMap("rst1")
 User getUser(String name);

MyBatis一对多表查询

根据hid查询出Home以及Home下所有User

分开查询

@Select("select * from Home where hid = #{id}")
@Results({
        @Result(property = "id",column = "hid",id = true),
        @Result(property = "name",column = "hname"),
        @Result(
        property = "users",column = "hid",
        many = @Many(select = "com.dane.mybatis.dao.IUserDao4.getUsers"
))})
Home getHome(int id);

@Select("select * from user where home_id = #{home_id}")
List getUsers(int home_id);

非注解方式只需要把association换成collection





    

    
        
        
        
    

    

联合查询

注意除了association换成collection,javaType换成ofType


  
        
    

  
    
    
    
    
      
      
      
      
      
    
  


 @Select("select h.*,u.* from Home h ,User u where hid = #{id} and h.hid = u.home_id")
 @ResultMap("rst1")
 Home getHome(int id);

MyBatis延迟加载

所谓的延迟加载,就是用到才去查询,比如:一对多查询,先查出了Home,home里面的users还没用到,MyBatis不会先去查询,等到我们用到getUsers时,MyBatis才去查询。




    
    
        
        
        
        
    
    ......

MyBatis配置参数路径或别名

 
        
 

MyBatis动态Sql

where





  

注解方式

 @Select("")
 User getUser(User user);

set


        UPDATE User
        
            
                name=#{name},
            
            
                password=#{password},
            
        
        
            
                id=#{id}
            
        
 

注解方式

@Select("")
User updateUser(User user);

foreach




MyBatis调用存储过程

DELIMITER $
CREATE PROCEDURE dane.student_count(IN sex INT, OUT count INT)
BEGIN
IF sex=0 THEN
SELECT COUNT(*) FROM dane.User WHERE User.sex='女' INTO count; ELSE
SELECT COUNT(*) FROM dane.student WHERE User.ssex='男' INTO count; END IF;
END
$


      
      
      
      

MyBatis缓存

MyBatis提供了一级和二级两种缓存,当进行增删改时,一级二级缓存都会被清空。

一级缓存基于PerpetualCache的HashMap本地缓存,其存储作用域为Session,当Session flush或close之后,该session中所有cache就将清空,一级缓存默认开启

二级缓存也是基于PerpetualCache的HashMap本地缓存,不过其存储作用域是Mapper,二级缓存默认不开启。要开启二级缓存,只需要在Mapper.xml中配置cache:






  
  

  
  

  
  


自定义缓存
实现MyBatis的Cache接口(具体自己实现),然后配置即可:

 

MyBaits配置package

之前我们每写一个Mapper,都需要在MyBatis-config中去配置,可以采用package进行全局配置:


    

如果报找不到mapper,在pom.xml下配置:


    
        
            src/main/java
            
                **/*.xml
            
        
    

MyBatis自动生成插件

MyBatis的org.mybatis.generator插件可以自动生成Mapper和Model代码:

添加依赖被配置resource:


    
            
                
                    org.mybatis.generator
                    mybatis‐generator‐maven‐plugin
                    1.3.2
                    
                        true
                        true
                    
                
            
    

    
        
            src/main/resources
            
                **/*.properties
            
        
    

在resource下新建generatorConfig.xml:





    
    

    
    

    

        
        
            
            
        


        
        
        


        
        
            
        


        
        

            
            
            
            
            
            
            
            
        

        
        
            
        

        
        
            
        


        

然后添加Configuration,commod line 为mybatis‐generator:generate ‐e


MyBatis-入门_第2张图片
image.png

然后跑一下,就自动生成代码了:


MyBatis-入门_第3张图片
image.png

你可能感兴趣的:(MyBatis-入门)