mybatis

结构图:
在这里插入图片描述

思路流程:搭建环境–>导入Mybatis—>编写代码—>测试

01、一个完整的mybatis构建

1、搭建实验数据库

CREATE DATABASE `mybatis`;

USE `mybatis`;

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
`id` int(20) NOT NULL,
`name` varchar(30) DEFAULT NULL,
`pwd` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert  into `user`(`id`,`name`,`pwd`) values (1,'jom','123456'),(2,'张三','abcdef'),(3,'李四','987654');

2、在pom.xml文件中导入相关 jar 包

1.导入MyBatis相关 jar 包
<dependency>
   <groupId>org.mybatis</groupId>
   <artifactId>mybatis</artifactId>
   <version>3.5.2</version>
</dependency>
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.47</version>
</dependency>


2.设置实体类的别名:
<!-- 此时,User可以代替jom.who.pojo.User -->
<typeAliases>
   <typeAlias type="jom.who.pojo.User" alias="User"/>
</typeAliases>

 也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean:
<typeAliases>
   <package name="jom.who.pojo"/>
</typeAliases>
此时,该Java类名的首字母改为小写后作为它的别名。例如 jom.who.pojo.User 的别名为:user

3、编写mybatis-config.xml核心配置文件:

1.设置日志记录:

<!-- 标准日志实现方式 -->
<settings>
       <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

<!-- log4j日志实现方式 -->
<settings>
   <setting name="logImpl" value="LOG4J"/>
</settings>

2.设置数据连接属性:

方式一:在mybatis-config.xml中直接设置数据库参数

 <environments default="development">
       <environment id="development">
           <transactionManager type="JDBC"/>
           <!-- 数据源也有很多第三方的实现,比如dbcp,c3p0,druid等等连接池.... -->
           <dataSource type="POOLED">
               <property name="driver" value="com.mysql.jdbc.Driver"/>
               <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
               <property name="username" value="root"/>
               <property name="password" value="123456"/>
           </dataSource>
       </environment>
   </environments>

方式二:通过 properties 文件的子元素来传递数据库元素,实现可动态替换:

先资源目录下新建一个db.properties:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8
username=root
password=123456
<!--导入properties文件-->
   <properties resource="db.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="${password}"/>
           </dataSource>
       </environment>
   </environments>

3.映射mapper文件:

<!-- 使用相对于类路径的资源引用 -->
<mappers>
 <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>

<!-- 使用完全限定资源定位符(URL) -->
<mappers>
 <mapper url="file:///var/mappers/AuthorMapper.xml"/>
</mappers>

<!--
使用映射器接口实现类的完全限定类名
需要配置文件名称和接口名称一致,并且位于同一目录下
-->
<mappers>
 <mapper class="org.mybatis.builder.AuthorMapper"/>
</mappers>

完整的mybatis-config.xml配置:

<?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="properties.properties"/>

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

<!--    给实体类起别名  -->
    <typeAliases>
        <typeAlias type="jom.who.pojo.Student" alias="Student"/>
        <typeAlias type="jom.who.pojo.Teacher" alias="Teacher"/>
    </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>

<!--    映射到对应的Mapper接口  -->
    <mappers>
        <mapper class="jom.who.dao.TeacherMapper"/>
        <mapper class="jom.who.dao.studentMapper"/>
    </mappers>

</configuration>

4、编写MybatisUtils工具类

读 mybatis-config.xml 并获取 获取SqlSession连接

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;

public class MybatisUtils {

   private static SqlSessionFactory sqlSessionFactory;

   static {
       try {
           String resource = "mybatis-config.xml";
           InputStream inputStream = Resources.getResourceAsStream(resource);
           sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
      } catch (IOException e) {
           e.printStackTrace();
      }
  }

   //获取SqlSession连接
   public static SqlSession getSession(){
       return sqlSessionFactory.openSession();
  }

}

改造MybatisUtils工具类的getSession( ) 方法:

  //获取SqlSession连接
  public static SqlSession getSession(){
      return getSession(true); //事务自动提交
  }

5、创建实体类

方式一:

public class User {
   
   private int id;  //id
   private String name;   //姓名
   private String pwd;   //密码
   
   //构造,有参,无参
   //set/get
   //toString()
   
}

方式二:

//导入Lombok插件,使用注解自动生成。
@Data  //GET,SET,ToString,有参,无参构造
public class Teacher {
   private int id;
   private String name;
}

6、编写Mapper接口类

import com.kuang.pojo.User;
import java.util.List;

public interface UserMapper {
   List<User> selectUser();
}

思路一:直接在方法中传递参数

1、在接口方法的参数前加 @Param属性,当编写Sql语句时,直接取@Param中设置的值即可。在方法接受多个参数的情况下,一般使用@Param注解给参数命名。

//通过密码和名字查询用户
User selectUserByNP(@Param("username") String name,@Param("pwd") String pwd);

/*
   <select id="selectUserByNP" resultType="com.kuang.pojo.User">
     select * from user where name = #{username} and pwd = #{pwd}
   </select>
*/

思路二:如果参数过多,我们可以考虑直接使用Map实现:

1、在接口方法中,参数直接传递Map:

User selectUserByNP2(Map<String,Object> map);

2、编写sql语句的时候,需要传递参数类型,参数类型为map

<select id="selectUserByNP2" parameterType="map" resultType="com.kuang.pojo.User">
select * from user where name = #{username} and pwd = #{pwd}
</select>

3、在使用方法的时候,Map的 key 为 sql中取的值即可,没有顺序要求

Map<String, Object> map = new HashMap<String, Object>();
map.put("username","小明");
map.put("pwd","123456");
User user = mapper.selectUserByNP2(map);

7、编写Mapper.xml配置文件

<?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接口  --> 
<mapper namespace="jom.who.dao.UserMapper">
 <select id="selectUser" resultType="jom.who.pojo.User">
  select * from user
 </select>
</mapper>

8、编写测试类

public class MyTest {
   @Test
   public void selectUser() {
       SqlSession session = MybatisUtils.getSession();
       //方法一:
       //List<User> users = session.selectList("jom.who.mapper.UserMapper.selectUser");
       //方法二:
       UserMapper mapper = session.getMapper(UserMapper.class);
       List<User> users = mapper.selectUser();

       for (User user: users){
           System.out.println(user);
      }
       session.commit(); //提交事务,重点!不写的话不会提交到数据库
       session.close();
  }
}

流程图解:
在这里插入图片描述

02、SQL分页

如果查询大量数据的时候,我们往往使用分页进行查询,也就是每次处理小部分数据,这样对数据库压力就在可控范围内。

1.使用Limit实现分页

#语法
SELECT * FROM table LIMIT stratIndex,pageSize

SELECT * FROM table LIMIT 5,10; // 检索记录行 6-15  

#为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1:   
SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last.  

#如果只给定一个参数,它表示返回最大的记录行数目:   
SELECT * FROM table LIMIT 5; //检索前 5 个记录行  

在测试类中传入参数测试

起始位置 = (当前页面 - 1 ) * 页面大小

   int currentPage = 1;  //第几页
   int pageSize = 2;  //每页显示几个
   Map<String,Integer> map = new HashMap<String,Integer>();
   map.put("startIndex",(currentPage-1)*pageSize);
   map.put("pageSize",pageSize);

   List<User> users = mapper.selectUser(map);

2.PageHelper分页插件

03、使用注解编写SQL语句

查询:

//根据id查询用户
@Select("select * from user where id = #{id}")
User selectUserById(@Param("id") int id);

新增:

//添加一个用户
@Insert("insert into user (id,name,pwd) values (#{id},#{name},#{pwd})")
int addUser(User user);

修改:

//修改一个用户
@Update("update user set name=#{name},pwd=#{pwd} where id = #{id}")
int updateUser(User user);

删除:

//根据id删除用
@Delete("delete from user where id = #{id}")
int deleteUser(@Param("id")int id);

04、一对多和多对一处理

多对一的处理

按查询嵌套处理:

  <!--
   需求:获取所有学生及对应老师的信息
   思路:
       1. 获取所有学生的信息
       2. 根据获取的学生信息的老师ID->获取该老师的信息
       3. 思考问题,这样学生的结果集中应该包含老师,该如何处理呢,数据库中我们一般使用关联查询?
           1. 做一个结果集映射:StudentTeacher
           2. StudentTeacher结果集的类型为 Student
           3. 学生中老师的属性为teacher,对应数据库中为tid。
              多个 [1,...)学生关联一个老师=> 一对一,一对多
           4. 查看官网找到:association – 一个复杂类型的关联;使用它来处理关联查询
   -->
   <select id="getStudents" resultMap="StudentTeacher">
    select * from student
   </select>
   <resultMap id="StudentTeacher" type="Student">
       <!--association关联属性 property属性名 javaType属性类型 column在多的一方的表中的列名-->
       <association property="teacher"  column="tid" javaType="Teacher" select="getTeacher"/>
   </resultMap>
   <!--
   这里传递过来的id,只有一个属性的时候,下面可以写任何值
   association中column多参数配置:
       column="{key=value,key=value}"
       其实就是键值对的形式,key是传给下个sql的取值名称,value是片段一中sql查询的字段名。
   -->
   <select id="getTeacher" resultType="teacher">
      select * from teacher where id = #{id}
   </select>

按结果嵌套处理:

<!--
按查询结果嵌套处理
思路:
   1. 直接查询出结果,进行结果集的映射
-->
<select id="getStudents2" 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">
   <id property="id" column="sid"/>
   <result property="name" column="sname"/>
   <!--关联对象property 关联对象在Student实体类中的属性-->
   <association property="teacher" javaType="Teacher">
       <result property="name" column="tname"/>
   </association>
</resultMap>

一对多的处理

按查询嵌套处理:

<select id="getTeacher2" resultMap="TeacherStudent2">
select * from teacher where id = #{id}
</select>
<resultMap id="TeacherStudent2" type="Teacher">
   <!--column是一对多的外键 , 写的是一的主键的列名-->
   <collection property="students" javaType="ArrayList" ofType="Student" column="id" select="getStudentByTeacherId"/>
</resultMap>
<select id="getStudentByTeacherId" resultType="Student">
  select * from student where tid = #{id}
</select>

按结果嵌套处理:

 <!--
   思路:
       1. 从学生表和老师表中查出学生id,学生姓名,老师姓名
       2. 对查询出来的操作做结果集映射
           1. 集合的话,使用collection!
               JavaType和ofType都是用来指定对象类型的
               JavaType是用来指定pojo中属性的类型
               ofType指定的是映射到list集合属性中pojo的类型。
   -->
   <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=#{id}
   </select>

   <resultMap id="TeacherStudent" type="Teacher">
       <result  property="name" column="tname"/>
       <collection property="students" ofType="Student">
           <result property="id" column="sid" />
           <result property="name" column="sname" />
           <result property="tid" column="tid" />
       </collection>
   </resultMap>

05、动态SQL

动态SQL在开发中大量的使用,一定要熟练掌握!

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

  1. where - if
<!--需求1:
根据作者名字和博客名字来查询博客!
如果作者名字为空,那么只根据博客名字查询,反之,则根据作者名来查询
select * from blog where title = #{title} and author = #{author}

“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。同时,如果标签返回的内容是以 AND 或 OR 开头的它会自动去掉。
-->

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

2.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};
</update>

3.choose - when
满足其中一个查询条件即可

<select id="queryBlogChoose" parameterType="map" resultType="blog">
  select * from 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>

4.SQL片段:
有些 sql 语句用的特别多,为了增加代码的重用性,我们将这些代码抽取出来,使用时直接调用。

注:在 sql 片段中不要包括 where

<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>
       <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
       <include refid="if-title-author"></include>
       <!-- 在这里还可以引用其他的 sql 片段 -->
   </where>
</select>

5.Foreach 根据某个属性的不同值查询多条数据

select * from blog where 1=1 and (id=1 or id=2 or id=3)

<foreach collection="ids"  item="id" open="and (" close=")" separator="or">
          id=#{id}
   collection:指定输入对象中的集合属性
   item:每次遍历生成的对象
   open:开始遍历时的拼接字符串
   close:结束时拼接的字符串
   separator:遍历对象之间需要拼接的字符串

06、缓存

将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。

缓存原理:

在这里插入图片描述

1.一级缓存

一级缓存是SqlSession级别的缓存,是一直开启的,只能通过close()关闭。

每个sqlSession中的缓存相互独立,当多个对象执行同一个操作时,使用的其实是同一个缓存,例如:

@Test
public void testQueryUserById(){
   SqlSession session = MybatisUtils.getSession();
   UserMapper mapper = session.getMapper(UserMapper.class);
   UserMapper mapper2 = session.getMapper(UserMapper.class);

   User user = mapper.queryUserById(1);
   System.out.println(user);
   User user2 = mapper2.queryUserById(2);
   System.out.println(user2);
   System.out.println(user==user2);

   session.close();
}

当改变了查询的数据后,SqlSession会重新执行,生成新的缓存。

二级缓存

基于namespace级别的缓存,一个名称空间,对应一个二级缓存

1、开启全局缓存 【mybatis-config.xml】

<setting name="cacheEnabled" value="true"/>

2、去每个mapper.xml中配置使用二级缓存【xxxMapper.xml】

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

注:查出的数据都会被默认先放在一级缓存中

只有会话提交或者关闭以后,一级缓存中的数据才会转到二级缓存中。

3、第三方缓存实现–EhCache

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值