Mybatis(一)

来源:互联网 发布:mssql分布式数据库 编辑:程序博客网 时间:2024/05/22 17:39

Mybatis与Hibernate区别

  • Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句,不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。
  • Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。
  • Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的缺点是学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。

MyBatis的一级缓存和二级缓存?

  • Mybatis首先去缓存中查询结果集,如果没有则查询数据库,如果有则从缓存取出返回结果集就不走数据库。Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象
  • Mybatis的二级缓存即查询缓存,它的作用域是一个mapper的namespace,即在同一个namespace中查询sql可以从缓存中获取数据。二级缓存是可以跨SqlSession的。

介绍

  • MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
  • Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatement、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

名词解释

  • pojo:不按mvc分层,只是java bean有一些属性,还有get set方法
  • domain:不按mvc分层,只是java bean有一些属性,还有get set方法
  • po:用在持久层,还可以再增加或者修改的时候,从页面直接传入action中,它里面的java bean 类名等于表名,属性名等于表的字段名,还有对应的get set方法
  • vo: view object表现层对象,主要用于在高级查询中从页面接收传过来的各种参数.好处是扩展性强
  • bo: 用在servie层,现在企业基本不用.
    这些po,vo, bo,pojo可以用在各种层面,因为都是普通的java bean没有语法错误,但是在企业最好不要混着用,因为这些都是设计的原则,混着用比较乱.不利于代码维护.

MyBatis与Hibernate的理解

  • 相同点:屏蔽jdbc api的底层访问细节,使用我们不用与jdbc api打交道,就可以访问数据。
  • Hibernate是一个全自动的orm映射工具,它可以自动生成sql语句,ibatis需要我们自己在xml配置文件中写sql语句,hibernate要比ibatis功能负责和强大很多。因为hibernate自动生成sql语句,我们无法控制该语句,我们就无法去写特定的高效率的sql。对于一些不太复杂的sql查询,hibernate可以很好帮我们完成。

Mybatis架构

  • 解释
    • SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
    • mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
    • 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
    • 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
    • mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
    • Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
    • Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
    • Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

环境搭建

  • jar包
  • SqlMapConfig.xml是mybatis核心配置文件
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration>    <!-- 和spring整合后 environments配置将废除-->    <environments default="development">        <environment id="development">        <!-- 使用jdbc事务管理-->            <transactionManager type="JDBC" />        <!-- 数据库连接池-->            <dataSource type="POOLED">                <property name="driver" value="com.mysql.jdbc.Driver" />                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />                <property name="username" value="root" />                <property name="password" value="123" />            </dataSource>        </environment>    </environments></configuration>
  • 日志配置
#Global logging configurationlog4j.rootLogger=DEBUG, stdout# Console output...log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
  • sql 映射文件约束
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">

  • mybatis框架需要加载映射文件,将Users.xml添加在SqlMapConfig.xml,如下:
<mappers>        <mapper resource="User.xml"/></mappers>

可以进行CRUD操作(示例:根据id查询用户信息)

测试程序:
public class Mybatis_first {
private SqlSessionFactory sqlSessionFactory;
@Before
public void createSqlSessionFactory() throws IOException {
String resource = “SqlMapConfig.xml”;
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() {
// 数据库会话实例
SqlSession sqlSession = null;
try {
sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne(“test.findUserById”, 10);
System.out.println(user);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close(); } }}}

细节

  • 1) 映射文件中namespace要等于接口的全路径名称
    2) 映射文件中sql语句id要等于接口的方法名称
    3) 映射文件中传入参数类型要等于接口方法的传入参数类型
    4) 映射文件中返回结果集类型要等于接口方法的返回值类型
  • #{}占位符:占位
    如果传入的是基本类型,那么#{}中的变量名称可以随意写
    如果传入的参数是pojo类型,那么#{}中的变量名称必须是pojo中的属性.属性.属性…
  • ${}拼接符:字符串原样拼接
    如果传入的是基本类型,那么${}中的变量名必须是value
    如果传入的参数是pojo类型,那么${}中的变量名称必须是pojo中的属性.属性.属性…
    注意:使用拼接符有可能造成sql注入,在页面输入的时候可以加入校验,不可输入sql关键字,不可输入空格
  • 映射文件:
    1)传入参数类型通过parameterType属性指定
    2)返回结果集类型通过resultType属性指定
  • hibernate和mybatis区别:
    hibernate:它是一个标准的orm框架,比较重量级,学习成本高.
    优点:高度封装,使用起来不用写sql,开发的时候,会减低开发周期.
    缺点:sql语句无法优化
    应用场景:oa(办公自动化系统), erp(企业的流程系统)等,还有一些政府项目,
    总的来说,在用于量不大,并发量小的时候使用.
    mybatis:它不是一个orm框架, 它是对jdbc的轻量级封装, 学习成本低,比较简单
    优点:学习成本低, sql语句可以优化, 执行效率高,速度快
    缺点:编码量较大,会拖慢开发周期
    应用场景: 互联网项目,比如电商,P2p等
    总的来说是用户量较大,并发高的项目.

Dao的开发方式

原始Dao的开发方式

  • 原始Dao开发方法需要程序员编写Dao接口和Dao实现类。
  • 映射文件
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="test"><!-- 根据id获取用户信息 -->    <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">        select * from user where id = #{id}    </select><!-- 添加用户 -->    <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">        select LAST_INSERT_ID()     </selectKey>      insert into user(username,birthday,sex,address)       values(#{username},#{birthday},#{sex},#{address})    </insert></mapper>
  • 接口与实现类
Public interface UserDao {    public User getUserById(int id) throws Exception;    public void insertUser(User user) throws Exception;}Public class UserDaoImpl implements UserDao {    private SqlSessionFactory sqlSessionFactory;    public UserDaoImpl(SqlSessionFactory sqlSessionFactory){        this.setSqlSessionFactory(sqlSessionFactory);}    @Override    public User getUserById(int id) throws Exception {        SqlSession session = sqlSessionFactory.openSession();        User user = null;        try {            //通过sqlsession调用selectOne方法获取一条结果集            //参数1:指定定义的statement的id,参数2:指定向statement中传递的参数            user = session.selectOne("test.findUserById", id);            System.out.println(user);        } finally{            session.close();        }        return user;    }    @Override    Public void insertUser(User user) throws Exception {        SqlSession sqlSession = sqlSessionFactory.openSession();        try {            sqlSession.insert("insertUser", user);            sqlSession.commit();        } finally{            session.close();        }    }}
  • 测试
private SqlSessionFactory sqlSessionFactory;    @Before    public void init() throws Exception {        SqlSessionFactoryBuilder sessionFactoryBuilder = new SqlSessionFactoryBuilder();        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");        sqlSessionFactory = sessionFactoryBuilder.build(inputStream);    }    @Test    public void testGetUserById() {        UserDao userDao = new UserDaoImpl(sqlSessionFactory);        User user = userDao.getUserById(22);        System.out.println(user);    }}
  • 原始Dao开发中存在以下问题:
    • Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作方法
    • 调用sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不利于开发维护。

Mapper动态代理方式

  • Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
    Mapper接口开发需要遵循以下规范:
    • Mapper.xml(映射文件)文件中的namespace等于mapper接口的全路径名称
    • Mapper.xml中sql语句id要等于Mapper接口方法名称
    • mapper.xml中传入的parameterType的类型等于Mapper接口方法的输入参数类型
    • mapper.xml中定义的每个sql的resultType的类型等于Mapper接口方法的返回值类型。
  • 定义mapper映射文件UserMapper.xml(内容同Users.xml),需要修改namespace的值为 UserMapper接口路径。将UserMapper.xml放在classpath 下mapper目录 下。
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="cn.itcast.mybatis.mapper.UserMapper"><!-- 根据id获取用户信息 -->    <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">        select * from user where id = #{id}    </select><!-- 自定义条件查询用户列表 -->    <select id="findUserByUsername" parameterType="java.lang.String"             resultType="cn.itcast.mybatis.po.User">       select * from user where username like '%${value}%'     </select><!-- 添加用户 -->    <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">        select LAST_INSERT_ID()     </selectKey>      insert into user(username,birthday,sex,address)       values(#{username},#{birthday},#{sex},#{address})    </insert></mapper>
  • 测试
Public class UserMapperTest extends TestCase {    private SqlSessionFactory sqlSessionFactory;    protected void setUp() throws Exception {        //mybatis配置文件        String resource = "sqlMapConfig.xml";        InputStream inputStream = Resources.getResourceAsStream(resource);        //使用SqlSessionFactoryBuilder创建sessionFactory        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);    }    Public void testFindUserById() throws Exception {        //获取session        SqlSession session = sqlSessionFactory.openSession();        //获取mapper接口的代理对象        UserMapper userMapper = session.getMapper(UserMapper.class);        //调用代理对象方法        User user = userMapper.findUserById(1);        System.out.println(user);        //关闭session        session.close();    }    @Test    public void testFindUserByUsername() throws Exception {        SqlSession sqlSession = sqlSessionFactory.openSession();        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);        List<User> list = userMapper.findUserByUsername("张");        System.out.println(list.size());    }Public void testInsertUser() throws Exception {        //获取session        SqlSession session = sqlSessionFactory.openSession();        //获取mapper接口的代理对象        UserMapper userMapper = session.getMapper(UserMapper.class);        //要添加的数据        User user = new User();        user.setUsername("张三");        user.setBirthday(new Date());        user.setSex("1");        user.setAddress("北京市");        //通过mapper接口添加用户        userMapper.insertUser(user);        //提交        session.commit();        //关闭session        session.close();    }}

SqlMapConfig.xml配置文件

  • SqlMapConfig.xml中配置的内容和顺序如下:
    • properties(属性)
    • settings(全局配置参数)
    • typeAliases(类型别名)
    • typeHandlers(类型处理器)
    • objectFactory(对象工厂)
    • plugins(插件)
    • environments(环境集合属性对象)
    • environment(环境子属性对象)
    • transactionManager(事务管理)
    • dataSource(数据源)
    • mappers(映射器)

properties

  • SqlMapConfig.xml可以引用java属性文件中的配置信息如下:

在classpath下定义db.properties文件,

jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8jdbc.username=rootjdbc.password=root

SqlMapConfig.xml引用如下:

<properties resource="db.properties"/>    <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>    </environments>

注意: MyBatis 将按照下面的顺序来加载属性:

  • 在 properties 元素体内定义的属性首先被读取。
  • 然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。

typeAliases

  • mybatis支持别名:
别名  映射的类型_byte   byte _long   long _short  short _int    int _integer    int _double     double _float  float _boolean    boolean string  String byte    Byte long    Long short   Short int     Integer integer     Integer double  Double float   Float boolean     Boolean date    Date decimal     BigDecimal bigdecimal  BigDecimal map     Map
  • 自定义别名:
    在SqlMapConfig.xml中配置:
<typeAliases>    <!-- 单个别名定义 -->    <typeAlias alias="user" type="cn.itcast.mybatis.po.User"/>    <!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->    <package name="cn.itcast.mybatis.po"/>    <package name="其它包"/></typeAliases>

mappers(映射器)

  • Mapper配置的几种方法:
<mapper resource=" " />使用相对于类路径的资源如:<mapper resource="sqlmap/User.xml" />
<mapper class=" " />使用mapper接口类路径如:<mapper class="cn.itcast.mybatis.mapper.UserMapper"/>

注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

package name=""/>注册指定包下的所有mapper接口如:<package name="cn.itcast.mybatis.mapper"/>

注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

原创粉丝点击