mybatis之再学习

mybatis的介绍

  • mybatis 就是一个封装JDBC的持久层框架,它和hibernate都属于ORM框架,但是具体的来说bihernatea是一个完整的ORM框架,mybatis 是不完整的ORM框架
  • Mybatis 让程序员只关注sql本身,而不需要关注如何连接、statement的创建等操作
  • Mybatis 输入参数和输出结果进行映射.

mybatis文档

分析jdbc的问题

原生态的jdbc代码

public static void main(String[] args) {
            Connection connection = null;
            PreparedStatement preparedStatement = null;
            ResultSet resultSet = null;
            
            try {
                //1、加载数据库驱动
                Class.forName("com.mysql.jdbc.Driver");
                //2、通过驱动管理类获取数据库链接
                connection =  DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root");
                //3、定义sql语句 ?表示占位符
            String sql = "select * from user where username = ?";
                //4、获取预处理statement
                preparedStatement = connection.prepareStatement(sql);
                //5、设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
                preparedStatement.setString(1, "王五");
                //6、向数据库发出sql执行查询,查询出结果集
                resultSet =  preparedStatement.executeQuery();
                //7、遍历查询结果集
                while(resultSet.next()){
                    User user 
                    System.out.println(resultSet.getString("id")+"  "+resultSet.getString("username"));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                //8、释放资源
                if(resultSet!=null){
                    try {
                        resultSet.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(preparedStatement!=null){
                    try {
                        preparedStatement.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(connection!=null){
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }

            }

        }


问题总结

  • 1、 在创建连接时,存在硬编码配置文件(全局配置文件)

  • 2、 在执行statement时存在硬编码
    配置文件(映射文件

  • 3、 频繁的开启和关闭数据库连接,会造成数据库性能下降。
    数据库连接池(全局配置文件)

工作原理

image.png

pom.xml 文件

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>

MyBatis配置文件

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

    <settings>
        <!--
            开启数据库列名下划线风格转换为驼峰命名法
            例如 user_name -> userName
                last_access_time -> lastAccessTime
        -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <!--配置别名-->
    <typeAliases>
        <typeAlias type="com.kaishengit.pojo.User" alias="User"/>
        <typeAlias type="com.kaishengit.pojo.Employee" alias="Employee"/>
        <typeAlias type="com.kaishengit.pojo.Dept" alias="Dept"/>
    </typeAliases>



    <!--配置数据库环境-->
    <environments default="dev">

        <environment id="dev">
            <!--配置事务管理器-->
            <transactionManager type="JDBC"/>
            <!--配置数据库连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///db_22"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>

    </environments>


    <!--加载Mapper.xml文件-->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
        <mapper resource="mapper/EmployeeMapper.xml"/>
        <mapper resource="mapper/DeptMapper.xml"/>

        <mapper class="com.kaishengit.mapper.AccountMapper"/>
    </mappers>

</configuration>

Mapper文件

<?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.kaishengit.mapper.UserMapper">

    <cache/>
    <!--
        将select节点的useCache属性设置为false表示该查询结果不会放入到缓存中
    -->
    <select id="findById" useCache="false" parameterType="int" resultType="User">
        SELECT * FROM t_user WHERE id = #{id}
    </select>
    
    <select id="findAll" resultType="User">
        SELECT * FROM t_user
    </select>

    <select id="findByUserNameAndPassword" resultType="com.kaishengit.pojo.User">
      SELECT * FROM t_user where user_name=#{name} and password=#{pwd}
    </select>

  
</mapper>
  • • namespace:命名空间,可以和同样完全限定名中的一个Mapper类对应;
  • • id:该查询语句的唯一标示
  • • parameterType:参数的类型
  • • resultType:返回值类型,如果是自己定义的Entity,需要在config文件中配置别名

测试



public class MyBatisTestCase {

    @Test
    public void readXml() {

        try {
            //1. 读取classpath中的配置文件
            Reader reader = Resources.getResourceAsReader("mybatis.xml");
            //2. 构建SqlSessionFactory对象
            SqlSessionFactory sessionFactory =
                    new SqlSessionFactoryBuilder().build(reader);
            //3. 创建SqlSession对象
            SqlSession sqlSession = sessionFactory.openSession();

            //执行查询单个对象语句
            User user = sqlSession.selectOne("com.kaishengit.mapper.UserMapper.findById",1);
            System.out.println(user);



            //4. 释放资源
            sqlSession.close();


        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void findById() {
        SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSession();

        User user = sqlSession.selectOne("com.kaishengit.mapper.UserMapper.findById",1);
        System.out.println(user);

        sqlSession.close();
    }

    @Test
    public void save() {
        SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSession();

        User user = new User();
        user.setUserName("mybatis");
        user.setPassword("109876");

        sqlSession.insert("com.kaishengit.mapper.UserMapper.save",user);

        //提交事务
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void update() {
        SqlSession session = SqlSessionFactoryUtil.getSqlSession(true);

        User user = session.selectOne("com.kaishengit.mapper.UserMapper.findById",58);
        user.setUserName("Spring");

        session.update("com.kaishengit.mapper.UserMapper.update",user);

        session.close();
    }

    @Test
    public void del() {
        SqlSession session = SqlSessionFactoryUtil.getSqlSession(true);
        session.delete("com.kaishengit.mapper.UserMapper.del",58);
        session.close();
    }

    @Test
    public void findAll() {
        SqlSession session = SqlSessionFactoryUtil.getSqlSession();

        List<User> userList = session.selectList("com.kaishengit.mapper.UserMapper.findAll");
        for(User user : userList) {
            System.out.println(user);
        }

        session.close();
    }



}

事务

Mybatis默认在操作insert、update、delete时不会自动提交事务,需要通过SqlSession对象的commit()方法来提交事务,通过rollback()方法回滚事务
调用SqlSessionFactory对象的openSession(true)方法可以获取一个可以自动提交事务的SqlSession对象
image.png

使用Mapper接口

package com.wanggs.mapper;
public interface UserMapper {
User findById(Integer id);
void save(User user);
void update(User user);
void del(Integer id);
List<User> findAll();
}

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findById(10);
logger.debug("{}",user);
sqlSession.close();
image.png
image.png

多对一结果集映射

image.png
image.png

ONGL

image.png

image.png

一对多

image.png
image.png
<?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.kaishengit.mapper.DeptMapper">
    

    <select id="findById" resultMap="deptMap">
        SELECT
            t_employee.id,empname,deptid,deptname
        FROM
            t_employee
        INNER JOIN t_dept ON t_employee.deptid = t_dept.id
        WHERE
            t_dept.id = #{id}
    </select>

    <resultMap id="deptMap" type="Dept">
        <id column="deptid" property="id"/>
        <result column="deptname" property="deptname"/>
        <collection property="employeeList" ofType="Employee">
            <id column="id" property="id"/>
            <result column="empname" property="empname"/>
            <result column="deptid" property="deptid"/>
        </collection>
    </resultMap>
</mapper>

传入多个参数

image.png
image.png

测试



public class MyBaitsInterfaceTestCase {

    private SqlSession sqlSession;
    private UserMapper userMapper;

    @Before
    public void setup() {
        sqlSession = SqlSessionFactoryUtil.getSqlSession();
        userMapper = sqlSession.getMapper(UserMapper.class);
    }

    @After
    public void close() {
        sqlSession.close();
    }

    @Test
    public void save() {
        SqlSession session = SqlSessionFactoryUtil.getSqlSession(true);
        User user = new User();
        user.setUserName("Rose");
        user.setPassword("123123");

        UserMapper userMapper = session.getMapper(UserMapper.class);
        userMapper.save(user);

        System.out.println(user.getId());

        session.commit();
        session.close();
    }


    @Test
    public void findByParam() {
        Map<String,Object> param = new HashMap<String,Object>();
        //param.put("username","tom");
        param.put("password","111");

        User user = userMapper.findByParam(param);
        System.out.println(user);
    }


    @Test
    public void batchSave() {
        List<User> userList = new ArrayList<User>();
        userList.add(new User("王五","99887"));
        userList.add(new User("咋喽","3344876"));
        userList.add(new User("呵呵","998876"));

        userMapper.batchSave(userList);
        sqlSession.commit();
    }


}


mapper
package com.kaishengit.mapper;

import com.kaishengit.pojo.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface UserMapper {
    
    void save(User user);
    User findByParam(Map<String,Object> param);
    List<User> findByIds(List<Integer> idList);
    void batchSave(List<User> userList);

}

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">
<mapper namespace="com.kaishengit.mapper.UserMapper">

    <cache/>
    <!--
        将select节点的useCache属性设置为false表示该查询结果不会放入到缓存中
    -->
    <select id="findById" useCache="false" parameterType="int" resultType="User">
        SELECT * FROM t_user WHERE id = #{id}
    </select>
    
    <select id="findByParam" resultType="com.kaishengit.pojo.User">
          SELECT * FROM t_user
          <trim prefix="where" prefixOverrides="and|or">
              <if test="username != null and username != ''">
                  user_name = #{username}
              </if>
              <if test="password != null and password != ''">
                  and password= #{password}
              </if>
          </trim>
    </select>
    <select id="findByIds" resultType="com.kaishengit.pojo.User">
        SELECT * FROM t_user where id in
        <foreach collection="list" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </select>

    <!--
        useGeneratedKeys:true 表示使用自动增长的主键
        keyProperty:id 将自动增长的主键赋值给parameterType对应类型的id属性
        flushCache:false 不刷新缓存
    -->
    <insert id="save" parameterType="User"
            useGeneratedKeys="true" keyProperty="id"
            flushCache="false">
        INSERT INTO t_user(user_name,password) VALUES (#{userName},#{password})
    </insert>
    <insert id="batchSave">
        INSERT INTO t_user(user_name,password)
        VALUES
        <foreach collection="list" item="user" separator=",">
            (#{user.userName},#{user.password})
        </foreach>
    </insert>


</mapper>

N+1问题

image.png
image.png

缓存


<mapper namespace="com.kaishengit.mapper.NodeMapper">
<cache/> 
作用
• 映射语句文件中所有的select语句将被缓存
• 映射语句文件中的所有insert、update、delete语句会刷新缓存
• 缓存会使用least recentily used(LRU,最近很少使用的)算法来收回
• 根据时间间隔来刷新缓存,默认不刷新
• 缓存会存储列表集合或对象的1024个引用
• 缓存被视为read/write的缓存

注:pojo类必须是可序列化类

更改默认配置

<cache size="2048" readOnly="false" eviction="FIFO" flushInterval="60000"/>
• 存储2048个对象
• 不是只读缓存
• 缓存策略为FIFO
• 每隔60秒刷新一次缓存
• eviction回收策略
• LRU:最近最少使用的,移除长时间不被使用的对象(默认)
• FIFO:先进先出:按对象进入缓存的顺序来移除他们
• SOFT:软引用:移除基于垃圾回收器状态和软引用规则的对象
• WEAK:弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
• flushInterval(刷新间隔):可以被设置为任意的正整数
• size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认
值是 1024。
• readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此
这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会
慢一些,但是安全,因此默认是false。

一级缓存

image.png

测试一级缓存

image.png

二级缓存

image.png
image.png
image.png
image.png
image.png
image.png
image.png

image.png

逆向生成

1

image.png

2

image.png

generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>

    <!-- Maven运行命令:mybatis-generator:generate -->
    <!-- 连接数据库jar包的位置 -->
    <classPathEntry location="D:\jar\mysql-connector-java-5.1.41.jar"/>

    <!-- 
        id: 自定义
        targetRuntime : MyBatis3Simple 生成简单的CRUD语句
                        MyBatis3 生成带Example的CRUD语句
     -->
    <context id="myConfig" targetRuntime="MyBatis3">

        <!--去掉自动产生的注释-->
        <commentGenerator>
            <!-- 是否去掉自动生成的注释 true是 false 否 -->
            <property name="suppressAllComments" value="true"/>
        <!-- 生成的注释是否带日期 true 不带 false 带 -->
            <property name="suppressDate" value="true"/>
        </commentGenerator>
        <!-- 连接数据库的信息 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql:///ssm_crm?useSSL=false"
                        userId="root" password="rootroot"/>

        <!-- POJO -->
        <javaModelGenerator targetPackage="com.kaishengit.pojo" targetProject="src/main/java"/>
         <!--XML映射文件-->
        <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"/>
         <!--Mapper接口-->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.kaishengit.mapper"
                             targetProject="src/main/java"/>


        <table tableName="t_user" domainObjectName="User" enableSelectByExample="true"/>
    </context>


</generatorConfiguration>

运行插件

    <build>
        <!-- 插件的配置 -->
        <plugins>
            <!-- MBG插件 -->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.5</version>
            </plugin>
        </plugins>
    </build>

image.png
image.png

使用

image.png
image.png

使用其他方式

image.png

gui链接

image.png
image.png

分页插件

image.png

使用

1. 添加maven

2. 添加拦截器

image.png

测试

image.png
image.png
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容