MyBatis

MyBatis 是一个开源、轻量级的数据持久化框架

学习文档:

https://www.cnblogs.com/hnkjdx-ssf/p/14942618.html

官方学习文档:https://github.com/xinyu-yudian/mybatis.git

原生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>
   <environments default="development">
       <environment id="development">
           <transactionManager type="JDBC"/>
           <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>
<!--每一个Mapper.xml都需要在Mybatis核心配置文件中注册! //或在接口上添加@Mapper注解--> <mappers> <mapper resource="com/kuang/dao/userMapper.xml"/> </mappers> </configuration>

实体类设置别名

方式一:注解

<typeAliases>
        <typeAlias type="com.kuang.pojo.User" alias="User" />
    </typeAliases>

 方式二:指定一个包名,扫描实体类的包,它的默认别名就为这个类的类名,首字母小写

<typeAliases>
        <package name="com.kuang.pojo"/>
    </typeAliases>
@Alias("User")
public class User {}

 

自动装配(spring)

 <!--连接数据库-->
    <!--1.导入外部文件-->
    <context:property-placeholder location="mysql.properties"/>
    <!--2.配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="testWhileIdle" value="true"/>
    </bean>

    <!-- 配置SqlSessionFactory对象 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 配置MyBaties全局配置文件:mybatis.xml -->
        <property name="configLocation" value="classpath:mybatis.xml"/>
    </bean>

    <!-- 配置扫描Dao接口包,动态实现Dao接口注入到spring容器中 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 注入sqlSessionFactory -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!-- mapper -->
        <property name="basePackage" value="com.xinyu.dao"/>
    </bean>

数据源

com.mchange.v2.c3p0.ComboPooledDataSource

org.apache.commons.dbcp2.BasicDataSource

 

<select>标签的属性

  id:唯一指定标签的名字

  resultType:查询结构返回的数据类型,自动进行封装操作

  parameterType:给SQL语句传递参数的数据类型

  resultMap:查询结果返回的数据类型,会根据映射文件中<resultMap>来完成数据封装

  parameterMap:给SQL语句传递参数的数据类型,需要和<parameterMap.../>标签连用

 模糊查询:https://blog.csdn.net/Adobe_java/article/details/118460709

mybatis工作流程:

-编写核心配置文件,环境信息,日志,缓存,Mapper等
-通过SqlSessionPactorBuild读取核心配置文件构建SqlSession
-通过SqlSessionOactor.getSession构建SqlSession
-使用SqlSession执行SQL语句

<Mapper>标签中加载XML文件几种方式
---URL
---CLASS
---RESOURCE
---PACKAGE


Mapper注意点:
接口和xml名字一样,路径一样(需到核心配置xml中配置<mappers>,因为maven工程约定:配置>编码)
接口的方法名和参数和返回值必须和xml保持一致
xml的命令空间必须全限定名

 

mybatis属性

resultMap:
resultMap 是一种“查询结果集---Bean对象”属性名称映射关系,
使用resultMap关系可将将查询结果集中的列一一映射到bean对象的各个属性
(两者属性名可以不同,配置好映射关系即可),适用与复杂一点的查询。
(1)适用于表的连接查询
(2)适用于表的一对多连接查询
(3)映射的查询结果集中的列标签可以根据需要灵活变化,
并且,在映射关系中,还可以通过typeHandler设置实现查询结果值的类型转换

resultType:
resultType 是一种“查询结果集---Bean对象”数据类型映射关系,使用resultType关系,即可使Bean对象接收查询结果集;
见名知意,该方法是通过查询结果集中每条记录(属性)的数据类型和Bean对象的数据类型作映射,
若两者都相同,则表示匹配成功,Bean可以接收到查询结果。
一般适用于pojo(简单对象)类型数据,简单的单表查询。

ParameterMap:
ParameterMap和resultMap类似,表示将查询结果集中列值的类型一一映射到java对象属性的类型上

parameterType
parameterType直接将查询结果列值类型自动对应到java对象属性类型上,不再配置映射关系一一对应

javaType:
javaType是用来指定pojo中对象属性的类型---(对象映射association用javaType)

ofType:
ofType指定的是映射到list集合属性中泛型的类型---(结果集collection用ofType)

 

mybatis常用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">
<!--namespace指定对应的dao/mapper接口-->
<mapper namespace="com.kuang.mapper.UserMapper">

    <!--模糊查询-->
    <select id="seletc" parameterType="string" resultType="com.kuang.pojo.User">
      select * from user where name like concat('%',#{name},'%');
   </select>

    <!--根据id查询-->
    <select id="selectById" parameterType="int" resultType="com.kuang.pojo.User">
        select * from user where id = #{id}
    </select>

    <!--新增-->
    <insert id="add" parameterType="com.kuang.pojo.User">
        insert user(id,name,pwd) values (#{id},#{name},#{pwd})
    </insert>

    <!--修改-->
    <update id="update" parameterType="com.kuang.pojo.User">
        update user set name = #{name},pwd = #{pwd} where id = #{id}
    </update>

    <!--删除-->
    <delete id="delete" parameterType="int">
        delete from user where id = #{id}
    </delete>

</mapper>

 

配置 JAVA 对象属性与查询结果集中列名对应关系
resultMap 标签的使用
基本作用:

建立 SQL 查询结果字段与实体属性的映射关系信息
查询的结果集转换为 java 对象,方便进一步操作。
将结果集中的列与 java 对象中的属性对应起来并将值填充进去
!注意:与 java 对象对应的列不是数据库中表的列名,而是查询后结果集的列名

<resultMap id="BaseResultMap" type="com.online.charge.platform.student.model.Student">
<id property="id" column="id" />
<result column="NAME" property="name" />
<result column="HOBBY" property="hobby" />
<result column="MAJOR" property="major" />
<result column="BIRTHDAY" property="birthday" />
<result column="AGE" property="age" />
</resultMap>

<!--查询时resultMap引用该resultMap -->
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="Object">
select id,name,hobby,major,birthday,age from student where id=#{id}
</select>

标签说明:

主标签:

id:该 resultMap 的标志
type:返回值的类名,此例中返回 Studnet 类
子标签:

id:用于设置主键字段与领域模型属性的映射关系,此处主键为 ID,对应 id。
result:用于设置普通字段与领域模型属性的映射关系
三. 动态 sql 拼接
if 标签
if 标签通常用于 WHERE 语句、UPDATE 语句、INSERT 语句中,通过判断参数值来决定是否使用某个查询条件、判断是否更新某一个字段、判断是否插入某个字段的值。

<if test="name != null and name != ''">
and NAME = #{name}
</if>

foreach 标签
foreach 标签主要用于构建 in 条件,可在 sql 中对集合进行迭代。也常用到批量删除、添加等操作中。

<!-- in查询所有,不分页 -->
<select id="selectIn" resultMap="BaseResultMap">
select name,hobby from student where id in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>

属性介绍:

collection:collection 属性的值有三个分别是 list、array、map 三种,分别对应的参数类型为:List、数组、map 集合。
item :表示在迭代过程中每一个元素的别名
index :表示在迭代过程中每次迭代到的位置(下标)
open :前缀
close :后缀
separator :分隔符,表示迭代时每个元素之间以什么分隔
choose 标签
有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。MyBatis 提供了 choose 元素,按顺序判断 when 中的条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when
的条件都不满则时,则执行 otherwise 中的 sql。类似于 Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。

if 是与(and)的关系,而 choose 是或(or)的关系。

<select id="getStudentListChoose" parameterType="Student" resultMap="BaseResultMap">
SELECT * from STUDENT WHERE 1=1
<where>
<choose>
<when test="Name!=null and student!='' ">
AND name LIKE CONCAT(CONCAT('%', #{student}),'%')
</when>
<when test="hobby!= null and hobby!= '' ">
AND hobby = #{hobby}
</when>
<otherwise>
AND AGE = 15
</otherwise>
</choose>
</where>
</select>

 otherwise

 sql片断(抽取出来的内容)

 字符拼接

LIKE ‘%${name}%’   //#{}能够有效防止SQL注入,但是也有它的缺点,它会把传入的数据自动加上一个双引号
like concat('%','#{a}','%')
liek "%"#{a}"%"

 

关联关系查询:

一对一:association -> javaType

一对多:conllection(集合) -> ofType

 

<?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.xinyu.mapper.fourTab.FourTabMapper">

    <resultMap id="itemsMap" type="com.xinyu.entity.Items">
        <id property="id" column="iid"/>
        <result property="name" column="name"/>
        <result property="price" column="price"/>
        <result property="detail" column="detail"/>
        <result property="pic" column="pic"/>
        <result property="createTime" column="createTime"/>
    </resultMap>

    <resultMap id="orderDetailMap" type="com.xinyu.entity.OrderDetail">
        <id property="id" column="did"/>
        <result property="ordersId" column="orders_id"/>
        <result property="itemsId" column="items_id"/>
        <result property="itemsNum" column="items_num"/>
        <association property="items" resultMap="itemsMap"/>
    </resultMap>

    <resultMap id="ordersMap" type="com.xinyu.entity.Orders">
        <id property="id" column="oid"/>
        <result property="userId" column="userId"/>
        <result property="number" column="number"/>
        <result property="createTime" column="createTime"/>
        <result property="note" column="note"/>
        <collection property="orderDetailList" resultMap="orderDetailMap"/>
    </resultMap>

    <resultMap id="userMap" type="com.xinyu.entity.User">
        <id property="id" column="uid"/>
        <result property="username" column="username"/>
        <result property="birthday" column="birthday"/>
        <result property="sex" column="sex"/>
        <result property="address" column="address"/>
        <collection property="ordersList" resultMap="ordersMap"/>
    </resultMap>

    <select id="usersList" resultMap="userMap" parameterType="int">
        SELECT
            u.id uid,
            u.username,
            u.birthday,
            u.sex,
            u.address,
            o.id oid,
            o.number,
            o.createtime,
            o.note,
            d.id id,
            d.items_num,
            i.id iid,
            i.`name`,
            i.price,
            i.detail,
            i.pic,
            i.createtime
        FROM `user` u
                 LEFT JOIN orders o
                           on o.user_id = u.id
                 LEFT JOIN orderdetail d
                           on d.orders_id = o.id
                 LEFT JOIN items i
                           on i.id=d.items_id
        WHERE u.id=#{uid}
    </select>

</mapper>

 

 

 

储存缓存

一级缓存(默认) -- SqlSession级别

第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。
得到用户信息,将用户信息存储到一级缓存中。

如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。

二级缓存 -- mapper级别

第一次调用mapper下的SQL去查询用户信息。查询到的信息会存到该mapper对应的二级缓存区域内。

第二次调用相同namespace下的mapper映射文件中相同的SQL去查询用户信息。会去对应的二级缓存内取结果。

如果调用相同namespace下的mapper映射文件中的增删改SQL,并执行了commit操作。此时会清空该namespace下的二级缓存。

禁用二级缓存:userCache=false(<select>)

刷新二级缓存:flushCache=true -- select默认flushCache是false,insert、update、delete语句默认flushCache是true

开启二级缓存(mybatis核心控制文件):

<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<!--配置二级缓存-->
<cache/>

 

 

 

a.junit
test.java.com.**.dao.UserdaoTest:

public class UserDaoTest {
1.查询全部:
@Test
public void test(){
//获取Sqlsession对象
SqlSession sqlSession= mybatisUtils.getSqlSession();
try{
//执行SQl
UserDao userDao=sqlSession.getMapper(UserDao.class);
List<User> userList=userDao.getUserList();
for(User user:userList){
System.out.println(user);
}
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭SqlSession
sqlSession.close();
}
}

2.id查询:
@Test
public void getUserById(){
SqlSession sqlSession= mybatisUtils.getSqlSession();
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
User user=mapper.getUserById(1);
System.out.println(user);
sqlSession.close();
}
//模糊查询
@Test
public void getUserById(){
SqlSession sqlSession= mybatisUtils.getSqlSession();
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
List<User> userList=mapper.getUserLike(value:"");
for(User user:userList){
System.out.println(user);
}
sqlSession.close();
}
//增删改需要提交事务
3.insert增加:
@Test
public void addUser(){
SqlSession sqlSession= mybatisUtils.getSqlSession();
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
if res=mapper.addUser(new User(id:4,name:"哈哈",pwd:"123333"));
if(res>0){
System.out.println("插入成功!");
}
//提交事务
sqlSession.commit();
sqlSession.close();
}
Map运用:
@Test
public void addUser(){
SqlSession sqlSession= mybatisUtils.getSqlSession();
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
Map<string,object> map=new HashMap<String,Oobject>
map.put("userid",5);
map.put("password","222333");
mapper.addUser(map);
sqlSession.close();
}

4.update修改:
@Test
public void updateUser(){
SqlSession sqlSession=MybatisUtils.getSqlSession();
userMapper mapper=sqlSession.getMapper(UserMapper.class);
mapper.updateUser(new User(id:4,name:"呵呵",pwd:"123333"));
if(res>0){
System.out.println("修改成功!");
}
//提交事务
sqlSession.commit();
sqlSession.close();
}

5.delete删除:
@Test
public void deleteUser(){
SqlSession sqlSession=MybatisUtils.getSqlSession();
userMapper mapper=sqlSession.getMapper(UserMapper.class);
mapper.deleteUser(id:4);
}
if(res>0){
System.out.println("删除成功!");
}
//提交事务
sqlSession.commit();
sqlSession.close();
}
}

 

注解开发

多参数 ——> arg0  ,  param1 , 

 @Select("select * from user where id=#{id}")
    User getUserById(@Param("id") int id);

    @Insert("insert into user (id,name,pwd) values(#{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);

注解动态SQL

@SelectProvider:用于构建动态查询SQL。
@InsertProvider:用于构建动态新增SQL。
@UpdateProvider:用于构建动态更新SQL。
@DeleteProvider:用于构建动态删除SQL。
    @UpdateProvider(type = BookProvider.class,method = "update")
    int update2(Book book);
class BookProvider{ public static String update(Book book){ return new SQL(){{ UPDATE("t_book"); if(book.getName()!=null){ SET("name=#{name}"); } if(book.getAuthor()!=null){ SET("author=#{author}"); } WHERE("id = #{id}"); } }.toString(); }

 

分页(PageHelper)

方式一:mybatis.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>
    <plugins>
        <!--分页插件-->
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <property name="param1" value="value1"/>
        </plugin>
    </plugins>

</configuration>

方式二:Spring 配置文件中配置拦截器插件

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <!-- 注意其他配置 -->
  <property name="plugins">
    <array>
      <bean class="com.github.pagehelper.PageInterceptor">
        <property name="properties">
          <!--使用下面的方式配置参数,一行配置一个 -->
          <value>
            params=value1
          </value>
        </property>
      </bean>
    </array>
  </property>
</bean>

使用

start = (pageNow-1)*pageSize;
        PageHelper.offsetPage(start, pageSize);
        List<User> userList = userService.getUserList(user);
        PageInfo pageInfo = new PageInfo<>(userList);
        System.out.println(pageInfo);

        long total = pageInfo.getTotal();
        long pageTotal = total%pageSize==0 ? total/pageSize : total/pageSize+1;

 

posted @ 2022-10-09 14:25  歆鱼  阅读(47)  评论(0编辑  收藏  举报