MyBatis

MyBatis,第1张

文章目录
    • 简介
    • 第一个MyBatis
      • 搭建环境
      • CRUD
    • mybatis-config.xml标签
      • environment
      • properties
      • typeAliases
      • mappers注册
      • 生命周期和作用域
    • 属性≠字段
    • log
      • STDOUT_LOGGING
      • LOG4J
    • 分页
      • limit
      • RowBounds
    • 使用注解开发
    • Lombok
    • 多对一association
      • 法一:查询嵌套
      • 法二:结果嵌套(直接sql,推荐)
    • 一对多collection
    • 动态SQL
      • if
      • where
      • choose
      • set
      • sql标签
      • foreach
    • 缓存
      • 一级缓存
      • 二级缓存
      • 缓存原理
      • 自定义缓存ehcatch

简介

MyBatis(原名iBatis)是持久层框架。主要是与数据库打交道

  • -避免JDBC和返回集合代码。利用xml文件 *** 作。

maven仓库

<dependency>
    <groupId>org.mybatisgroupId>
    <artifactId>mybatisartifactId>
    <version>3.5.9version>
dependency>
  • dao数据持久化:data access object就是将数据库中的数据,转化为持久状态
第一个MyBatis 搭建环境
  • maven导包mysql-connector-java,mybatis
  • 主配置文件,并注册mappers
  • 实体类、其接口和响应的映射.xml(实现sql *** 作)
  • 编写utils,MyTest
CRUD
  • maven导
  • pojo
public class User {
    private int id;
    private String name;
    private String pwd;

    public User() {
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
}
  • 方法和映射配置文件
public interface UserMapper {
    public List<User> selectUser();	//所有用户

    public User getUserById(int id);

    public int addUser(User user);

    public int upDateUser(User user);
    
    public int deleteUser(int id);
    
    int addUser2(Map<String,Object> map);

    List<User> getUserLike(String value);
}
================UserMapper.xml===========================

DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0/EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.adair.dao.UserDao">		//链接UserDao
    <select id="selectUser" resultType="com.adair.pojo.User">//	其中的方法,和返回值
        select * from mybatis.user
    select>
    
    <select id="getUserById" parameterType="int" resultType="com.adair.pojo.User">
        select * from mybatis.user where id= #{id}
    select>
    
    <insert id="addUser" parameterType="com.adair.pojo.User">
        insert into mybatis.user (id,name,pwd) value (#{id},#{name},#{pwd});
    insert>
    
    <update id="upDateUser" parameterType="com.adair.pojo.User">
        update mybatis.user
        set  name=#{name},pwd=#{pwd}
        where id=#{id};
    update>
    
    <delete id="deleteUser" parameterType="int">
        delete from mybatis.user where id=#{id}
    delete>
    
    <insert id="addUser2" parameterType="map">
        insert into mybatis.user (id,pwd) values (#{userid},#{passWord})
    insert>
    
    <select id="getUserLike" parameterType="String" resultType="com.adair.pojo.User">
        select * from mybatis.user where name like #{value}
    select>
mapper>
  • 主配置文件mybatis-config.xml

DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0/EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <typeAliases>
        <package name="com.adair.pojo"/>
    typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"/>
                <property name="username" value="root"/>
                <property name="password" value="123"/>
            dataSource>
        environment>
    environments>

    <mappers>
        <mapper resource="com/adair/dao/UserMapper.xml"/>
    mappers>

configuration>
  • MyTest
public class MyTest {
    public static void main(String[] args) throws IOException {
        String resources = "mybatis-config.xml";            //可以设置为常用类。utils包
        InputStream is = Resources.getResourceAsStream(resources);
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = sessionFactory.openSession(true);

        //方式一:getMapper得到类
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        List<User> userList = mapper.selectUser();//所有用户
        User user = mapper.getUserById(1);//id为1
        mapper.addUser(new User(5, "zhaoliu", "444"));//增加一个用户
        mapper.upDateUser(new User(5,"laowu","555"));   //更新用户
        mapper.deleteUser(5);

        //若数据库没有更变sqlSession.commit();

        System.out.println(user.toString());
        //方式二:直接得到方法,并利用方法
//        List userList = sqlSession.selectList("com.adair.dao.UserDao.selectUser");

        HashMap<String, Object> map = new HashMap<>();//new hashmap然后put键值对
        map.put("userid",4);		
        map.put("passWord","444");
        mapper.addUser2(map);
        
        List<User> userList = mapper.getUserLike("%李%");
        for (User user : userList) {
            System.out.println(user.toString());
        }
    }
}
  • utils下的工具类
public class MybatisUtils {//直接优化成工具类
    private static SqlSessionFactory sqlsessionFactory;
    static {
        try {
            String resources = "mybatis-config.xml";
            InputStream is = Resources.getResourceAsStream(resources);
            sqlsessionFactory = new SqlSessionFactoryBuilder().build(is);
        } catch (IOException e){
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession(){
        return sqlsessionFactory.openSession();
    }
}

传参总结:

  • 一个基本类型:直接可以用。标签内无parameterType也可以
  • 对象:直接利用属性即可
  • map:多个属性,可以利用parameterType=“map”。键值对
mybatis-config.xml标签 environment
  • transactionManager
  • dataSource
properties
==============db.properties================
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai

==============mybatis-config.xml================
<configuration>
    
    <properties resource="db.properties">
        <property name="username" value="root"/>
        <property name="pwd" value="123"/>
    properties>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${pwd}"/>
            dataSource>
        environment>
    environments>

    <mappers>
        <mapper resource="com/adair/dao/UserMapper.xml"/>
    mappers>

configuration>
typeAliases

自定义。扫描包。注解(在类上)

<typeAliases>
    <typeAlias type="com.adair.pojo.User" alias="User"/>    
    <package name="com.adair.pojo"/>      
typeAliases>

@Alias("hello")
public class User {
    private int id;
    private String name;
    private String pwd;
}
======================UserMapper.xml========================
<select id="selectUser" resultType="user">
     select * from mybatis.user
select>
mappers注册

法一:通过资源引用。

<mappers>
    <mapper resource="com/adair/dao/UserMapper.xml"/>
mappers>

法二:(同一包下。类名同.xml名字一样)

<mappers>
    <mapper class="com.adair.dao.UserMapper"/>
mappers>

法三:(要求同二)

<mappers>
    <package name="com.adair.dao"/>
mappers>
生命周期和作用域

sqlSessionFactoryBuilder:

  • 局部变量,创建sqlSessionFactory就可以挂了。

sqlSessionFactory:

  • 应用作用域,运行期间一直存在。相当于一个连接池

sqlSession:

  • 方法作用域(用完就关)。连接到连接池的一个请求。sqlSession的实例是不安全的,不可被共享。

tip:代码正确(还报错),删除target下的。

属性≠字段

java类的属性中会出现和数据库字段名字不同的情况(password≠pwd)。

解决方案:

  • 别名。在select时,给数据库字段起一个别名(同java属性)
<select id="getUserById" parameterType="int" resultType="com.adair.pojo.User">
    select id,name,pwd as password from mybatis.user where id= #{id}
select>
  • resultMap
<resultMap id="UserMap" type="User">
    <result column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="pwd" property="password"/>
resultMap>


<select id="getUserById" resultMap="UserMap">
    select * from mybatis.user where id= #{id}
select>
log STDOUT_LOGGING
  • mybatis-config.xml
<settings>		//在MyTest会自动运行,并显示
    <setting name="logImpl" value="STDOUT_LOGGING"/>
settings>
  • 控制台

LOG4J
  • mybatis-config.xml
<settings>		//在MyTest会自动运行,并显示
    <setting name="logImpl" value="LOG4J"/>
settings>
  • log4j.properties
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/adair.log	//生成的文件地址
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
  • MyTest
static Logger logger = Logger.getLogger(MyTest.class);
@Test
public void test(){
    logger.info("info:进入logger");
    logger.debug("debug:进入logger");
    logger.error("error:进入logger");
}
  • 在项目下,自动生成log/adair.log文件
分页 limit
  • 在sql
select * from user limit 0,2
  • 接口和映射配置文件
public interface UserMapper {
    List<User> getUserByLimit(Map<String,Object> map);
}

=======================================================
<select id="getUserByLimit" parameterType="map" resultType="user">
	select * from user limit #{startIndex},#{pageSize}
</select>
=======================================================
    public static void main(String[] args) throws IOException {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Map<String, Object> map = new HashMap<>();
        map.put("startIndex",1);
        map.put("pageSize",2);

        List<User> userList = mapper.getUserByLimit(map);
        for (User user : userList) {
            System.out.println(user);
        }
    }
RowBounds
  • 借用getUser方法(之前的)得到所有用户
RowBounds rowBounds = new RowBounds(1, 2);
List list = sqlSession.selectList("com.adair.dao.UserMapper.getUser", null, rowBounds);
for (User user : list) {
    System.out.println(user);
}
使用注解开发
  • UserMapper接口的方法
@Select("select * from mybatis.user where id=#{id}")
public User getUserById(int id);
  • 主配置文件用mappers注册就好了
<mappers>
    <mapper class="com.adair.dao.UserMapper"/>
mappers>
  • MyTest。同上

本质:反射机制。底层:动态代理

  • Debug查看本质
  • Mybatis执行流程

  • 利用注解select,param

@Select("select * from mybatis.user where id=#{id1}")
public User getUserById(@Param("id1") int id);                  
  • 没有提交到数据库的情况
sqlsessionFactory.openSession();		//设置为true
//或者,手动提交
sqlSession.commit();		
  • #{}和${}的区别是什么

    a、#{}是预编译处理,${}是字符串替换。

    b、Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的 set 方法来赋值;
    c、Mybatis 在处理${}时,就是把${}替换成变量的值。
    d、使用#{}可以有效的防止 SQL 注入,提高系统安全性

Lombok

偷懒神器

步骤:

  • 在idea安装plugin
  • 导入maven依赖
  • 在类上加注解即可
@Data
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@EqualsAndHashCode
public class User {
    private int id;
    private String name;
    private String pwd;
}
多对一association 法一:查询嵌套
  • 导入数据库student ,teacher
  • pojo类。用lombok的话,安装插件和库
@Data
public class Student {
    private int id;
    private String name;
    private Teacher teacher;
}
  • dao
public interface StudentMapper {
    public List<Student> getStudent();
}
  • mybatis-config.xml

DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0/EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
	//其他的

    <mappers>		//导入资源
        <mapper class="com.adair.dao.StudentMapper"/>
        <mapper class="com.adair.dao.TeacherMapper"/>	
    mappers>
configuration>
  • resources下的com.adair.dao。联表查询

DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0/EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.adair.dao.StudentMapper">
    <select id="getTeacher" resultType="teacher">
        select * from teacher
    select>

    <resultMap id="StudentTeacher" type="student">
        <association property="teacher" column="id" javaType="Teacher" select="getTeacher"/>
    resultMap>


    <select id="getStudent" resultMap="StudentTeacher">
        select * from student
    select>
mapper>
  • 测试查询
法二:结果嵌套(直接sql,推荐)
  • pojo
public interface StudentMapper {
    public List<Student> getStudent();
    public List<Student> getStudent2();
}
  • StudentMapper.xml。assciation用的javaType
<mapper namespace="com.adair.dao.StudentMapper">

    <resultMap id="StudentTeacher2" type="student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <association property="teacher" javaType="Teacher">
            <result property="name" column="tname"/>
            <result property="id" column="tid"/>
        association>
    resultMap>
    
    <select id="getStudent2" resultMap="StudentTeacher2">
        select s.id sid,s.name sname,t.name tname 
        from student s,teacher t 
        where s.tid=t.id
    select>
mapper>
一对多collection
  • List getTeacher();方法。 colletion中的ofType
<resultMap id="TeacherStudent" type="teacher">
    <result property="id" column="tid"/>
    <result property="name" column="tname"/>
    <collection property="students" ofType="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
    collection>
resultMap>

<select id="getTeacher" resultMap="TeacherStudent">
    select t.name tname,t.id tid,s.name sname,s.id sid 
    from student s,teacher t 
    where s.tid=t.id
select>
  • List getTeacher2();方法。按查询嵌套
<select id="getTeacher2" resultMap="TeacherStudent2">
    select * from teacher
select>

<resultMap id="TeacherStudent2" type="Teacher">
    <collection property="students"  javaType="ArrayList" ofType="Student" select="getStudent" column="id"/>	//column也可为name
resultMap>


<select id="getStudent" resultType="student">
    select * from student
select>
动态SQL

动态SQL就是根据不同的情况,生成不同的SQL语句

实验

  • utils包
public class IDUtils {
    public static String getId(){
        return UUID.randomUUID().toString().replace("-","");
    }
}
  • 配置文件

DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0/EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <properties resource="db.properties"/>
    
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    settings>

    <typeAliases>
        <package name="com.adair.pojo"/>
    typeAliases>

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


    <mappers>
        <mapper class="com.adair.dao.BlogMapper"/>
    mappers>
configuration>
  • 实体类,接口方法,其映射的.xml
===============pojo=================
public class Blog {
    private String id;
    private String title;
    private String author;
    private Date createTime;
    private int views;
}
=============dao层BlogMapper===================
public interface BlogMapper {
    int addBlog(Blog blog);
    List<Blog> queryBlogIf(Map<Object, Object> map);
}

if
==============BlogMapper.xml==================




    

where
  • 上面的if在一定条件下会报错(and多余错误) 。where标签可以避免
<select id="queryBlogIf" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <if test="title != null">
            title = #{title}
        if>
        <if test="author != null">
           and author = #{author}
        if>
    where>    
      
select>
choose
  • choose(when,otherwise)。相当于switch
<select id="queryBlogIf" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <choose>
            <when test="title != null">
                title = #{title}
            when>
            <when test="author != null">
                author = #{author}
            when>
            <otherwise>
                views = #{views}
            otherwise>
        choose>
    where>
select>
set
  • set标签,会动态的去掉逗号
    <update id="updateBlog" parameterType="map">
        update blog
        <set>
            <if test="title != null">
                title = #{title},
            if>
            <if test="author != null">
                author = #{author}
            if>
        set>
        <where>
            id = #{id}
        where>
    update>
sql标签
  • 使用公共部分的sql语句
<sql id="if-title-author">
    <if test="title != null">
        title = #{title}
    if>
    <if test="author != null">
        and author = #{author}
    if>
sql>

<select id="queryBlogIf" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <include refid="if-title-author">include>
    where>
select>
  • 注意:片段基于单表。片段不包括where标签
foreach
<select id="queryBlogForeach" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <foreach collection="ids" item="id" open="(" close=")" separator=" or ">
            id=#{id}
        foreach>
    where>
select>
public void test1() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    HashMap<Object, Object> map = new HashMap<>();
    ArrayList<Integer> ids = new ArrayList<>();
    ids.add(1);
    ids.add(2);
    map.put("ids",ids);
    for (Blog blog : mapper.queryBlogForeach(map)) {
        System.out.println(blog);
    }
}
缓存

读写分离,主从复制

一级缓存

也叫本地缓存

public class MyTest {
    public static void main(String[] args) {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user1 = mapper.getUserById(2);
        System.out.println(user1);
        User user2 = mapper.getUserById(2);
        System.out.println(user2);
        System.out.println(user1 == user2);
        sqlSession.close();
    }
}
  • 结果
  • 在其中增加一个update,更新语句,则会更新缓存。地址不同则会false
  • 在两个查询语句中间加入sqlSession.clearCache();

小结:一级缓存默认开启,只在一次qlSession中有效。

二级缓存

也叫全局缓存。由于一级缓存太低,所有诞生了二级缓存。

  • 主配置文件
<setting name="cacheEnabled" value="true"/>
  • 类配置文件。注意:类要实现序列化
<cache readOnly="true"/>	//true为同一个实体类。为fals则是一个拷贝的
<select id="getUserById" resultType="user" useCache="true">
    select * from user where id=#{id}
select>
  • MyTest
public class MyTest {
    public static void main(String[] args) {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        SqlSession sqlSession2 = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        User user1 = mapper.getUserById(1);
        System.out.println(user1);
        sqlSession.close();

        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        User user2 = mapper2.getUserById(1);
        System.out.println(user2);

        System.out.println(user1 == user2);

        sqlSession2.close();
    }
}
  • 结果
缓存原理
  • 查看顺序:用户 → 二级缓存 → 一级缓存 → 数据库
  • 提示: 一级缓存提交或关闭之后,才会提交到二级缓存中。不关闭则不提交
自定义缓存ehcatch
  • 接口映射的配置文件

  • ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">

    <diskStore path="./tmpdir/Tmp_EhCache"/>

    <defaultCache
            eternal="false"
            maxElementsInMemory="10000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="259200"
            memoryStoreEvictionPolicy="LRU"/>

    <cache
            name="cloud_user"
            eternal="false"
            maxElementsInMemory="5000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="1800"
            memoryStoreEvictionPolicy="LRU"/>
ehcache>

面试高频:

  • MySql引擎

  • InnoDB底层原理

  • 索引

  • 索引优化

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/874497.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存