mybatis 学习笔记(总)2018-12-02

MyBatis

  • mybatis-3.4.6
  • jdk1.8+

一、mybatis入门

1.依赖jar包

mybatis 学习笔记(总)2018-12-02_第1张图片
mybatis基础包
  • pom.xml引入依赖
    
        
        
            org.mybatis
            mybatis
            3.4.6
        
        
            cglib
            cglib
            3.2.9
        
        
            commons-logging
            commons-logging
            1.2
        
        
            ognl
            ognl
            3.2.8
        
        
            org.slf4j
            slf4j-log4j12
            1.7.25
        
        
        
            org.mybatis.generator
            mybatis-generator-core
            1.3.7
        
        
            junit
            junit
            4.12
        
        
            com.oracle
            ojdbc6
            11.2.0
        
        
            org.apache.logging.log4j
            log4j-core
            2.9.1
            
        
    

2. MyBatis 配置文件

  • mybatis-config.xml




    
    
    
    
        
        
        
        
    
    
    
        
    
    
    
        
        
            
            
            
                
                
                
                
                
            
        
    
    
    
        
    

3. Mapper映射文件

  • PhoneUserMapper.xml




  
    
    
    
    
    
    
    
    
  
  
      
        select SQ_PHONE_USER_ID.nextval as id from dual
      
    insert into PHONE_USER (ID, NAME, BIRTH_DAY, 
      ID_NO, MOBILE_TEL, E_MAIL, 
      PASSWD, CREATE_DATE)
    values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{birthDay,jdbcType=TIMESTAMP}, 
      #{idNo,jdbcType=VARCHAR}, #{mobileTel,jdbcType=VARCHAR}, #{eMail,jdbcType=VARCHAR}, 
      #{passwd,jdbcType=VARCHAR}, #{createDate,jdbcType=TIMESTAMP})
  
  

4.MyBatis完成数据操作代码

public class BasicMyBaitisTest {
    public static void main(String[] args) throws IOException {
        //读取mybatis-config.xml配置文件
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        //初始化mybatis.创建SQLSessionFactory实例
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        //创建session实例
        SqlSession session = sqlSessionFactory.openSession();
        //创建phoneUser 对象
        PhoneUser user = new PhoneUser("test", "吴总", new Date(1992, 9, 26), "54232819800130824X", "15555555858", "[email protected]", "123456", new Date());
        //插入数据 
        //session.insert("com.zhougl.web.dao.mapper.PhoneUserMapper.insertPhoneUser", user);
        PhoneUser userOne = session.selectOne("com.zhougl.web.dao.mapper.PhoneUserMapper.selectPhoneUserById", "1");
        System.out.println(userOne.toString());
        //提交事务
        session.commit();
        //关闭session
        session.close();
    }
}
//打印结果
PhoneUser [id=1, name=测试, birthDay=Tue Oct 23 00:00:00 CST 1984, idNo=220724198410236590, mobileTel=199123425678, [email protected], passwd=1, createDate=Thu Nov 22 00:00:00 CST 2018]

5. log4j日志文件配置

#全局日志配置
#log4j.rootLogger=ERROR,stdout
log4j.rootLogger=DEBUG,Console
#MyBatis日志配置
#log4j.logger.com.zhougl.mapper.UserMapper=DEBUG
#控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

6.mybatis-generator插件使用(快速生成代码)

  • generatorConfig.xml




    
    
    
    

    
        
        
        
        
        
        
        
        
            
        
        
        
                        
        
        
            
            
                               

        
        
            
            
            
            
        

        
        
            
            
        
        
        
            
        

        
        
        

二、mybatis基础

1. typeAliases类型设置别名

mybatis-config.xml文件中设置:



    



    

@Alias("User")
public class PhoneUser {
}

2.mapper映射器


    
    
        
    
    
    
        
    
    
    
        
    
  • 使用接口类

    • mybatis-config.xml

      
      
          
      
      
    • 接口与映射文件位置

      接口与映射文件

    • 映射文件命名空间namespace="com.zhougl.web.dao.PhoneDepartmentMapper"必须与接口类全限定名一直

    • 测试代码

    PhoneDepartment phoneDepartment = session.selectOne("com.zhougl.web.dao.PhoneDepartmentMapper.selectByPrimaryKey", "1");
    //结果  PhoneDepartment [id=1, departmentName=企划部, departmentCode=D01]
    

3.生成主键

 
    
        select SQ_PHONE_DEPARTMENT_ID.nextval as id from dual
    
    insert into PHONE_DEPARTMENT (ID, DEPARTMENT_NAME, DEPARTMENT_CODE
      )
    values (#{id,jdbcType=VARCHAR}, #{departmentName,jdbcType=VARCHAR}, #{departmentCode,jdbcType=VARCHAR}
      )
  

4. sql代码段



${prefix}Table
from 


5.SqlSessionFactoryUtil工厂类封装方法

public class SqlSessionFactoryUtil {
    
    private static SqlSessionFactory sqlSessionFactory = null;
    //创建初始化SqlSessionFactory对象
    static {
        try {
            //读取mybatis-config.xml配置文件
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            
            e.printStackTrace();
        }
    }
    //获取SqlSession对象的静态方法
    public static  SqlSession getSession() {
        return sqlSessionFactory.openSession();
    }
    //获取SqlSessionFactory的静态方法
    public static SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }
}

6. 一对一查询

元素的解释:

  • column 表示当前查询数据库表的列名DEPARTMENT_ID
  • property 表示返回类型PhoneUserIdAndDepartment属性名department
  • javaType 表示该属性对于的类型名称
  • select 表示执行的查询语句,将查询到的数据封装到property所代表的类型对象当中

6.1 基本应用

6.1.1 java bean
  • WebClass.java
public class WebClass {
    private BigDecimal id;
    private String code;
    private String name;
    //班级与学生是一对多的关系
    private List students;
    
}
  • Student.java
public class Student {
    private BigDecimal id;

    private String name;

    private String sex;

    private Short age;
    //学生与班级是多对一的关系
    private WebClass webClass;
} 
6.1.1 映射文件

  
    
    
    
    
    
    
  
 
  
  
 

6.1.2 测试代码
public static void main(String[] args) {
        SqlSession session = SqlSessionFactoryUtil.getSession();
        List students = session.selectList("com.zhougl.web.dao.StudentDao.selectStudent");
        students.forEach(student -> System.out.println(student));
        session.commit();
        session.close();
    }
  • 结果
==>  Preparing: select * from STUDENT 
==> Parameters: 
====>  Preparing: select * from WEB_CLASS where ID = ? 
====> Parameters: 1(Integer)
<====      Total: 1
====>  Preparing: select * from WEB_CLASS where ID = ? 
====> Parameters: 2(Integer)
<====      Total: 1
<==      Total: 4
Student [id=1, name=null, sex=女, age=22, webClass=WebClass [id=1, code=C001, name=大乱斗指导班]]
Student [id=2, name=null, sex=女, age=24, webClass=WebClass [id=2, code=C002, name=无限流战斗班]]
Student [id=3, name=null, sex=男, age=28, webClass=WebClass [id=1, code=C001, name=大乱斗指导班]]
Student [id=4, name=null, sex=女, age=26, webClass=WebClass [id=2, code=C002, name=无限流战斗班]]

6.2 一对一映射(接口)

6.2.1 java bean
  • card.java
public class Card {
    private Integer id;
    private String code;
    //省略构造器和set/get方法
}
  • Person.java
public class Person {
    private Integer id;
    private String name;
    private String sex;
    private Short age;
    private Card card;
    //省略构造器和set/get方法
}
6.2.2 映射文件
  • CardMapper.xml

  
    ID, CODE
  
 
  
 

  • PersonMapper.xml

    
        
        
        
        
        
        
    

    
        ID, NAME, SEX, AGE, CARD_ID
    

    

6.2.3 接口
  • PersonMapper.java,与PersonMapper.xml在同一个文件夹,接口的类名必须与映射文件namespace一致
public interface PersonMapper {
    /**
     * 方法名与参数必须和xml文件中的id属性和parameterType属性一致
     * @param id
     * @return Person
     */
    Person selectPersonById(Integer id);  
}
6.2.4 测试类
public class OneToOneTest {
    public static void main(String[] args) {
        SqlSession session = SqlSessionFactoryUtil.getSession();
        //获得mapper接口代理对象
        PersonMapper mapper = session.getMapper(PersonMapper.class);
        //直接调用接口方法,查询数据
        Person person = mapper.selectPersonById(1);
        System.out.println(person);
        System.out.println(person.getCard());
        session.commit();
        session.close();
    }
}

7 一对多查询

元素的解释:

  • column 表示当前查询数据库表的列名DEPARTMENT_ID
  • property 表示返回类型PhoneUserIdAndDepartment属性名department
  • javaType 表示该属性对于的类型名称,本例是一个ArrayList集合
  • select 表示执行的查询语句,将查询到的数据封装到property所代表的类型对象当中
  • ofType 表示集合当中的类型

7.1 基本应用

7.1.1 java bean
  • 同 6.1.1
7.1.2 映射文件

    
        
        
        
        
        
    
    
    
  


7.1.3 测试代码
SqlSession session = SqlSessionFactoryUtil.getSession();
        List classes = session.selectList("com.zhougl.web.dao.WebClassDao.selectClass");
        classes.forEach(classe ->{
            System.out.println(classe);
            List students = classe.getStudents();
            students.forEach(student -> System.out.println(student));
        });
        session.commit();
        session.close();
  • 结果
==>  Preparing: select * from WEB_CLASS 
==> Parameters: 
<==      Total: 2
==>  Preparing: select * from STUDENT where class_id = ? 
==> Parameters: 2(Integer)
<==      Total: 2
WebClass [id=2, code=C002, name=无限流战斗班]
Student [id=2, name=王怡, sex=女, age=24]
Student [id=4, name=王多燕, sex=女, age=26]
==>  Preparing: select * from STUDENT where class_id = ? 
==> Parameters: 1(Integer)
<==      Total: 2
WebClass [id=1, code=C001, name=大乱斗指导班]
Student [id=1, name=王一倩, sex=女, age=22]
Student [id=3, name=王二赞, sex=男, age=28]

7.2 一对多映射

7.2.1 mybatis配置
  • mybatis-config.xml添加如下配置

    
    
    
    

7.2.2 java bean
  • 同 6.1.1
7.2.3 mapper映射文件
  • WebClassMapper.xml

    
        
        
        
        
        
            
            
            
            
        
    

    
        ID, CODE, NAME
    
    


7.2.4 mapper接口
  • WebClassMapper.xml
public interface WebClassMapper {
  
    WebClass selectWebClassById(int i);
}
7.2.5 测试类
public class OneToManyTest {

    public static void main(String[] args) {
        SqlSession session = SqlSessionFactoryUtil.getSession();
        OneToManyTest test = new OneToManyTest();
        //测试一对多
        test.testOneToMany(session);
        
        //测试多对一
        //test.testManyToOne(session);
        session.commit();
        session.close();

    }
    //测试一对多,查询班级(一)级联查询学生(多)
    public void testOneToMany(SqlSession session) {
        WebClassMapper mapper = session.getMapper(WebClassMapper.class);
        WebClass webClass = mapper.selectWebClassById(1);
        System.out.println(webClass.getId()+" "+webClass.getCode()+" "+webClass.getName());
        System.out.println(webClass.toString());
        List students = webClass.getStudents();
        for (Student student : students) {
            System.out.println(student.toString());
        }
    }

}
==>  Preparing: select ID, CODE, NAME from WEB_CLASS where ID = ? 
==> Parameters: 1(Integer)
<==      Total: 1
1 C001 大乱斗指导班
==>  Preparing: select ID as studentId, NAME as studentName, SEX, AGE, CLASS_ID from STUDENT where CLASS_ID = ? 
==> Parameters: 1(Integer)
<==      Total: 4
WebClass [id=1, code=C001, name=大乱斗指导班]
Student [id=1, name=王一倩, sex=女, age=22]
Student [id=2, name=王怡, sex=女, age=24]
Student [id=3, name=王二赞, sex=男, age=28]
Student [id=4, name=王多燕, sex=女, age=26]

7.3 多对一映射

7.3.1 java bean
  • 同 6.1.1

7.3.2 mapper配置

  • StudentMapper.xml

  
    
    
    
    
    
    
        
        
        
    
  
 
  
    ID as studentId, NAME as studentName, SEX, AGE, CLASS_ID
  
  
    ${student}.ID as studentId, ${student}.NAME as studentName, ${student}.SEX, ${student}.AGE, ${student}.CLASS_ID
  
  
        ${webClass}.ID , ${webClass}.CODE, ${webClass}.NAME 
  
 
 
  
  
 

7.3.3 mapper接口
  • StudentMapper.java
public interface StudentMapper {
   
    Student selectStudentById(int id);
    List selectStudentByClassId(int classId);

}
7.3.4 测试类
public class OneToManyTest {
    //测试多对一,查询学生(多)级联查询班级(一)
    public void testManyToOne(SqlSession session) {
        StudentMapper studentMapper = session.getMapper(StudentMapper.class);
        Student student = studentMapper.selectStudentById(1);
        System.out.println(student);
        System.out.println(student.getWebClass().toString());
    }

  • 结果
==>  Preparing: select s.ID as studentId, s.NAME as studentName, s.SEX, s.AGE, s.CLASS_ID , c.ID , c.CODE, c.NAME from STUDENT s,WEB_CLASS c where s.class_id=c.id and s.ID = ? 
==> Parameters: 1(Integer)
<==      Total: 1
Student [id=1, name=王一倩, sex=女, age=22]
WebClass [id=1, code=C001, name=大乱斗指导班]

7.4 多对多映射

7.4.1 java bean
public class WebOrder {
    private BigDecimal id;
    private String code;
    private BigDecimal total;
    private BigDecimal userId;
    //订单和用户是多对一关系
    private WebUser user;
    //订单和商品是多对多关系
    private List articles;
}
public class WebUser {
    private BigDecimal id;
    private String username;
    private String loginname;
    private String password;
    private String phone;
    private String address;
    
    //用户和订单是一对多关系
    private List orders;
}
public class WebArticle {
    private BigDecimal id;
    private String name;
    private BigDecimal price;
    private String remark;
}
7.4.2 mapper配置
  • WebOrderMapper.xml

  
    
    
    
    
    
         
        
        
        
        
        
    
    
    
        
        
        
        
    
  
    
  
  


  
    
    
    
    
    
    
    
    
        
        
        
    
  
 
  
    ID, USERNAME, LOGINNAME, PASSWORD, PHONE, ADDRESS
  
 
  
  


  
    
    
    
    
  
  
  
    ID, NAME, PRICE, REMARK
  
  
  
  

7.4.3 mapper接口
public interface WebOrderMapper {
    List selectOrderByUserId(int userId);
    WebOrder selectOrderById(int id); 
}
public interface WebUserMapper {
    WebUser selectUserById(int id);
}
7.4.4 测试类

public class ManyToManyTest {

    public static void main(String[] args) {
        SqlSession session = SqlSessionFactoryUtil.getSession();
        ManyToManyTest test = new ManyToManyTest();
        //test.testOneToMany(session);
        test.testManyToMany(session);
        session.commit();
        session.close();
    }
    public void testOneToMany(SqlSession session) {
        WebUserMapper userMapper = session.getMapper(WebUserMapper.class);
        WebUser user = userMapper.selectUserById(1);
        System.out.println(user.getUsername()+" "+user.getLoginname()+" "+user.getPhone()+" "+user.getAddress());
        List orders = user.getOrders();
        for (WebOrder webOrder : orders) {
            System.out.println(webOrder.toString());
        }
    }
    public void testManyToMany(SqlSession session) {
        WebOrderMapper orderMapper = session.getMapper(WebOrderMapper.class);
        WebOrder order = orderMapper.selectOrderById(1);
        System.out.println(order.getCode()+" "+order.getTotal());
        WebUser user = order.getUser();
        System.out.println(user.toString());
        List articles = order.getArticles();
        for (WebArticle webArticle : articles) {
            System.out.println(webArticle.toString());
        }
    }
}

8.动态SQL

mybatis才有ognl表达式来完成动态SQL。

常用元素;

  • if
  • choose
    • when
    • otherwise
  • where
  • set
  • foreach
  • bind

8.1 if

  • 可选条件 如果不为空则加入限制条件
  

8.2 choose

  • 选择其中的一项

8.3 where

  • where元素之一在一个以上的if条件有至的情况下才会去插入where子句,若最后内容是 and 或 or 开头,where元素会将他们去除

  

8.5 foreach

  • 元素用来遍历集合
  • collection:指定输入对象中的集合属性
  • item:每次遍历生成的对象
  • open:开始遍历时的拼接字符串
  • close:结束时拼接的字符串
  • separator:遍历对象之间需要拼接的字符串

8.6 bind

  • 预定义变量


8.7 trim

  • 替换和添加

  • prefix:前缀

  • prefixoverride:去掉第一个and或者是or

  • suffix:后缀

  • suffixoverride:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样)


8.8 set

  • set 元素会动态前置set关键字,同时会消除无关的逗号

    update WEB_EMPLOYEE
    
    
      LOGINNAME = #{loginname,jdbcType=VARCHAR},
      PASSWORD = #{password,jdbcType=VARCHAR},
      NAME = #{name,jdbcType=VARCHAR},
      SEX = #{sex,jdbcType=VARCHAR},
      AGE = #{age,jdbcType=DECIMAL},
      PHONE = #{phone,jdbcType=VARCHAR},
      SAL = #{sal,jdbcType=DECIMAL},
      STATE = #{state,jdbcType=VARCHAR}
    
    
    where id=#{id,jdbcType=DECIMAL}
  

9.事务管理及缓存机制

9.1 事务管理

9.1.1 事务特性
  • 原子性。事务是应用中最小执行单位。
  • 一致性。事务执行的结果,必须使数据库从一种一致状态,变到另一种一致性状态。
  • 隔离性。事务执行互不干扰,不能互相影响。
  • 持续性。事务一提交,对数据所做的任何改变都要保存到物理数据库中。
9.1.2 Transaction接口
  • Transaction接口

    • JdbcTransaction实现类
    • ManagedTransaction实现类
  • TransactionFactory接口

    • JdbcTransactionFactory实现类
    • ManagedTransactionFactory实现类
  • 使用JDBC事务管理机制。利用java.sql.Connection完成对事务的提交(commit())、回滚(rollback())、和关闭(close())等。

  • 使用MANAGED事务管理机制。mybatis自身不会去实现事务管理,让容器如weblogic、JBoss等来实现对事务的管理。

9.1.3 事务的配置创建
  • mybatis-config.xml

        
            
          

9.2 缓存机制

9.2.1 一级缓存(SqlSession级别)

一级缓存的作用域是SqlSession范围的。同一个SqlSession中执行两次相同的SQL语句,第一次执行会将查询的数据写到缓存(内存),第二次查询时会从缓存中获取数据。如果SqlSession执行DML操作(insert、update、delete),并提交到数据库,mybatis会清空SqlSession中的一级缓存,保证缓存中是最新信息,避免出现脏读现象。

mybatis默认开启一级缓存。

9.2.2 二级缓存(Mapper级别)

二级缓存是mapper级别的,多个SqlSession可以使用同一个mapper的SQL语句去操作数据库,得到的数据会存在二级缓存。

9.2.2.1 开启二级缓存配置
  • mybatis-config.xml


9.2.2.2 mapper中开启二级缓存
  • mapper.xml


  • cashe元素用来开启当前mapper的namespace下的二级缓存,属性设置:
    • flushInterval。刷新间隔。默认不设置,缓存仅仅调用语句时刷新。
    • size。缓存数目。默认值1024。
    • readOnly。只读。默认为false。只读的缓存会给所有调用者返回缓存对象的相同实例,这些对象不能被修改。
    • eviction。收回策略。默认为LRU。
      • LRU。最近最少使用的策略。移出最长时间不被使用的对象。
      • FIFO。先进先出策略。按对象进入缓存的顺序来移除。
      • SOFT。软引用策略。移除基于垃圾回收器状态和软引用规则的对象。
      • WEAK。弱引用策略。更积极地移除基于垃圾收集器和弱引用规则的对象。
  • 使用二级缓存时,查询结果映射的Java对象必须实现java.io.Serializable接口。

三、注解配置

  • select。映射查询SQL语句
  • selectProvider。select语句的动态SQL映射。
  • insert。映射插入的SQL语句
  • insertProvider。insert语句的动态SQL映射。
  • update。映射更新的SQL语句。
  • updateProvider
  • delete。映射删除的SQL语句。
  • deleteProvider
  • result。在列和属性直接的单独结果映射。属性包括:id、column、property、javaType、jdbcTpye、type Handler、one、many。id是一个布尔值,表示十分被用于主键映射。one属性是单独的联系,与相似。many属性是对集合而言的,与相似。
  • results。多结果映射(result)列表。
  • options。提供配置选项的附加值。@Options(userGenerateKeys=true,keProperty="id")
  • one。复杂类型的单独属性映射。必须制定select属性。表示已映射SQL语句的完全限定名。
  • many。复杂类型的集合属性映射。必须制定select属性。表示已映射SQL语句的完全限定名。
  • param。用于映射器方法来给每个参数取一个名字。否则,多参数将会以它们的顺序位置和SQL语句中的表达式进行映射。
  • SelectKey。用于生产主键。
    • 属性statement="select max(empNo)+1 as myNo from emp":表示定义的子查询语句
      • before=true:表示在之前执行,booler类型的,所以为true
      • keyColumn="myNo":表示查询所返回的类名
      • resultType=int.class:表示返回值得类型
      • keyProperty="empNo":表示将该查询的属性设置到某个列中,此处设置到empNo中

1. CRUD基本注解

1.1 接口定义

  • WebUserDao.java
public interface WebUserDao {
     /*
     * statement="select max(empNo)+1 as myNo from emp":表示定义的子查询语句
     * before=true:表示在之前执行,booler类型的,所以为true
     * keyColumn="myNo":表示查询所返回的类名
     * resultType=int.class:表示返回值得类型
     * keyProperty="empNo" :表示将该查询的属性设置到某个列中,此处设置到empNo中
     */
    @Insert("insert into web_user (id, username,loginname,password, phone, address) values (#{id},#{username},#{loginname},#{password},#{phone},#{address})")
    @SelectKey(statement="select SQ_PHONE_DEPARTMENT_ID.nextval as id from dual",before=true,keyColumn="id",resultType=int.class,keyProperty="id" )
    int saveUser(WebUser user);
  
    @Select("select * from web_user where id = #{id}")
    @Results({
        @Result(column="id",property="id"),
        @Result(column="username",property="username"),
        @Result(column="loginname",property="loginname"),
        @Result(column="password",property="password"),
        @Result(column="phone",property="phone"),
        @Result(column="address",property="address"),
    })
    WebUser selectUserById(int id);
    @Update("update web_user set phone=#{phone}, password=#{password},address=#{address} where id=#{id}")
    int modifyUser(WebUser user);
    
    @Delete("delete from web_user where id=${id}")
    int deleteUser(@Param("id") int id);

}

1.2 测试

  • CrudAnnotationTest.java
public class CrudAnnotationTest {

        public static void main(String[] args) {
        SqlSession session = SqlSessionFactoryUtil.getSession();
        WebUserDao userDao = session.getMapper(WebUserDao.class);
        CrudAnnotationTest test = new CrudAnnotationTest();
        //test.testInsert(userDao);
        //test.testUpdate(userDao);
        //test.testDelete(userDao);
        test.testSelect(userDao);
        
        session.commit();
        session.close();
    }
    
    public void testInsert(WebUserDao userDao) {
        WebUser user = new WebUser();
        user.setUsername("杨涵");
        user.setLoginname("Yanhan");
        user.setPassword("123456");
        user.setAddress("石各庄");
        userDao.saveUser(user);
        System.out.println(user.getId());
    }
    
    public void testSelect(WebUserDao userDao) {
        WebUser user = userDao.selectUserById(8);
        System.out.println(user.toString());
    }
    public void testUpdate(WebUserDao userDao) {
        WebUser user = new WebUser();
        user.setPhone("16677778888");
        user.setPassword("666666");
        user.setAddress("石家庄");
        user.setId(7);
        int num = userDao.modifyUser(user);
        System.out.println(num);
    }
    
    public void testDelete(WebUserDao userDao) {
        int num = userDao.deleteUser(7);
        System.out.println(num);
    }


}

1.3 插入空值异常处理

解决插入空值产生的异常 Error setting null for parameter #5 with JdbcType OTHER .
说明:postgreSQL,MySQL,SQLSERVER都支持JdbcType.NULL类型,Oracle是不支持,适配的时候也因为这个问题导致mybatis报错。

解决方法

  • MyBatis-config.xml 中设置当JDBC类型为空值时,要指定的值得,默认为OTHER,我们指定为NULL就好了(注意是大写的NULL)。

  
  • 在每个数据变量那里设置相应的jdbcType

2. 一对一、一对多、多对多映射

2.1 一对一

2.1.1 java bean
  • 同(二) 6.2.1
2.1.2 接口
  • PersonDao.java
public interface PersonDao {
    @Select("select * from person where id = #{id}")
    @Results({
        @Result(column="ID" ,property="id"),
        @Result(column="NAME",property="name"),
        @Result(column="SEX" ,property="sex"),
        @Result(column="AGE",property="age"),
        @Result(column="card_id",property="card",//表示person的card属性对于表的card_id列
        one=@One(
                select="com.zhougl.web.annotation.dao.CardDao.selectCardById",
                fetchType=FetchType.EAGER))
    })
    Person selectPersonById(Integer id);

}
  • CardDao.java
public interface CardDao {
    @Select("select * from Card where id = #{id}")
    Card selectCardById(Integer id);
}
2.1.3 测试
public void testOneToOne(SqlSession session) {
         PersonDao dao = session.getMapper(PersonDao.class);
         Person person =dao.selectPersonById(1);
         System.out.println(person.toString());
         System.out.println(person.getCard().toString());
    }

2.2 一对多

2.2.1 java bean
  • 同(二) 6.1.1
2.2.2 接口
  • WebClassDao.java
public interface WebClassDao {
    @Select("select * from WEB_CLASS where ID = #{id}")
    @Results({
        @Result(column="ID",property="id" ),
        @Result(column="CODE",property="code"),
        @Result(column="NAME",property="name"),
        @Result(column="id",property="students",
        many=@Many(
                select="com.zhougl.web.annotation.dao.StudentDao.selectStudentByClassId",
                fetchType=FetchType.LAZY))
    })
    WebClass selectWebClassById(int id);
}
  • StudentDao.java
public interface StudentDao {
   
    //Student selectStudentById(int id);
    @Select("select * from STUDENT  where CLASS_ID = #{classId}")
    @Results({
        @Result(column="Id",property="id"),
        @Result(column="name",property="name"),
        @Result(column="SEX",property="sex"),
        @Result(column="AGE",property="age")
    })
    List selectStudentByClassId(int classId);

}
2.2.3 测试
public void testOneToMany(SqlSession session) {
        WebClassDao dao = session.getMapper(WebClassDao.class);
         WebClass webClass = dao.selectWebClassById(1);
         System.out.println(webClass.toString());
         webClass.getStudents().forEach(student ->System.out.println(student.toString()));
    }

2.3 多对多

2.3.1 java bean
  • 同(二)7.4.1
2.3.2 接口
  • WebUserDao.java
public interface WebUserDao {
WebUser selectUserById(int id);
    @Update("update web_user set phone=#{phone}, password=#{password},address=#{address} where id=#{id}")
    int modifyUser(WebUser user);
}    
  • WebArticleDao.java
public interface WebArticleDao {
    @Select("select  *  from WEB_ARTICLE where id in( select article_id from WEB_ITEM where order_id =#{orderId} )")
    List selectArticleByOrderId(int orderId);
}
  • WebOrderDao.java
public interface WebOrderDao {
    @Select("select * from WEB_ORDER where id = #{id}")
    @Results({
        @Result(column="id",property="id"),
        @Result(column="CODE",property="code"),
        @Result(column="TOTAL",property="total"),
        @Result(column="user_id",property="user",
        one=@One(select="com.zhougl.web.annotation.dao.WebUserDao.selectUserById",fetchType=FetchType.EAGER)),
        @Result(column="id",property="articles" ,
        many=@Many(select="com.zhougl.web.annotation.dao.WebArticleDao.selectArticleByOrderId",fetchType=FetchType.LAZY)),
    })
    WebOrder selectOrderById(int id); 
}
2.3.3 测试
public void testManyToMany(SqlSession session) {
        WebOrderDao dao = session.getMapper(WebOrderDao.class);
         WebOrder order = dao.selectOrderById(1);
         System.out.println(order.toString());
         System.out.println(order.getUser().toString());
         order.getArticles().forEach(article ->System.out.println(article.toString()));
        
    }
//结果
WebOrder [id=1, code=201811300001, total=3666.65, userId=null]
WebUser [id=1, username=梁二燕, loginname=yangzi, password=123456, phone=15555556666, address=武汉]
WebArticle [id=1, name=花鸟画, price=1999.99, remark=梁老师著作]
WebArticle [id=2, name=肖像画, price=1666.66, remark=梁老师著作]

3. Provider注解动态SQL

3.1 @InsertProvider

3.1.1 构建动态SQL类
public class EmployeeDynaSqlProvider {
    
    public String insertEmployee(WebEmployee employee){
        return new SQL() {
            {
                INSERT_INTO("web_employee");
                if(employee.getId()!=null) {
                    VALUES("id", "#{id}");
                }
                if(employee.getLoginname()!=null) {
                    VALUES("loginname", "#{loginname}");
                }
                if(employee.getLoginname()!=null) {
                    VALUES("password", "#{password}");
                }
                if(employee.getLoginname()!=null) {
                    VALUES("name", "#{name}");
                }
                if(employee.getLoginname()!=null) {
                    VALUES("sex", "#{sex}");
                }
                if(employee.getLoginname()!=null) {
                    VALUES("age", "#{age}");
                }
                if(employee.getLoginname()!=null) {
                    VALUES("phone", "#{phone}");
                }
                if(employee.getLoginname()!=null) {
                    VALUES("sal", "#{sal}");
                }
                if(employee.getLoginname()!=null) {
                    VALUES("state", "#{state}");
                }
            }
        }.toString();
    }
}
3.1.2 接口
public interface WebEmployeeDao {
    @InsertProvider(type=EmployeeDynaSqlProvider.class,method="insertEmployee")
    @SelectKey(statement="select max(id)+1 as id from web_employee",before=true,keyColumn="id",resultType=int.class,keyProperty="id" )
    int insertEmployee(WebEmployee employee);
}
3.1.3 测试类
public class DynamicSQLTest {
    public static void main(String[] args) {
        SqlSession session = SqlSessionFactoryUtil.getSession();
        WebEmployeeDao dao = session.getMapper(WebEmployeeDao.class);
        DynamicSQLTest test = new DynamicSQLTest();
        test.testInsertEmployee(dao);
        //test.testUpdateEmployee(dao);
        //test.testDeleteEmployee(dao);
        //test.testSelectWhithMap(dao);
        session.commit();
        session.close();
    }
    
    public void testInsertEmployee(WebEmployeeDao dao) {
        WebEmployee employee = new WebEmployee();
        employee.setName("菠萝赛东");
        employee.setLoginname("boluosaidong");
        employee.setPassword("123456");
        employee.setState("active");
        int num = dao.insertEmployee(employee);
        System.out.println(num);        
    }
  • 结果
==>  Preparing: select max(id)+1 as id from web_employee 
==> Parameters: 
<==      Total: 1
==>  Preparing: INSERT INTO web_employee (id, loginname, password, name, sex, age, phone, sal, state) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) 
==> Parameters: 6(Integer), boluosaidong(String), 123456(String), 菠萝赛东(String), null, null, null, null, active(String)
<==    Updates: 1
WebEmployee [id=6, loginname=boluosaidong, password=123456, name=菠萝赛东, sex=null, age=null, phone=null, sal=null, state=active]

3.1 @SelectProvider

3.1.1 构建动态SQL类
public class EmployeeDynaSqlProvider {
    
    public String selectWhithMap(Map map) {
        return new SQL(){
            {
                SELECT("*");
                FROM("web_employee");
                //多个参数时
                //SELECT * FROM web_employee WHERE ( id = ? AND loginname = ? and password = ? AND state = ? ) 
                if(map.get("id")!=null) {
                    WHERE(" id = #{id} ");
                }
                if(map.get("loginname")!=null && map.get("password")!=null) {
                    WHERE(" loginname = #{loginname} and password = #{password} ");
                }
                if(map.get("name")!=null) {
                    WHERE(" name = #{name} ");
                }
                if(map.get("phone")!=null) {
                    WHERE(" phone = #{phone} ");
                }
                if(map.get("state")!=null) {
                    WHERE(" state = #{state} ");
                }
            }
        }.toString();
    }
}
3.1.2 接口
public interface WebEmployeeDao {
    @SelectProvider(type=EmployeeDynaSqlProvider.class,method="selectWhithMap")
    List selectEmployeeWithMap(HashMap map);
}
3.1.3 测试类
public class DynamicSQLTest {
    
    public void testSelectWhithMap(WebEmployeeDao dao) {
        HashMap map = new HashMap();
        //map.put("id", 1);
        //map.put("loginname", "rose");
        //map.put("password", "123456");
        map.put("state", "active");
        //map.put("state", "inactive");
        List employees = dao.selectEmployeeWithMap(map);
        employees.forEach(WebEmployee -> System.out.println(WebEmployee.toString()));
    }
}    
  • 结果
==>  Preparing: SELECT * FROM web_employee WHERE ( state = ? ) 
==> Parameters: active(String)
<==      Total: 5
WebEmployee [id=1, loginname=jack, password=123456, name=苏文, sex=男, age=26, phone=15566665555, sal=9800, state=active]
WebEmployee [id=2, loginname=rose, password=123456, name=苏问问, sex=女, age=24, phone=16655556666, sal=6800, state=active]
WebEmployee [id=3, loginname=tom, password=123456, name=陈大山, sex=男, age=29, phone=17766665555, sal=8800, state=active]
WebEmployee [id=4, loginname=alice, password=123456, name=苏苏豆豆, sex=女, age=25, phone=19955556666, sal=5800, state=active]
WebEmployee [id=6, loginname=boluosaidong, password=123456, name=菠萝赛东, sex=null, age=null, phone=null, sal=null, state=active]

3.1 @UpdateProvider

3.1.1 构建动态SQL类
public class EmployeeDynaSqlProvider {
    
    public String updateEmployee(WebEmployee employee) {
        return new SQL() {
            {
                UPDATE("web_employee");
                if(employee.getLoginname()!=null) {
                    SET("loginname = #{loginname}");
                }
                if(employee.getLoginname()!=null) {
                    SET("password = #{password}");
                }
                if(employee.getLoginname()!=null) {
                    SET("name = #{name}");
                }
                if(employee.getLoginname()!=null) {
                    SET("sex = #{sex}");
                }
                if(employee.getLoginname()!=null) {
                    SET("age = #{age}");
                }
                if(employee.getLoginname()!=null) {
                    SET("phone = #{phone}");
                }
                if(employee.getLoginname()!=null) {
                    SET("sal = #{sal}");
                }
                if(employee.getLoginname()!=null) {
                    SET("state = #{state}");
                }
                WHERE(" id = #{id} ");
            }
        }.toString();
    }
}
3.1.2 接口
public interface WebEmployeeDao {
    @UpdateProvider(type=EmployeeDynaSqlProvider.class,method="updateEmployee")
    int updateEmployee(WebEmployee employee);
}
3.1.3 测试类
public class DynamicSQLTest {
    public void testUpdateEmployee(WebEmployeeDao dao) {
        WebEmployee employee = new WebEmployee();
        employee.setId(6);
        employee.setName("菠萝赛西");
        employee.setLoginname("boluosaiXi");
        employee.setPassword("789012");
        employee.setState("active");
        int num = dao.updateEmployee(employee);
        System.out.println(num);        
    }       
}
  • 结果
==>  Preparing: UPDATE web_employee SET loginname = ?, password = ?, name = ?, sex = ?, age = ?, phone = ?, sal = ?, state = ? WHERE ( id = ? ) 
==> Parameters: boluosaiXi(String), 789012(String), 菠萝赛西(String), null, null, null, null, active(String), 6(Integer)
<==    Updates: 1

WebEmployee [id=6, loginname=boluosaiXi, password=789012, name=菠萝赛西, sex=null, age=null, phone=null, sal=null, state=active]

3.1 @DeleteProvider

3.1.1 构建动态SQL类
public class EmployeeDynaSqlProvider {
    
    public String deleteEmployee(WebEmployee employee) {
        return new SQL() {
            {
                DELETE_FROM("web_employee");
                if(employee.getId()!=null) {
                    WHERE(" id = #{id} ");
                }
                if(employee.getLoginname()!=null) {
                    WHERE("loginname", "#{loginname}");
                }
                if(employee.getLoginname()!=null) {
                    WHERE("password", "#{password}");
                }
                if(employee.getLoginname()!=null) {
                    WHERE("name", "#{name}");
                }
                if(employee.getLoginname()!=null) {
                    WHERE("sex", "#{sex}");
                }
                if(employee.getLoginname()!=null) {
                    WHERE("age", "#{age}");
                }
                if(employee.getLoginname()!=null) {
                    WHERE("phone", "#{phone}");
                }
                if(employee.getLoginname()!=null) {
                    WHERE("sal", "#{sal}");
                }
                if(employee.getLoginname()!=null) {
                    WHERE("state", "#{state}");
                }
            }
        }.toString();
    }
}
3.1.2 接口
public interface WebEmployeeDao {
    @DeleteProvider(type=EmployeeDynaSqlProvider.class,method="deleteEmployee")
    int deleteEmployee(WebEmployee employee);
}
3.1.3 测试类
public class DynamicSQLTest {
    public void testDeleteEmployee(WebEmployeeDao dao) {
        WebEmployee employee = new WebEmployee();
        employee.setId(6);
        int num = dao.deleteEmployee(employee);
        System.out.println(num);        
    }       
}
  • 结果
==>  Preparing: DELETE FROM web_employee WHERE ( id = ? ) 
==> Parameters: 6(Integer)
<==    Updates: 1

你可能感兴趣的:(mybatis 学习笔记(总)2018-12-02)