Mybatis

作者: FTOLsXD | 来源:发表于2017-02-25 14:23 被阅读134次

    什么是Mybatis?

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)。

    官网对Mybatis的介绍更加具有权威性:

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

    MyBatis是iBatis的升级版,用法有很多的相似之处,但是MyBatis进行了重要的改进。例如:

    1、Mybatis实现了接口绑定,使用更加方便。

    在ibatis2.x中我们需要在DAO的实现类中指定具体对应哪个xml映射文件, 而Mybatis实现了DAO接口与xml映射文件的绑定,自动为我们生成接口的具体实现,使用起来变得更加省事和方便。

    2、对象关系映射的改进,效率更高

    3、MyBatis采用功能强大的基于OGNL的表达式来消除其他元素。


    MyBatis的框架架构

    看到Mybatis的框架图,可以清晰的看到Mybatis的整体核心对象

    mybatis框架图

    MyBatis应用程序根据XML配置文件创建SqlSessionFactory,SqlSessionFactory在根据配置,配置来源于两个地方,一处是配置文件,一处是Java代码的注解,获取一个SqlSession。SqlSession包含了执行sql所需要的所有方法,可以通过SqlSession实例直接运行映射的sql语句,完成对数据的增删改查和事务提交等,用完之后关闭SqlSession。


    MyBatis的优缺点

    优点:

    1、简单易学
    mybatis本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。

    2、灵活
    mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。

    3、解除sql与程序代码的耦合
    通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。

    4、提供映射标签,支持对象与数据库的orm字段关系映射

    5、提供对象关系映射标签,支持对象关系组建维护

    6、提供xml标签,支持编写动态sql。

    缺点:

    1、编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。

    2、SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库。

    3、框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。

    4、二级缓存机制不佳


    总结

    mybatis的优点同样是mybatis的缺点,正因为mybatis使用简单,数据的可靠性、完整性的瓶颈便更多依赖于程序员对sql的使用水平上了。sql写在xml里,虽然方便了修改、优化和统一浏览,但可读性很低,调试也非常困难,也非常受限。

    mybatis没有hibernate那么强大,但是mybatis最大的优点就是简单小巧易于上手,方便浏览修改sql语句。


    实践:

    项目是在springMVC 测试项目的基础之上进行的,相当于整合Spring-springMVC-Mybatis的一个项目。

    首先在之前项目的基础上添加jar包,aopalliance.jar、aspjectj.jar、aspectjweaver.jar、c3po.jar、common-pool.jar、cglib.jar、javassist.jar、dom4j.jar、mybatis.jar、mybatis-spring.jar、mysql-connector-java-5.1.38-bin.jar、log4j.jar、log4j.core.jar、log4j-api.jar。

    工程项目架构图

    web.xml中添加了对spring配置文件的加载

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:com/hb/test/resources/spring/applicationContext.xml
        </param-value>
      </context-param>
    

    User类没变,不再展示。

    创建User类对应的dao接口:

    public interface UserMapper {
        void save(User user);
        boolean update(User user);
        boolean delete(int id);
        User findById(int id);
        List<User> findAll();
    }
    

    User类的sql语句文件UserMapper.xml

    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"   
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
    <!--   
        namespace:必须与对应的接口全类名一致  
        id:必须与对应接口的某个对应的方法名一致  
          
     -->  
     <mapper namespace="com.hb.test.mapper.UserMapper">
        <insert id="save" parameterType="User">
            insert into t_user(user_name,user_password,user_age) values(#{name},#{password},#{age})
        </insert>
        
        <update id="update" parameterType="User">
            update t_user set user_name = #{name}, user_password = #{password}, user_age where user_id = #{id}
        </update>
        <delete id="delete" parameterType="int">
            delete from t_user where user_id = #{id}
        </delete>
        
        <select id="findById" parameterType="int" resultType="User">
            select * from t_user where user_id = #{id}
        </select>
        
        <select id="findAll" resultType="User">
            select * from t_user
        </select>
     </mapper>
    

    创建MyBatis的mapper配置文件
    在src/com/hb/test/resources/mabatis中创建MyBatis配置文件:mybatis-config.xml。

    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"   
    "http://mybatis.org/dtd/mybatis-3-config.dtd">  
    <configuration>  
        <!-- 实体类,简称 -设置别名 -->  
        <typeAliases>
            <typeAlias alias="User" type="com.hb.test.bean.User"/>
        </typeAliases>
        <!-- 实体接口映射资源 -->  
        <!-- 
            说明:如果xxMapper.xml配置文件放在和xxMapper.java统一目录下,mappers也可以省略,因为org.mybatis.spring.mapper.MapperFactoryBean默认会去查找与xxMapper.java相同目录和名称的xxMapper.xml 
        -->  
        <mappers>
            <mapper resource="com/hb/test/mapper/UserMapper.xml"/>
        </mappers>
    </configuration>
    
    

    spring配置文件:

    <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:context="http://www.springframework.org/schema/context"
     xmlns:tx="http://www.springframework.org/schema/tx"
     xmlns:aop="http://www.springframework.org/schema/aop"
     xmlns:util="http://www.springframework.org/schema/util" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/util   
        http://www.springframework.org/schema/util/spring-util-3.1.xsd">
        <context:annotation-config/>
        <context:component-scan base-package="com.hb.test.service"></context:component-scan>
        <!-- spring加载外部配置文件 -->
        <util:properties id="dataSourceProps" location="classpath:com/hb/test/resources/resource/jdbc.properties"/>  
     
        <!-- 定义数据源Bean,使用C3P0数据源实现 -->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
            <property name="driverClass" value="#{dataSourceProps['jdbc.driverClass']}"/>
            <property name="jdbcUrl" value="#{dataSourceProps['jdbc.jdbcUrl']}"/>
            <property name="user" value="#{dataSourceProps['jdbc.user']}"/>
            <property name="password" value="#{dataSourceProps['jdbc.password']}"/>
            <property name="maxPoolSize" value="#{dataSourceProps['jdbc.maxPoolSize']}"/>
            <property name="minPoolSize" value="#{dataSourceProps['jdbc.minPoolSize']}"/>
            <property name="initialPoolSize" value="#{dataSourceProps['jdbc.initialPoolSize']}"/>
            <property name="maxIdleTime" value="#{dataSourceProps['jdbc.maxIdleTime']}"/>
        </bean>
        <!--  
            2. mybatis的SqlSession的工厂: SqlSessionFactoryBean dataSource:引用数据源  
            MyBatis定义数据源,同意加载配置  
        -->  
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="configLocation" value="classpath:com/hb/test/resources/mybatis/mybatis-config.xml" />   
        </bean>
         <!--  
            3. mybatis自动扫描加载Sql映射文件/接口 : MapperScannerConfigurer sqlSessionFactory  
      
            basePackage:指定sql映射文件/接口所在的包(自动扫描)  
        -->  
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.hb.test.mapper"/>
            <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
        </bean> 
    
           <!--  4. 事务管理 : DataSourceTransactionManager dataSource:引用上面定义的数据源 
        -->  
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
        </bean>
        <!-- 5. 使用声明式事务  
             transaction-manager:引用上面定义的事务管理器  
         -->  
        <tx:annotation-driven transaction-manager="txManager"/>
     </beans>
    
    

    User业务类

    @Service
    public class UserServiceImpl implements UserService{
        @Autowired
        private UserMapper userMapper;
        
        @Override
        public void save(User user) {
    
            userMapper.save(user);
        }
    
        @Override
        public boolean update(User user) {
            
            return userMapper.update(user);
        }
    
        @Override
        public boolean delete(int id) {
            
            return userMapper.delete(id);
        }
    
        @Override
        public User findById(int id) {
            
            return userMapper.findById(id);
        }
    
        @Override
        public List<User> findAll() {
            return userMapper.findAll();
        }
    
    }
    
    

    User类控制器

    @Controller
    public class UserController {
        @Resource(name="userServiceImpl")
        private UserService us;
        @RequestMapping("")
        public String create(Model model){
            return "create";
        }
        
        @RequestMapping("/save")
        public String Save(@ModelAttribute("form") User user, Model model){
            
            us.save(user);
            model.addAttribute("user", user);
            return "detail";
        }
    }
    

    运行结果

    在实际操作过程中又遇到了一个坑,在容器启动时报如下错误,让我折腾了好久。

    Failed to convert property value of type 'java.lang.String' to required type 'int' for property 'maxPoolSize'; nested exception is java.lang.NumberFormatException: For input string: "${jdbc.maxPoolSize}"
    

    报错时使用的加载外部资源代码如下:

    <bean id="mappings" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="locations" value="classpath:com/hb/test/resources/resource/jdbc.properties"></property>
        </bean>
    

    原因是当我加入了MapperScannerConfigurer他会优先于PropertyPlaceholderConfigurer执行,所以这个时候,${jdbc.maxPoolSize}还没有被解析呢,故没有被mysql.properties里面的值所替换,所以出现NumberFormatException就是情理之中了这是mybatis-spring的一个己经公开的问题.

    解决方法是使用spring的<util:properties id="dataSourceProps"> 加载指定的jdbc.properties,也可以使用其他的方式,我没有试过.

    相关文章

      网友评论

        本文标题:Mybatis

        本文链接:https://www.haomeiwen.com/subject/hxvwwttx.html