Mybatis

Mybatis

1.搭建环境

<dependencies>
   
<!--mysql驱动-->
   
<dependency>
        <
groupId>mysql</groupId>
        <
artifactId>mysql-connector-java</artifactId>
        <
version>8.0.16</version>
    </
dependency>
   
<!--mybatis-->
   
<dependency>
        <
groupId>org.mybatis</groupId>
        <
artifactId>mybatis</artifactId>
        <
version>3.5.7</version>
    </
dependency>
   
<!--junit-->
   
<dependency>
        <
groupId>junit</groupId>
        <
artifactId>junit</artifactId>
        <
version>4.12</version>
    </
dependency>
</
dependencies>

2.创建模块

  1. 编写mybatis的核心配置文件
  2. &t;?xm version="1.0" encoding="UTF-8" ?> &t;!DOCTYPE configuration         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"         "http://mybatis.org/dtd/mybatis-3-config.dtd"> &t;!--configuration核心配置文件--> &t;configuration>     &t;environments defaut="deveopment">         &t;environment id="deveopment">             &t;transactionManager type="JDBC"/>             &t;dataSource type="POOLED">                 &t;property name="driver" vaue="com.mysq.jdbc.Driver"/>                 &t;property name="ur" vaue="jdbc:mysq://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=fase&amp;serverTimezone=Asia/Shanghai&amp;useSSL=fase&amp;alowPublicKeyRetrieval=true"/>                 &t;property name="username" vaue="root"/>                 &t;property name="password" vaue="123456"/>             &t;/dataSource>         &t;/environment>     &t;/environments> &t;/configuration>

  1. 编写mybatis工具类
  2. pubic class MybatisUtis {     private static SqSessionFactory sqSessionFactory ;     static {         try {             //使用mybatis第一步,必须的一部             //获取sqSessionFactory对象             String resource = "mybatis-config.xm";             InputStream inputStream = Resources.getResourceAsStream(resource);             sqSessionFactory = new SqSessionFactoryBuilder().buid(inputStream);         } catch (IOException e) {             e.printStackTrace();         }     } //    既然有了 SqSessionFactory,顾名思义,我们可以从中获得 SqSession 的实例。 // SqSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqSession 实例来直接执行已映射的 SQL 语句。     pubic static SqSession getSqSession(){         return sqSessionFactory.openSession();     } }

3.编写代码

  1. 实体类
  2. pubic class User {     private int id;     private String name;     private String pwd;     pubic User() {     }     pubic User(int id, String name, String pwd) {         this.id = id;         this.name = name;         this.pwd = pwd;     }     pubic int getId() {         return id;     }     pubic void setId(int id) {         this.id = id;     }     pubic String getName() {         return name;     }     pubic void setName(String name) {         this.name = name;     }     pubic String getPwd() {         return pwd;     }     pubic void setPwd(String pwd) {         this.pwd = pwd;     }     @Override     pubic String toString() {         return "User{" +                 "id=" + id +                 ", name='" + name + '\'' +                 ", pwd='" + pwd + '\'' +                 '}';     } }
  3. 接口
  4. pubic interface UserDao {     List&t;User> getUserList(); }
  5. 接口实现类
  6. &t;?xm version="1.0" encoding="UTF-8" ?> &t;!DOCTYPE mapper         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"         "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> &t;!--namespace=绑定一个对应的Dao/Mapper接口--> &t;mapper namespace="com.cheng.dao.UserDao">     &t;!--查询语句-->     &t;seect id="getUserList" resutType="com.cheng.pojo.User">        seect  * from  mybatis.user;     &t;/seect> &t;/mapper>

3.测试

public class UserDaoTest {

    @Test

    public void test(){



        //第一步:获取SqlSession对象

        SqlSession sqlSession = MybatisUtils.getSqlSession();



        //方式一:getMapper

        UserDao userDao = sqlSession.getMapper(UserDao.class);

        List<User> userList = userDao.getUserList();



        for (User user : userList) {

            System.out.println(user);

        }



        //关闭SqlSession

        sqlSession.close();

    }

}

maven文件导出失败的问题

<build>

    <resources>

        <resource>

            <directory>src/main/resources</directory>

            <includes>

                <include>**/*.properties</include>

                <include>**/*.xml</include>

            </includes>

            <filtering>false</filtering>

        </resource>

        <resource>

            <directory>src/main/java</directory>

            <includes>

                <include>**/*.properties</include>

                <include>**/*.xml</include>

            </includes>

            <filtering>false</filtering>

        </resource>

    </resources>

</build>

3.CRUD

1、namespace

Namespace中的包名要和Dao/Mapper接口的包名一致

2、select

选择,查询语句;

  1. Id:就是对应的namespace中的方法名
  2. resultType:sql语句的返回值
  3. parameterType:参数类型

增删改操作

  1. 接口

  2. //根据ID查询用户
    User getUserById(int id);

    //增加一个用户
    int addUser(User user);

    //修改用户
    int UpdateUser(User user);

    //删除一个用户
    int DeleteUser(int id);
  3. 实现类
  4. <!--增加一个用户-->
    <insert id="addUser" parameterType="com.cheng.pojo.User" >
       
    insert into mybatis.user(id, name, pwd) values (#{id},#{name},#{pwd})
    </
    insert>

    <!--修改用户-->
    <update id="UpdateUser" parameterType="com.cheng.pojo.User">
       
    update mybatis.user set name=#{name},pwd=#{pwdwhere id=#{id} ;
    </update>

    <!--删除一个用户-->
    <delete id="DeleteUser" parameterType="int">
       
    delete from mybatis.user where id=#{id};
    </delete>

3.测试

增删改测试需要提交事务

7、Map

假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应当考虑使用Map!

增加用户为例:

接口

//使用Map
int addUser2(Map<String,Object> map);

实现类

<!--增加一个用户2:对象中的属性,可以直接取出来
传递map的key
-->

<insert id="addUser2" parameterType="map" >
   
insert into mybatis.user(id, name, pwd) values (#{userid},#{username},#{userpwd})
</
insert>

测试

@Test
public void addUser2(){
   
SqlSession sqlSession = MybatisUtils.getSqlSession();
   
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

   
HashMap<String, Object> map = new HashMap<String, Object>();

   
map.put("userid",4);
   
map.put("username","haha");
   
map.put("userpwd","123123");

   
mapper.addUser2(map);
   
sqlSession.commit();

   
sqlSession.close();
}

Map传递参数,直接在sql中取出key即可

对象传递参数,直接在sql中取对象的属性即可

只有一个基本类型参数的情况下,可以直接在sql中取到

多个参数用Map,或者注解!

8、思考题

模糊查询写法

List<User> userList = mapper.getUserLike("%h%");

4、配置解析

1、核心配置文件

Mybatis-config.xml

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。

configuration(配置)

环境配置(environments)

MyBatis 可以配置成适应多种环境

不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

  • 默认使用的环境 ID(比如:default="development")。
  • 每个 environment 元素定义的环境 ID(比如:id="development")。
  • 事务管理器的配置(比如:type="JDBC")。
  • 数据源的配置(比如:type="POOLED")。

属性(properties)

我们可以通过propertise属性类实现引用配置文件

编写一个配置文件

Db.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
username=root
password=123456

在核心配置文件引入

<!--引入外部配置文件-->
<properties resource="db.properties">
    <
property name="username" value="root"/>
    <
property name="password" value="123456"/>
</
properties>

  1. 可以直接引入外部文件
  2. 可以在其中增加一些属性配置
  3. 如果两个文件有同一个字段,优先使用外部配置文件!

类型别名(typeAliases)

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写

给单个类起别名

<!--查询语句-->
<select id="getUserList" resultType="User" >
  
select  * from  mybatis.user;
</select>

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean

扫描实体类的包,它的默认别名为这个类名的首字母小写!

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

在实体类比较少的时候,建议使用第一种

如果实体类比较多的时候,建议使用第二种

第一种可以DIY,第二种则不行,如果非要进行diy,需要在实体类上加注解

//实体类
@Alias("hello")
public class User {

设置(settings)

cacheEnabled:     全局性地开启或关闭所有映射器配置文件中已配置的任何缓存

lazyLoadingEnabled: 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。

其他配置

映射器(mappers)

使用class文件绑定注册的注意点

  1. 接口和他的Mapper配置文件必须同名!
  2. 接口和他的Mapper配置文件必须在同一个包下

解决属性名和字段名不一致的问题

新建一个项目,拷贝之前的,测试实体类字段不一致的情况

解决方法:

  1. 起别名
  2. <select id="getUserById" parameterType="int" resultType="com.cheng.pojo.User">
       
    select id,name,pwd as password from mybatis.user where id=#{id}
    </
    select>
  3. resultMap

结果集映射

<!--结果集映射-->
<resultMap id="UserMap" type="User">
   
<!--column数据库中的字段,property实体类中的属性-->
   
<result column="id" property="id"/>
    <
result column="name" property="name"/>
    <
result column="pwd" property="password"/>
</
resultMap>

<!--根据ID查询用户-->
<select id="getUserById" parameterType="int" resultMap="UserMap">
   
select * from mybatis.user where id=#{id}
</
select>

resultMap 元素是 MyBatis 中最重要最强大的元素。

6、日志

6.1、日志工厂

如果一个数据库操作,出现了异常,我们需要排错,日志就是最好的助手!

曾经:sout、debug

现在:日志工厂!

logImpl       指定 MyBatis 所用日志的具体实现,未指定时将自动查找


SLF4J

LOG4J 【掌握】}

LOG4J2

JDK_LOGGING

COMMONS_LOGGING

STDOUT_LOGGING【掌握】}

NO_LOGGING

在Mybatis中具体使用哪个日志实现,在设置中设定

STDOUT_LOGGING标准日志输出

<!--日志配置-->
<settings>
    <
setting name="logImpl" value="STDOUT_LOGGING"/>
</
settings>

6.2、Log4j

1.先导入包

<!-- https://mvnrepository.com/artifact/log4j/log4j -->

<dependency>

    <groupId>log4j</groupId>

    <artifactId>log4j</artifactId>

    <version>1.2.17</version>

</dependency>

2.Log4g.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/cheng.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

3.配置log4j为日志的实现

<!--日志配置-->
<settings>
    <setting name="logImpl" value="LOG4J"/>
</
settings>

4.loh4j的使用,直接测试运行

简单使用

  1. 在要使用log4j的类中,导入包import org.apache.log4j.Logger;
  2. 日志对象,参数为当前类的class

static Logger logger = Logger.getLogger(UserDaoTest.class);

  1. 日志级别
  2. logger.info("info:进入了log4j");
    logger.debug("debug:进入了log4j");
    logger.error("error:进入了log4j");

7、分页

使用limit分页

select * from user limit 0,2;

使用mytatis实现分页

  1. 接口

//分页
List<User> getUserByLimit(Map<String,Integer> map);

  1. Mapper.xml

<!--分页-->
<select id="getUserByLimit" parameterType="map" resultMap="UserMap">
   
select * from mybatis.user limit #{startIndex},#{pageSize}
</
select>

  1. 测试

@Test
public void getUserByLimit(){
   
SqlSession sqlSession = MybatisUtils.getSqlSession();
   
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

   
HashMap<String, Integer> map = new HashMap<String, Integer>();
   
map.put("startIndex",0);
   
map.put("pageSize",2);


   
List<User> userList = mapper.getUserByLimit(map);

    for
(User user : userList) {
       
System.out.println(user);
   
}

}

7.1、RowBounds分页

不在使用sql实现分页

1.接口

//分页RowBounds
List<User> getUserByRowBounds();

2.mapper.xml

<!--分页2-->
<select id="getUserByRowBounds"  resultMap="UserMap">
   
select * from mybatis.user
</select>

3.测试

@Test
public void getUserByRowBounds(){
   
SqlSession sqlSession = MybatisUtils.getSqlSession();

   
//通过RowBounds实现
   
RowBounds rowBounds = new RowBounds(1, 2);

   
//通过java代码层面实现分页
   
List<User> userList = sqlSession.selectList("com.cheng.dao.UserMapper.getUserByRowBounds",null,rowBounds);

    for
(User user : userList) {
       
System.out.println(user);
   
}

   
sqlSession.close();
}

7.2、分页插件

8、使用注解开发

接口

@Select("select * from user")
List<User> getUsers();

测试

@Test
public void test(){
   
SqlSession sqlSession = MybatisUtils.getSqlSession();
   
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
   
List<User> users = mapper.getUsers();
    for
(User user : users) {
       
System.out.println(user);
   
}
   
sqlSession.close();
}

8.3、CRUD

我们可以在工具类创建的时候实现自动提交事务

接口

@Select("select * from user")
List<User> getUsers();

//方法存在多个参数,所有的参数前面必须加上@Param("id")注解
@Select("select * from user where id = #{id}")
User getUserById(@Param("id") int id);

@Insert("insert into user(id,name,pwd) value(#{id},#{name},#{password})")
int addUser(User user);

@Update("update user set name=#{name},pwd=#{password} where id=#{id} ")
int upDateUser(User user);

@Delete("delete from user where id=#{uid}")
int deleteUser(@Param("uid") int id);

【注意:我们必须将接口注册绑定到我们的核心配置文件中!】

关于@Param()注解

  1. 基本类型的参数或者String类型,需要加上
  2. 引用类型不需要加

9、Lombok(不建议使用)

使用步骤:

  1. 在IDEA中安装Lombok插件!
  2. 在项目中导入lombok的jar包

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->

<dependency>

    <groupId>org.projectlombok</groupId>

    <artifactId>lombok</artifactId>

    <version>1.18.10</version>

    <scope>provided</scope>

</dependency>

@Data:无参构造,get,set,tostring,hashcode,equals

@AllArgsConstructor

@NoArgsConstructor

10、多对一处理

按照查询嵌套处理

<!--
思路:
    1.查询所有的学生信息
    2.根据查询出来的学生的tid,寻找对应的老师
-->


<select id="getStudent" resultMap="StudentTeacher">
   
select * from student;
</select>
<
resultMap id="StudentTeacher" type="Student">
    <
result property="id" column="id"/>
    <
result property="name" column="name"/>
   
<!--复杂的属性,我们需要单独处理
        对象:association
        集合:collection
    -->
   
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>

</
resultMap>

<
select id="getTeacher" resultType="Teacher">
   
select * from mybatis.teacher where id=#{id};
</select>

按照结果嵌套处理

<!--按照结果嵌套处理-->
<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>
<
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"/>
    </
association>
</
resultMap>

11、一对多处理

实体类

老师

@Data
public class Teacher {
   
private int id;
    private
String name;

   
//一个老师拥有多个学生
   
private List<Student> students;
}

学生

@Data
public class Student {
   
private int id;
    private
String name;
    private int
tid;
}

按照结果嵌套处理

<!--按结果嵌套查询-->
<select id="getTeacher" resultMap="TeacherStudent">
   
select s.id sid,s.name sname,t.name tname,t.id tid
    from student s,teacher t
    where s.tid=t.id and t.id=
#{tid};
</select>
<
resultMap id="TeacherStudent" type="Teacher">
    <
result property="id" column="tid"/>
    <
result property="name" column="tname"/>
   
<!--
    javaType=""
指定数据类型
    集合中的泛型信息,使用ofType
    -->
   
<collection property="students" ofType="Student">
        <
result property="id" column="sid"/>
        <
result property="name" column="sname"/>
        <
result property="tid" column="tid"/>
    </
collection>
</
resultMap>

按照查询嵌套处理

<select id="getTeacher2" resultMap="TeacherStudent2">
   
select * from mybatis.teacher where id =#{tid};
</select>

<
resultMap id="TeacherStudent2" type="Teacher">
    <
collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/>
</
resultMap>

<
select id="getStudentByTeacherId" resultType="Student">
   
select * from mybatis.student where tid=#{tid}
</
select>

小结

  1. 关联:association,多对一
  2. 集合:collection,一对多
  3. javaType   &  ofType
  1. javaType用来指定实体类中属性的类型
  2. ofType用来指定映射到List或者集合中的pojo类型,泛型中的约束类型!

12、动态SQL

搭建环境

创建一个基础工程

  1. 导包
  2. 编写配置文件
  3. 编写实体类
  4. 编写实体类对应Mapper接口和Mapper.xml文件

If

<select id="queryBlogIF" parameterType="map" resultType="Blog">
    select * from mybatis.blog where 1=1
    <if test="title !=null">
        and title=#{title}
    </if>
    <if test="author!=null">
        and author=#{author}
    </if>
</select>

choose、when、otherwise

<select id="queryBlogChoose" parameterType="map" resultType="Blog">
   
select * from mybatis.blog
   
<where>
        <
choose>
            <
when test="title!=null">
               
title=#{title}
            </
when>
            <
when test="author!=null">
               
and author=#{author}
            </
when>
            <
otherwise>
               
and views=#{views}
            </
otherwise>
        </
choose>
    </
where>
</
select>

trim、where、set

select * from mybatis.blog
   
<where>
        <
if test="title !=null">
           
and title=#{title}
        </
if>
        <
if test="author!=null">
           
and author=#{author}
       
</if>
    </
where>

</
select>

set

<update id="updateBlog" parameterType="map">

    update mybatis.blog 

    <set>

        <if test="title!=null">

            title=#{title},

        </if>

        <if test="author!=null">

            author=#{author}

        </if>

    </set>

    where id=#{id}

</update>

所谓的动态sql,本质还是sql语句,只是我们可以在sql层面,去执行一个逻辑代码

Foreach

<select id="queryBlogForeach" parameterType="map" resultType="blog">
   
select  * from mybatis.blog
   
<where>
        <
foreach collection="ids" item="id" open="and (" close=")" separator="or">
           
id=#{id}
        </
foreach>
    </
where>
</
select>

Foreach测试

@Test
public void test4(){
   
SqlSession sqlSession = MybatisUtils.getSqlSession();
   
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

   
HashMap map = new HashMap();

   
ArrayList<Integer> ids = new ArrayList<Integer>();

   
ids.add(1);

   
map.put("ids",ids);
   
List<Blog> blogs = mapper.queryBlogForeach(map);
    for
(Blog blog : blogs) {
       
System.out.println(blog);
   
}

   
sqlSession.close();
}

 

Sql片段

有时候,我们可能会将一些功能的部分抽取出来,方便复用!

  1. 使用SQL标签抽取公共的部分
  2. 在需要使用的地方使用include标签引用计科
  3. <sql id="if-title-author">
        <
    if test="title !=null">
           
    and title=#{title}
        </
    if>
        <
    if test="author!=null">
           
    and author=#{author}
       
    </if>
    </
    sql>



    <
    select id="queryBlogIF" parameterType="map" resultType="Blog">
       
    select * from mybatis.blog
       
    <where>
            <
    include refid="if-title-author"/>
        </
    where>

    </
    select>

13、缓存

13.1、一级缓存

  1. 一级缓存也叫本地缓存:

与数据库同一次会话期间查询到的数据会放在本地缓存中

以后如果需要获取相同的数据,直接从缓存中拿,没必须在去查询数据库;

测试步骤:
1.开启日志!

2.测试在一个session中查询两次相同的纪录

3.查看日志输出

缓存失效的情况

  1. 查询不同的东西
  2. 增删改操作,可能会改变原来的数据,所以必定会刷新缓存
  3. 查询不同的Mapper.xml
  4. 手动清理缓存!

sqlSession.clearCache();//手动清理缓存

小结:一级缓存是默认开启的,只在一次sqlsession中有效,也就在拿到链接关闭链接这一个区间中

13.2、二级缓存

二级缓存也叫作全局缓存

步骤:
1.开启全局缓存

<!--显示的开启全局缓存-->
<setting name="cacheEnabled" value="true"/>

2.在要使用二级缓存的Mapper中开启

<cache eviction="FIFO"
       
flushInterval="60000"
       
size="512"
       
readOnly="true"
/>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值