资讯专栏INFORMATION COLUMN

Java Persistence with MyBatis 3读书笔记

JinB / 1390人阅读

摘要:内部将通过创建事务管理应用服务器负责管理数据库连接生命周期使用。对于大型数据库而言这会导致很差的性能问题。这是指检索出的对象不会被共享并且可以被调用者安全地修改不会其他潜在的调用者或者线程的潜在修改干扰。

第一章 mybatis 简介

以下内容是自己在看本书时觉得重要的地方记录下来,一方面自己做个笔记也希望对其他同行有帮助

简介

mybatis: 是一个简化和实现了Java数据持久层的开源框架爱,抽象和大量的jdbc冗余代码,提供简单的API和数据库加护

mybatis优点

消除大量的JDBC冗余代码

低的学习曲线

很好的域传统数据库协作

接收SQL语句

提供Spring框架集成

提供第三方缓存类库集成

引入更好的性能

mybatis简单使用

mybatis 配置




  

  
  

  
  
    
    
    
    
  

  
  

  

0.1. 创建session Factory 类

package com.mybatis3.util;
import java.io.*;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.*;
public class MyBatisSqlSessionFactory
{
private static SqlSessionFactory sqlSessionFactory;
public static SqlSessionFactory getSqlSessionFactory()
{
    if(sqlSessionFactory == null)
    {
        InputStream inputStream;
try
        {
            inputStream = Resources.
                          getResourceAsStream("mybatis-config.xml");
            sqlSessionFactory = new
            SqlSessionFactoryBuilder().build(inputStream);
        }
        catch (IOException e)
        {
            throw new RuntimeException(e.getCause());
         }
    }
    return sqlSessionFactory;
}
public static SqlSession openSession()
{
    return getSqlSessionFactory().openSession();
}
}

创建xml映射



INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB)
    VALUES(#{studId},#{name},#{email},#{dob})

创建mapper接口

public interface StudentMapper
{
    Student findStudentById(Integer id);
    void insertStudent(Student student);
}

创建会话使用接口

SqlSession session = getSqlSessionFactory().openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
// Select Student by Id
Student student = mapper.selectStudentById(1);
//To insert a Student record
mapper.insertStudent(student);

第二章 mybatis 配置 使用XML配置



    //加载properties文件
  
    
    
  
  //开启缓存
  
    
  
  
  //别名
  
    
    
    
  
  //类型处理器,注册自定义类型
  
    
    
  
  
  //支持配置多个数据源,设置默认环境为开发环境
  
    
      
      
        
        
        
        
      
    
     
      
      
        
      
    
  
  
    
    
    
  

以上是一个简单的基于XML的配置
通过以上XML可以到所有的配置:

加载properties 文件

直接默认值


      
      

如果文件中定义了jdbc.username,以上配置中的默认值会被覆盖掉

通过占位符


  

开启缓存

配置environments default="development" 实现默认环境 ,可以配置不同环境

配置多数据库实现

针对不同的数据库创建不同sessionFactory

InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory defaultSqlSessionFactory = new SqlSessionFactoryBuilder().
build(inputStream);
SqlSessionFactory cartSqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStre
    am, "shoppingcart");
reportSqlSessionFactory = new SqlSessionFactoryBuilder().
build(inputStream, "reports");

如果不指定环境id,则使用默认的环境创建

数据库类型配置

UNPOOLED

mybatis会为每个数据库创建错误一个新的连接,并关闭它。__只适用于小闺蜜数据并发__

POOLED

mybatis创建一个数据库连接池,__开发环境经常使用__  
默认的数据库连接池实现是通过`org.apache.ibatis.datasource.pooled.PooledDataSource`

JNDI

mybatis从应用服务器配置好的JNDI数据源获取数据库连接  

事务管理

JDBC

是由JDBC事务管理器管理事务。 内部将通过JDBCTransactionFactory创建事务管理  

MANAGED

应用服务器负责管理数据库连接生命周期使用。内部使用`ManagedTranscationFactory`类来创建事务管理器

设置别名
由于在* mapper.xml 文件中resultTypeparameterType属性设置要使用全限定名,可以使用别名的形式简化


      
      
      

也可以不用直接设定别名,可以设定包,然后系统自动扫描设置一个以类首字母小写的别名
通过实体类添加注解形式实现

@Alias("")
public class Student{

}

类型处理器
mubatis对一下类型实现內建处理器 :

所有基本数据类型

基本类型的包裹类型(装箱操作对象类型)

byte[]

java.util.Date

java.sql.Date

java.sql.Time

java.sql.Timestamp

java枚举类型

创建自定义的类型处理器,处理自定义类型

//PhoneNumber 自定义的类
public class PhoneTypeHandler extends BaseTypeHandler
{
     @Override
public void setNonNullParameter(PreparedStatement ps, int i,
                                PhoneNumber parameter, JdbcType jdbcType) throws SQLException
{
    ps.setString(i, parameter.getAsString());
}

public PhoneNumber getNullableResult(ResultSet rs, String columnName)  throws SQLException
{
     return new PhoneNumber(rs.getString(columnName));
}

public PhoneNumber getNullableResult(ResultSet rs, int columnIndex) throws SQLException
{
     return new PhoneNumber(rs.getString(columnIndex));
}
}

别忘了注册

全局参数设定(一下是默认的,)


           
           
           
           
           
           
           
           
           
           
           
              
              

配置mappers映射xml文件路径
多种配置形式


     
     
    
    

使用Java 配置

通过XML配置形式了解了mybatis中的各个配置属性, 通过Java API 的配置形式也可以实现

public class MybatisConfig{
    public static SqlSessionFactory getSqlSessionFactory()
    {
      SqlSessionFactory sqlSessionFactory = null;
    try
    {
        DataSource dataSource = DataSourceFactory.getDataSource();
        TransactionFactory transactionFactory = new
        JdbcTransactionFactory();
        Environment environment = new Environment("development",
                transactionFactory, dataSource);
        Configuration configuration = new Configuration(environment);
        configuration.getTypeAliasRegistry().registerAlias("student",
                Student.class);
        configuration.getTypeHandlerRegistry().register(PhoneNumber.
                class, PhoneTypeHandler.class);
        configuration.addMapper(StudentMapper.class);
        //创建
        sqlSessionFactory = new SqlSessionFactoryBuilder().
        build(configuration);
    }
    catch (Exception e)
    {
        throw new RuntimeException(e);
    }
    return sqlSessionFactory;
}
}

创建datasource

public class DataSourceFactory
{
    public static DataSource getDataSource(){
       String driver = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/mybatisdemo";
        String username = "root";
        String password = "admin";
        PooledDataSource dataSource = new PooledDataSource(driver, url,
        username, password);
        return dataSource;
    }
    
    //通过JNDI创建  
    public static DataSource getDataSource(){
        String jndiName = "java:comp/env/jdbc/MyBatisDemoDS";
        try{
                 InitialContext ctx = new InitialContext();
                DataSource dataSource = (DataSource) ctx.lookup(jndiName);
                return dataSource;
        }catch(NamingException e){
            throw new RuntimeException(e);
        }
    }
    
     
}
自定义mybatis日志 mybatis 日志支持

mybatis中针对日志支持的优先级:

SLF4J

Apache Commons Logging

Log4j 2

Log4j

JDK logging

mybatis 设置日志

调用一下方式实现

org.apache.ibatis.logging.LogFactory.useSlf4jLogging(); 
org.apache.ibatis.logging.LogFactory.useLog4JLogging();
org.apache.ibatis.logging.LogFactory.useLog4J2Logging(); 
org.apache.ibatis.logging.LogFactory.useJdkLogging();
org.apache.ibatis.logging.LogFactory.useCommonsLogging(); 
org.apache.ibatis.logging.LogFactory.useStdOutLogging();
第三章 XML配置SQL映射器

通过xml的形式映射有两种形式:

只有XML映射

定义xml映射文件

        
        
        
            
        

调用

public Student = findStudentById(Integer id){
    SqlSession session = MybatisUtil.geSqlSession();
    try{
        //通过字符串的形式调用
        Student student = sqlSession.selectOne("com.mybatis3.mappers.StudentMapper.findStudentById",id);
    }
}

带有mapper接口类形式

需要注意的点: __其名空间namespace 应该跟StudentMapper接口的完全限定名保持一至__, __ id,parameterType,returnType 应该分别和 StudentMapper 接口中的方法名, 参数类型,返回值相对应__

mybatis 提供的的映射语句

mybatis 提供多种不同的映射语句:

INSERT

useGeneratedKeys: 设置自增长

keyProperty: 主键属性

SELECT

UPDATE

DELETE

mybatis 不同映射语句实例:

INSERT

通过自增长设置主键


    INSERT INTO STUDENTS(NAME, EMAIL, PHONE)
    VALUES(#{name},#{email},#{phone})

针对支持序列生成主键值


    
        SELECT ELEARNING.STUD_ID_SEQ.NEXTVAL FROM DUAL
    
    INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL, PHONE)
    VALUES(#{studId},#{name},#{email},#{phone})


//使用触发器  

    INSERT INTO STUDENTS(NAME,EMAIL, PHONE)
    VALUES(#{name},#{email},#{phone})
    
        SELECT ELEARNING.STUD_ID_SEQ.CURRVAL FROM DUAL
    

mybatis结果集映射规则:

对于 List, Collection, Iterable类型,返回 java.util.ArrayList

对于Map 类型,返回 java.util.HashMap

对于Set 类型: 返回 java.util.HashSet

对于SortedSet类型: 返回java.util.TreeSet

mybatis 映射关系 一对一映射

方式1: 使用点语法进行映射

public class Student
{
   private Integer studId;
   private String name;
   private String email;
   private Address address;        //一个地址对象, 每个学生对应一个地址  
}


  
  
  
  
  
  
  
  
  
  


//使用了左外连接来查询

方式2: 使用嵌套结果 ResultMap进行映射

引入其他文件定义的ResultMap

__使用标签`association` 引入__  

      
      
      



      
      
      
      
查询语句  

本身内部嵌套


      
      
      
      
        
        
        
        
        
        
      

方式3: 使用其那套select查询语句
每一个对应的对象实现自己的查询语句


     
     


//查询语句



     
    

注意嵌套查询:通过association 将另一个对象的查询语句嵌套进入, 并且此标签好像只能用于查询

一对一查询中内部的对象在数据库中对应的都是一个Id或者唯一标识值,所以此处底部的嵌套xml中的值都是id属性的

一对多映射

使用元素将 一对多类型的结果 映射到 一个对象集合上

使用嵌套对象形式显示

public class Tutor
{
    private Integer tutorId;
    private String name;
    private String email;
    private Address address;
    private List courses;
    / setters & getters
}

  
  
  
  





使用嵌套语句实现


  
  
  
  
  






注意: 嵌套 Select 语句查询会导致 N+1 选择问. 首先,主查询将会执行(1 次),对于主 查询返回的每一行,另外一个查询将会被执行(主查询 N 行,则此查询 N 次)。对于 大型数据库而言,这会导致很差的性能问题。

动态SQL

mybatis 提供: ,,,, 进行构造动态SQL

1. if

    SELECT * FROM COURSES
        WHERE TUTOR_ID= #{tutorId}
    
    AND NAME LIKE #{courseName}
    

当if中test条件成立时, 才会添加if中的内容到SQL语句中

choose, when, otherwise

__mybatis计算 测试条件的值,且使用第一个值为true的子句, 如果没有条件为true,则使用 内的子句。

where
trim

foreach
mybatis Other 处理枚举

存储枚举名

默认情况下mybatis支持开箱方式持久化枚举类型属性, 其通过`EnumTypeHandler`来处理枚举类型与Java类型对应  
默认是使用字符串进行存储的,数据表中对应的是枚举对应的字符串  

存储枚举对应的int类型值

需要将枚举对应的handler修改为以下类  
__还是建议使用默认的形式的,使用顺序的如果改变了枚举对应的顺序,数据库中值就无法对应上了__  

处理 blob类型

默认情况下,mybatis将CLOB类型的列映射到 java.lang.String类型上,
将BLOB 映射到byte[]类型上

多个参数

使用map形式引入


使用参数替代

缓存

默认情况下,mybatis开启一级缓存,对select进行缓存支持。 可以通过开启二级缓存
开启耳机缓存的同时引发的问题:

所有在映射语句文件定义的