MyBatis基础-增删改查

本文介绍了MyBatis作为轻量级持久层框架的优势,对比了与Hibernate的区别,并展示了如何在Java代码中构建复杂的SQL语句。通过详细步骤指导了MyBatis的配置,包括数据库连接、接口定义、SQL映射文件和Junit测试。同时,讨论了分页查询的两种实现方式:SQL的limit关键字和内存缓存。最后,简要说明了MyBatis的动态SQL功能。
摘要由CSDN通过智能技术生成

          很多互联网公司放弃使用Hibernate, 改用MyBatis; 理由是MyBatis比较轻巧, 可以做SQL语句优化。PS: 想想DBA的工作吧, 大数量级的数据库操作需要专业的DBA做SQL语句优化。 Hibernate封装比较完善,导致它不够灵活。  我们需要的是减化数据库操作的编码量,对JDBC进行必要的封装即可。

         Hibernate和Mybatis都提供了缓存功能, 但实际项目开发中更多的是使用中间件如Redis来做缓存;Mybatis最大的优势是在Java代码里生成复杂的SQL语句,Hibernate做不到。

         MyBatis官方说明: http://www.mybatis.org/mybatis-3/zh/statement-builders.html

        百度百科上的介绍:https://baike.baidu.com/item/MyBatis/2824918?fr=aladdin

项目结构:


在pom.xml中添加junit,mybatis和log4j的maven仓库:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.brycegao.mybatis</groupId>
    <artifactId>mybatis_demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>6.0.6</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

    </dependencies>
</project>
   log4j默认会读取名为log4j.properties的文件。
  

    MyBatis是对JDBC的封装,建议不要用MyBatis创建表。 我先电脑上启动MySQL服务, 并创建一个名为mybatis的数据库和一个user表。


jdbc.properties文件里填写jdbc的各个属性:

jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8&useSSL=true
jdbc.username=root
jdbc.password=111111

设置mybatis-config.xml的属性(主要是jdbc和mapper标签):

<?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>

    <!-- 引用其它配置文件 -->
    <properties resource="jdbc.properties"/>

    <!-- mybatis的各个配置项 -->
    <settings>
        <setting name="cacheEnabled" value="true"/>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="multipleResultSetsEnabled" value="true"/>
        <setting name="useColumnLabel" value="true"/>
        <setting name="useGeneratedKeys" value="false"/>
        <setting name="autoMappingBehavior" value="PARTIAL"/>
        <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
        <setting name="defaultExecutorType" value="SIMPLE"/>
        <setting name="defaultStatementTimeout" value="25"/>
        <setting name="defaultFetchSize" value="100"/>
        <setting name="safeRowBoundsEnabled" value="false"/>
        <setting name="mapUnderscoreToCamelCase" value="false"/>
        <setting name="localCacheScope" value="SESSION"/>
        <setting name="jdbcTypeForNull" value="OTHER"/>
        <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
    </settings>

    <!-- 别名可以用在数据类型参数里,其实没啥用, 直接用原数据类型更直观! -->
    <typeAliases>
        <typeAlias alias="User" type="com.brycegao.mybatis.entity.User"/>
    </typeAliases>

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

    <mappers>
        <!-- 跟Dao类对应的xml文件,编写SQL语句 -->
        <mapper resource="mappers/user_mapper.xml" />
    </mappers>

</configuration>

user-mapper.xml里编写SQL语句:

<?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">
<!-- 一个interface对应一个mapper.xml文件 -->
<mapper namespace="com.brycegao.mybatis.dao.UserDao">

    <!-- 查询语句 根据关键字查询记录, select id值必须跟UserDao方法名相同-->
    <select id="findUserById" parameterType="Integer" resultType="com.brycegao.mybatis.entity.User">
        select * from user where id=#{id}
    </select>

    <!-- 查询语句 注意:返回值类型是数组时,仍然使用item数据类型 -->
    <select id="findUsersAll" resultType="com.brycegao.mybatis.entity.User">
        select * from user
    </select>

    <!-- User是在mybatis-config.xml里声明的别名 -->
    <!-- useGeneratedKeys表示是否自动生成主键值, keyProperty是主键列名 -->
    <insert id="addUser" parameterType="User"
            useGeneratedKeys="true" keyProperty="id" >
        insert into `user`(name, age, address, job, idno, mobile)
        values(#{name},#{age},#{address},#{job},#{idno},#{mobile})
    </insert>


    <!-- 更新记录 User是别名-->
    <update id="updateUser" parameterType="User" flushCache="true">
        update user set name=#{name}, age=#{age}, address=#{address}, job=#{job}, idno=#{idno}, mobile=#{mobile} where id=#{id}
    </update>

    <!-- 根据主键删除一条记录 SQL不区分大小写。 注意java代码的deleteUser函数参数跟SQL语句的变量相同-->
    <delete id="deleteUser" parameterType="int">
        DELETE FROM  user WHERE id=#{id}
    </delete>
</mapper>

注意:

1、 select id要跟Java方法名相同, parameterType跟Java方法参数类型相同;

2、 namespace是Java中的接口类,Mybatis通过注解实现函数体;

3、 每个insert、update、select和delete标签对应一个sqlsession,可以单独配置超时、刷内存等等属性;


完整的junit测试类:注意在数据库操作完成后要释放SqlSession, 即调用其close方法,否则内存泄漏。 测试类在@Before里获取SqlSession实例, 在@Test里操作SqlSession实例, 在@After里释放SqlSession。

public class UserTest {
    private final static Logger LOG = LoggerFactory.getLogger(UserTest.class);

    private SqlSession session;

    @Before
    public void init() {
        session = SqlSessionFactoryUtil.getSqlSession();
    }

    @Test
    public void testQueryById() {
        UserDao userDao = session.getMapper(UserDao.class);
        User cur = userDao.findUserById(3);   //执行SQL语句:select * from user where id=3

        if (cur != null) {
            LOG.debug(cur.toString());
        }

        User curExt = userDao.findUserBydIdExt(3);
        if (curExt != null) {
            LOG.debug(curExt.toString());
        }
    }

    @Test
    public void testQueryAll() {
        UserDao userDao = session.getMapper(UserDao.class);
        List<User> list = userDao.findUsersAll();   //执行SQL语句:select * from user

        if (list != null) {
            System.out.println("记录总数:" + list.size());
        }

        List<User> all = userDao.getUsers();
        if (all != null) {
            System.out.println("记录总数:" + all.size());
        }
    }

    @Test
    public void testAddUser() {
        UserDao userDao = session.getMapper(UserDao.class);

        //第一种插入方法, 缺点是无返回值,不知道是否插入成功
        /*
        User user1 = new User();
        user1.setAge(31);
        user1.setName("张一");
        user1.setAddress("天津");
        userDao.addUser(user1);
        session.commit();   //必须执行该语句!
        */

        //第二种插入方法,推荐使用! 有返回值,能判断是否插表成功
        User user2 = new User();
        user2.setAge(32);
        user2.setName("张二");
        user2.setAddress("天津");
        //第一个参数是user_mapper.xml的namespace和id值拼起来
        int resultCount = session.insert("com.brycegao.mybatis.dao.UserDao.addUser", user2); //如果插入成功,user2对象的id字段非0
        System.out.printf("新插入记录id :%d ,插入记录数:%d ", user2.getId(), resultCount);  //获取插入对象的id
        session.commit();   //数据有变化时必须同步到数据库, 否则只是刷新了缓存!
    }

    @Test
    public void testUpdateUser() {
        UserDao userDao = session.getMapper(UserDao.class);

        //找到表中任意一条记录,然后修改它并回写数据库
        User cur = userDao.findUserById(3);   //执行SQL语句:select * from user where id=3

        System.out.println("testUpdateUser修改前:" + cur.getName());
        cur.setAge(77);

        //第一种方法
        userDao.updateUser(cur);
        session.commit();

        //第二种方法
        //int count = session.update("com.brycegao.mybatis.dao.UserDao.updateUser", cur);  //count表示更新的记录数
        //session.commit();
        //System.out.println("更新总数:" + count);

        User curExt = userDao.findUserById(3);   //执行SQL语句:select * from user where id=3
        System.out.println("testUpdateUser修改后:" + curExt.getName());
    }

    @Test
    public void testDeleteUser() {
        UserDao userDao = session.getMapper(UserDao.class);

        //使用sql gui工具查看user表中的记录,随便挑一条记录

        //第一种方法  无返回值!
        userDao.deleteUser(6);
        session.commit();

        //第二种方法 count是成功删除的记录数
        int count = session.delete("com.brycegao.mybatis.dao.UserDao.deleteUser", 6);
        session.commit();
    }


    @After
    public void deinit() {
        session.close();
    }
}


在测试前先添加若干条数据:


分页查询的实现方法:

1、 使用SQL的limit关键字实现,通过区间限制即可实现分页查询功能;优点是不费内存,缺点是每次都要从数据库查询。

取前10条记录: select * from user limit 10    

取0~5条记录: select * from user limit 0,5

取5~10条记录: select * from user limit 5,10


2、 将表的内容缓存到内存, 每次从内存中读取; 一般是缓存到中间件Redis里, 优点是查询快,缺点是浪费内存。


在@Test函数体里点击鼠标左键, 然后选中Debug调试就可以了:

  


简要说一下Mybatis的动态SQL,即在Java代码里生成SQL语句; 支持生成增删改查语句, 下面以查询为例:

   1、 创建一个java文件, 每个函数都可以返还一个SQL语句字符串。 注意看Mybatis的语法很清晰,这也是Mybatis的一大优势!!! Mybatis在xml文件里可以实现相同功能,即根据条件判断生成复杂的SQL语句。

public class UserSqlBuilder {

    //根据姓名查询记录
    public String buildGetUsersByName(final String name) {
        return new SQL() {{   //是2个大括号
            SELECT("*");
            FROM("user");
            if (name != null) {  //支持条件判断
                WHERE("name like #{name} || '%' ");    //#{...}跟@Param的值一致
            }
            ORDER_BY("id");
        }}.toString();
    }
}

2、在UserDao.java里添加声明,

    //使用UserSqlBuilder.java的buildGetUsersByName方法
    @SelectProvider(type= UserSqlBuilder.class, method="buildGetUsersByName")
    List<User> getUserByName(String name);
3、使用:

        UserDao userDao = session.getMapper(UserDao.class);
        List<User> list = userDao.getUserByName("张三");


demo代码:http://download.csdn.net/download/brycegao321/9956809

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值