Mybatis上

为什么学习Mybatis

Hibernate的核心是ORM,将表的记录和对象进行全自动映射,目标是消除SQL,但是对于复杂的查询,需要进行定制,我们需要精通HQL来满足要求.

Mybatis则将SQL语句写在配置文件中,实现SQL和Java分离,且SQL是可定制,由开发人员控制.

Mybait下载目录:https://github.com/mybatis/mybatis-3/releases

Mybatis- Helloworld

1.根据配置文件(全局配置文件)创建SQLSessionFactory对象,这个文件中有数据源的配置信息. myconfig.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>  
     <environments default="development">  
         <environment id="development">  
             <transactionManager type="JDBC"/>  
                 <dataSource type="POOLED">  
                 <property name="driver" value="com.mysql.jdbc.Driver"/>  
                 <property name="url" value="jdbc:mysql://localhost:3306"/>
                 <property name="username" value="root"/>  
                 <property name="password" value="123456"/>  
                 </dataSource>  
         </environment>  
 </environments>  
</configuration>  

2.创建SQL映射文件.eg: employee.xml

<?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">  
<!-- 名称空间 ,可以随便写,但是如果使用接口,则需要指定为接口的全类名,-->  
<Mapper namespace="com.dong.service.employeeMapper">  
     <select id="selectEmployee" resultType="com.dong.service.employee"  >  
        select * from Blog where id = #{id}  
     </select>  
</Mapper>  

3.将SQL映射文件放入到全局配置文件.

 <!-- 将写好的sql映射文件一定要写到全局配置文件myconfig.xml中 -->  
 <Mappers>  
 <Mapper resource="employee.xml"/>  
 </Mappers> 

4.写代码:根据配置文件获取SQLSessionFactory -> 然后获取SQLSession ,表示SQL的一次会话,然后使用SQL的唯一标志来告诉mybatis执行哪个SQL语句,->关闭session.

package com.dong.controller;  
  
import java.io.IOException;  
import java.io.InputStream;  
import org.apache.ibatis.io.Resources;  
import org.apache.ibatis.session.SqlSession;  
import org.apache.ibatis.session.SqlSessionFactory;  
import org.apache.ibatis.session.SqlSessionFactoryBuilder;  
import com.dong.service.employee;  
import com.dong.service.employeeMapper;  
  
public class Mybatis {  
    public static void main(String[] args) throws IOException {  
      
    }  
      
    public void test() throws IOException {  
        String resource = "config/myconfig.xml";  
        InputStream inputStream = Resources.getResourceAsStream(resource);  
        SqlSessionFactory sqlSessionFactory =  
                new SqlSessionFactoryBuilder().build(inputStream);    
        //获取sqlSession实例,可以直接执行已经映射的sql语句  
        SqlSession openSession = null ;  
        try {  
            openSession  = sqlSessionFactory.openSession();       
            employee emp = openSession.selectOne("org.mybatis.example.employeeMapper.selectEmp", 1);  //这个时候我们的namespace是一个随便写的值,com.dong.service.employeeMapper为namespace, selectEmployee是sql标识id.  
            System.out.println(emp.toString());   
        } finally {  
            openSession.close();  
        }  
    }  
}  

问题:

在上面的SQL语句中,使用selectOne需要一个id值,但没有显示的限制传递的类型,也没有进行判断,有可能导致查询不到,eg: 传递“ad”,而不是数字,因此Mybatis使用更高级的写法:

接口的方式,更安全:

1.创建接口. employeeMapper

package com.dong.service;  
  
import java.util.Map;  
  
public interface employeeMapper {  
    public employee getEmployee(Integer id);  
}  

2.在Mapper文件中,将命名空间改为接口的全类名,然后将SQL的id改为方法名.

<?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">  
<!-- 名称空间 ,可以随便写,但是如果使用接口,则需要指定为接口的全类名,-->  
<Mapper namespace="com.dong.service.employeeMapper">  
     <select id="getEmployee" resultType="com.dong.service.employee" databaseId="mysql" >  
        select * from Blog where id = #{id}  
     </select>  
</Mapper>  

3.写代码

public void test1() throws IOException {  
        String resource = "config/myconfig.xml";  
        InputStream inputStream = Resources.getResourceAsStream(resource);  
        SqlSessionFactory sqlSessionFactory =  
                new SqlSessionFactoryBuilder().build(inputStream);    
        SqlSession openSession = null;  
        //获取sqlSession实例,可以直接执行已经映射的sql语句  
        try {  
            openSession = sqlSessionFactory.openSession();  
            employeeMapper Mapper = openSession.getMapper(employeeMapper.class);  
            employee employee = Mapper.getEmployee(1);  
            System.out.println(employee.toString());  
            openSession.commit();  
        }finally {  
            openSession.close();      
        }  
    }  

每个接口方法都对应Mapper.xml中的一个映射,

SqlSession 和 Connector是非线程安全的,每次使用我们最好创建一个新的SQLSession.

 Mapper没有接口的实现类,Mybatis会生成一个代理.

       配置文件

配置文件:全局配置文件, 包含数据库信息,事务管理,系统运行环境,注意全局配置文件可以没有,Mybatis使用默认的配置.eg: myconfig.xml

SQL映射文件:必须有,保存了每一个SQL语句的映射信息.eg:eployeeMapper.xml

Mybatis 全局配置文件

注意:这些标签都不需包含在<Configuration>..</Configuraion>中.

properteis:用来引入外部配置文件

resource:用来引入类路径下配置文件

uri:引入网络路径或者磁盘路径下的资源

<properties resource="db.propreties"></properties>  

settings:包含很多设置项,设置项直接影响mybatis的运行时行为,

settting:用于设置属性,

setting name:属性名   value 属性值.eg:开启驼峰命令识别

<settings>  
        <setting name="MapUnderscoreToCamelCase" value="true"/>  
</settings>  

typeAliases :别名处理器, Java类型起别名,使得引用方便,注意别名不区分大小写.

typeAlis:为某个Java类型起别名,

              type:指定想要其别的全类名,默认别名是类名小写.

              alias:新的别名

<typeAliases>  
        <typeAlias type="com.dong.service.employee" alias="emp"/>  
</typeAliases>  

package:为某个包下类批量其别名,

           name:当前包的所有类其别名,默认别名为类名小写.

           alias:新的别名

       在批量起别名的情况下,使用注解@Alias()在特定的类上指定别名

<typeAliases>   
        <package name="com.dong.controller"/>  
</typeAliases>  

typeHandlers : 进行数据库类型和Java类型映射

plugins: 进行插件,mybatis可以进行拦截,拦截使用插件进行,

environments:进行环境配置,mybatis可以配置多种环境,default指定使用某种环境,可以快速切换环境.

environment:配置一个具体的环境信息,必须有两个标签,即dataSource ,transcationManager

environment id: 代表当前环境的唯一标识.

transcationManager:配置事务管理器,:

             type:JDBC | MANAGED,也可以自定义事务管理器,

            dataSource:数据源,

            type:UNPOOLED | POOLED | JNDI,也可以自定义数据源,

<environments default="development">  
     <environment id="development">  
         <transactionManager type="JDBC"/>  
             <dataSource type="POOLED">  
             <property name="driver" value="${jdbc.driver}"/>  
             <property name="url" value="${jdbc.url}"/>  
             <property name="username" value="${jdbc.username}"/>  
             <property name="password" value="${jdbc.password}"/>  
             </dataSource>  
</environment>  

databaseIdProvider:Mybatis可执行不同的SQL语句根据不同的数据库厂商,支持多数据库厂商,eg:Oracle

       type:"DB_VENDOR",作用:得到数据库厂商的标识. MYSQL, Oracle,SQL Server,可以对不同的数据库厂商起别名.

 <databaseIdProvider type="DB_VENDOR">  
        <!-- 为不同的数据库厂商起别名 -->  
        <property name="MySQL" value="mysql"/>  
        <property name="Oracle" value="oracle"/>  
        <property name="SQL Server" value="sqlserver"/>  
    </databaseIdProvider>

  

       使用方式在Mapper文件中,select标签中使用 databaseId="mySQL"属性来设置使用哪个数据库厂商,值为别名.

<select id="getEmployee" resultType="com.dong.service.employee" databaseId="mysql" >  
        select * from Blog where id = #{id}  
</select>  

Mappers:将SQL映射注册到全局配置中

       Mapper:注册SQL映射

              resource:引入类路径下

              url:应用网络路径|磁盘路径下

<!-- 将写好的sql映射文件一定要写到全局配置文件 -->  
<Mappers>  
<Mapper resource="employee.xml"/>  
</Mappers> 

 

 package:批量注册, name: 具体包名, 需要将映射文件放在包的目录下,

<!-- 将写好的sql映射文件一定要写到全局配置文件 -->  
<Mappers>  
<package name="com.dong.Mappers"/>  
</Mappers>  

class:注册接口,

1.有映射文件,需要将配置文件放到接口同一目录下,配置文件的名字与接口同名;

<Mappers>   
<Mapper class="com.dong.service.employeeMapper"/>  
</Mappers>  

2.没有映射文件, 直接在接口上写相应的注解@Select(SQL语句),然后再Mapper中进行注册,eg:employeeMapper接口

public interface employeeMapper {   
    @Select("selct * from table_name where id = #{id} ")  
    public employee getEmployee(Integer id);  
}  

全局配置文件,config.xml(名字随意)

<Mappers>  
<Mapper class="com.dong.service.employeeMapper"/>  
</Mappers>  

注意:全局文件编辑也是有顺序的,

   推荐比较重要的dao,写SQL映射文件,不重要的,简单的,为了快速开发,使用注解方式.

Mybatis映射文件

增删改查:

public interface employeeMapper {  
    public employee getEmployees2 (Map<String ,Object> Map);  
    public void addEmployee(employee emp);  
    public void updateEmployee(employee emp);  
    public void deleteEmployee(employee emp);  
}  

获取自增主键

Mybatis 支持自增主键,自增主键的获取,通过statement.getGenerateKeys(),

useGeneratedKeys="true":使用自增主键获取主键值策略,

keyProperty="xxx":指定对应的主键属性,也就是mybatis获取到主键值以后,将这个值封装到JavaBean的哪个属性.

由于主键自增,所以SQL语句不需要写主键,但在构建映射bean时,需要填写主键的值,可以使用null代替.

<insert id="addEmployee" parameterType="com.dong.service.employee" useGeneratedKeys="true" keyProperty="id">  
    insert into tbl_employee(last_name,email,gendar) values (#{lastName},#{email},#{gendar})  
</insert>  

       Oracle:不支持自增,主键是从序列中获取,

插入时的主键是从序列中获取的,使用<selectKey>,进行查询主键语句, KeyProperty:将查询的主键封装到bean的哪个属性, order:"BEFROE",查主键的SQL是在前执行,"AFTER",在后执行,resultType:xxx,结果的类型.

keyProperty 也可使用AFTER,获取当前的序列值,但是之前的insert语句为:insert  into ... value( employee_seq.nextval....);

参数处理

单个参数:Mybatis不做任何处理, 使用 #{参数名},获取参数值,

多个参数:Mybatis多个参数会被封装成一个Map, key:param1 ...paramN, value:是传入的参数值,  #{} 从Map中获取指定的key,

#{param1...N} ,对于参数过多,则不好使用,使用命名参数,

  <select id="getEmployees" resultType="com.dong.service.employee">  
    select * from BLog where id = #{param1} and id2 = #{param2}  
</select>  

命名参数:明确指定封装参数时Map的key:@Param("id")

key:为使用@Param注解的值

value:为参数值

public employee getEmployees(@Param("id")Integer id,@Param("id2")Integer id2);  

  #{指定的命名值}

<select id="getEmployees" resultType="com.dong.service.employee">  
    select * from BLog where id = #{id} and id2 = #{id2}  
</select> 

 

POJO

如果多个参数正好是Bean,则可以直接传递POJO, #{属性名} 即可获取pojo的值,

如果多个参数不是业务逻辑的模型,没有对应的POJO,则可以传入Map,

#{key} : 取出Map对应的值,

如果多个参数不是对应的Bean,但经常使用,则推荐使用一个(transfer object) 传输对象,

特别注意,如果Collection(list, Set)类型或者数组,也会特殊处理,把传入的list或者数组封装在Map中,

 Key: 为collection

如果是List,可使用key:list  eg: #{list[0]}

如果是Array,可使用key:array

<insert id="addEmployee" parameterType="com.dong.service.employee" useGeneratedKeys="true" keyProperty="id">  
    insert into tbl_employee(last_name,email,gendar) values (#{list[0]},#{list[1]},#{list[2]})  
 </insert>  

参数值的获取

  #{}:获取Map中的值或者POJO对象属性的值,

  ${}:获取Map中的值或POJO对象属性的值,

  区别: #{}是以预编译的形式,将参数设置到SQL语句,使用占位符

              ${}取出值直接封装在SQL语句中,存在安全问题.

 大多数情况下,我们取参数的值都应该使用 # {  } ,在不支持占位符的地方我们可以使用${}方式.

 #{}更丰富的用法:

 规定参数的一些规则:

JavaType,jdbcType,mode,numericScale,resultMap,typeHandler,jdbcTypeName,expression.

jdbcType:当数据为null时,有些数据库不能识别mybatis对null的默认处理,eg:Oracle,

mybatis将 null类型映射为数据库类型的 OTHER类型,对于Oracle是不认识,而对MySQL可以识别.可以进行制定:eg: #{email,jdbcType=NULL}

由于全局配置中的jdbcTypeForNull=OTHER,oracle不支持, 所以可以在#{}中修改,也可以修改全局配置,

Select

Select: 普通的参数不做介绍,

当返回值为List时,在写映射时,resultType的类型为List中元素的类型,

当返回类型Map时,返回一条记录的Map,,key为列名,值为对应的值,在写映射时,resultType的类型为Map,

当返回类型Map时,返回多条记录封装成一个Map,Map<String,Employee>:键是主键,值为封装后的Javabean,

写映射时,resultType的类型为集合中元素的类型,如果想要指定key使用哪个属性,则需要在方法上使用@MapKey("")

resultMap:自定义结果集映射规则,resultMap 和 resultType只能二选一,

                   type:自定义Java类型, id:唯一id,方便引用,

                   <resultMap type="", id ="" >

                          id: 指定主键的封装规则,column:指定列,  property:指定对应的JavaBean属性,

                          <id column="" ,property=""/>

                          指定普通列封装的规则,

                          <result column="" ,property=""/>

                          其他不指定的列会自动封装,尽量写出所有列的对应,

                   </resultMap>

<resultMap type="com.dong.service.employee" id="test">  
    <id column="id" property="id"/>  
    <result column="name" property="name"/>  
 </resultMap>  

            然后再select中使用resultMap引用定义好的映射规则即可.

  <select id="getEmployee" resultMap="test" resultType="com.dong.service.employee" databaseId="mysql" >  
    select * from Blog where id = #{id}  
</select>     

联合查询,级联属性封装结果,对于别的表的属性,则使用属性.属性即可.还可以使用:<association>可以指定联合的JavaBean对象,eg:

            proeorty:指定哪个对象是联合属性,  JavaType:指定属性对象的类型,然后再assocaition的标签内定义映射规则,

<association property="dept" JavaType="com.dong.department">  
    <id.../>  
    <result .../>  
</association>  

association分步查询

select:表明当前属性是调用select指定的方法查出的结果

column:指定将哪一列的值传递给这个方法

流程:首先使用select指定方法(传入column指定的这列参数的值,)查出对象,并封装给property指定的属性,

如果想要在使用的时候才进行加载,则可以使用懒加载机制,可在setting中进行设置.

如果关联多个对象:集合

即查询部分是,将对应部分的所有员工信息也查询出来:

     collection定义关联集合类型的属性的封装,

     property:对应的属性名   ofType:指定集合列元素的类型  

     <collection property= "" ofType="com.dong.xxxbaen">

           定义这个集合中的元素的封装规则,

            <id column="xx" property="xx" />

            <result column="xx" property="xx" />

            ......

     </collection>

<resultMap type="com.dong.service.employee" id="test">  
    <id column="id" property="id"/>  
    <result column="name" property="name"/>  
    <!-- association 是关联一个对象,如果是多个对象,则使用collection -->  
    <!-- property为对应的多个对象的属性,select为另一个查询,其值为另一个查询的id标识,column为使用哪个id进行查询 -->  
    <collection property="emp"   
        select="funciont_id" column="id" fetchType="lazy"></collection>  
</resultMap>  

注:如何在collection的 select 语句中传入多个column值,可以将多列值封装到Map中传递, column= “{key1 = column1,key2 = column2}  fetchType:设置加载,可选延迟加载,立即加载,

discriminator

resultMap中的 discriminator 鉴别器,,用来判断某列的值,然后根据某列的值改变封装行为,

JavaType:列值对应的Java类型,    column:指定判定的列名,

         <discriminator JavaType="string"  column="gender">  
                <case value = " " resultType="xxx">  
                    相应的规则  
                </case>  
                <case value= " "  resultType="xxx">  
                    相应的规则,  
                </case>  
            </discriminator>  

 

 

如有异议,敬请指出,谢谢观看,与君共勉.(观看https://www.bilibili.com/video/av45816095?t=113&p=36

全部评论

相关推荐

勤奋努力的椰子这就开摆:美团骑手在美团工作没毛病
投递美团等公司10个岗位
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务