mybatis学习与使用

"本文深入探讨了MyBatis框架,包括其作为持久层解决方案的优势,如减少代码量、灵活性等。详细介绍了MyBatis的快速入门步骤,如创建核心配置文件、映射文件以及编写Mapper接口。还讨论了#{}
摘要由CSDN通过智能技术生成

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、库和框架的区别?

库: 对原有技术的封装,让操作更加简单

框架: 是一整套技术的解决方案

二.mybatis的介绍

      mybatis是一个持久层(DAO)的框架。把实体类和sql语句之间建立了半自动的映射关系(半自动的ORM)

Mybatis的优点:

  • 减少代码量
  • 基于sql语句,简单易学,自己可以改变sql语句,灵活度高,便于调优
  • 能了解底层组装过程,是开源的
  • sql语句封装在配置文件中,便于统一管理

三.mybatis快速入门

  • 1.建立数据库和数据表
    在这里插入图片描述
  • 2.创建项目,并导包
    在这里插入图片描述
  • 3.创建实体类
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 4.配置mybatis的核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!--引入dtd格式的约束文件-->
<!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:///mybatis?characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
<!--        引入映射文件-->
        <mapper resource="com/shangma/cn/mapper/AMapper.xml"/>
    </mappers>
</configuration>

- 配置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 命名空间  一个命名空间中可以编写n条的sql语句
相当于java中的包,用于区分相同名称的类 这里区分相同的sql
-->
  • xmlsql语句标签:
 查询	  select       <select>
 插入     insert       <insert>
 修改     update       <update>
 删除     delete       <delete>

查询

<!--
添加用户
 keyProperty:表示主键的属性
 order: 表示返回的主键是在添加前(BEFORE)还是在添加后(AFTER)
 last_insert_id() 是mysql中的函数  返回的是最后一次添加的id
-->
   <select id="findAll" resultType="com.shangma.cn.entity.User">
        select * from user
    </select>

根据id查询

 <select id="findUserById" parameterType="int" resultType="com.shangma.cn.entity.User">
        select * from user where id = #{id}
    </select>

添加

   <insert id="addUser" parameterType="com.shangma.cn.entity.User">
		//设置selectKey会返回增加的ID
		<!--

添加用户
 keyProperty:表示主键的属性
 order: 表示返回的主键是在添加前(BEFORE)还是在添加后(AFTER)
 last_insert_id() 是mysql中的函数  返回的是最后一次添加的id
-->
        <selectKey keyProperty="id" order="AFTER" resultType="int">
            select last_insert_id()
        </selectKey>
        insert into user (username,sex,birthday,address) values(#{username},#{sex},#{birthday},#{address})
    </insert>

修改用户

    <update id="updateUser" parameterType="com.shangma.cn.entity.User">
        update user set username = #{username},sex = #{sex},birthday = #{birthday},address=#{address} where id = #{id}
    </update>

根据id删除用户

<!--    根据id删除用户-->
    <delete id="deleteUserById" parameterType="int">
        delete from user where id = #{id}
    </delete>

模糊查询

<!--
模糊查询
mybatis3.4之前,下面必须写value
-->
    <select id="searchUser" parameterType="string" resultType="com.shangma.cn.entity.User">
        select * from user where username like '%${value}%'
    </select>
</mapper>

该处使用的url网络请求的数据。


  • test测试类 编写代码(核心对象SqlSession)
private InputStream inputStream;

    private SqlSession sqlSession;

    @Before  // 表示在每一次测试方法执行之前都会执行
    public void init() throws IOException {
        // mybatis核心配置文件的名称
        String resource = "mybatis.xml";
        // 从路径下面加载核心配置文件
        inputStream = Resources.getResourceAsStream(resource);
        // 获取sqlSession工厂类
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        // 获取sqlSession
        sqlSession = sqlSessionFactory.openSession();
    }

    @After //表示在每一次测试方法执行之后都会执行
    public void release(){
        // 关闭资源
        sqlSession.close();
        try {
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

关于增删改查的测试

  @Test
    public void findAll() throws IOException {
        // 使用sqlsession进行增删改查
        List<User> users = sqlSession.selectList("gufengshuo.findAll");
        users.forEach(user-> System.out.println(user));
    }

    @Test
    public void findUserById() throws IOException {
        // 使用sqlsession进行增删改查
        User user = sqlSession.selectOne("gufengshuo.findUserById", 24);
        System.out.println(user);
    }


    @Test
    public void addUser() throws IOException {
        // 使用sqlsession进行增删改查
        User user = new User();
        user.setUsername("张无忌");
        user.setSex("男");
        user.setAddress("冰火岛");
        user.setBirthday(new Date());
        sqlSession.insert("gufengshuo.addUser",user);
        // 增删改时,需要手动提交事务,否则不能持久化到数据库中
        sqlSession.commit();
        System.out.println(user);
    }

    @Test
    public void updateUser() throws IOException {
        // 使用sqlsession进行增删改查
        User user = new User();
        user.setId(22);
        user.setUsername("谢逊");
        user.setSex("男");
        user.setAddress("冰火岛");
        user.setBirthday(new Date());
        // 修改数据
        sqlSession.update("gufengshuo.updateUser",user);
        // 增删改时,需要手动提交事务,否则不能持久化到数据库中
        sqlSession.commit();
    }


    @Test
    public void deleteUser() throws IOException {
        // 使用sqlsession进行增删改查
        // 删除数据
        sqlSession.delete("gufengshuo.deleteUserById",36);
        // 增删改时,需要手动提交事务,否则不能持久化到数据库中
        sqlSession.commit();
    }

    @Test
    public void searchUser() throws IOException {
        // 使用sqlsession进行增删改查
        List<User> users = sqlSession.selectList("gufengshuo.searchUser", "张");
        System.out.println(users);
    }

五 mybatismapper开发

使用这种方式,可以不用写dao的实现类.程序员只需要编写mapper接口就可以。

注意:这种使用方式需要符合规范

5.1 Mapper代理书写规范
  • Mapper接口的完整路径,要和Mapper配置文件(xml)中的namespace一致
  • Mapper接口中的方法名,必须和mapper配置文件中的sql语句的id值相同
  • Mapper接口中的方法的参数只能有一个,并且类型要和mapper配置文件中的sql语句的parameterType类型一致
  • mapper接口中的返回值要和mapper配置文件中sql语句的resultType(或者resultMap)的类型一致

六 #{}和${}的区别

  • #{}在引用时,如果发现目标是一个字符串,则会将其值作为一个字符串拼接在sql上
  • ${}在引用时,即使发现目标是一个字符串,也不会作为字符串而是直接使用将其拼接在sql上
    大部分场景都使用#{}
insert into user values(null,#{username},55);
insert into user values(null,'关谷神奇',55);

insert into user values(null,${username},55);
insert into user values(null,关谷神奇,55);

如果需要引用的是一个列名,使用${}

select * from user order by #{cage};
select * from user order by 'age';

select * from user order by ${cage};
select * from user order by age;

# 七.全局配置文件讲解 ## 7.1 文件名称 mybatis的核心配置文件的名称,其实可以随便写。但是在公司中一般都会有两种命名 - sqlMapperConfig.xml - mybatis-config.xml ## 7.2 数据库环境配置
<!--    default 要使用哪一个数据库环境-->
    <environments default="development">
<!--        开发环境下的数据库-->
//此外还有test(测试环境)www(上线环境)
        <environment id="development">
<!--     JDBC的事务管理 交给mybatis统一管理       -->
            <transactionManager type="JDBC"/>
<!--
       dataSource 数据源(连接池)
       type: POOLED    要使用POOLED的数据源 不是druid 也不是C3p0  对应的类是PooledDataSource
             UNPOOLED  对应的是UnPooledDataSource
       -->
            <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>

7.3 导入外部配置文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///mybatis?characterEncoding=utf-8
username=root
password=123456

在核心配置文件中加载

<!--    加载配置文件-->
    <properties resource="db.properties"></properties>

使用

<dataSource type="POOLED">
<!--                数据源的配置-->
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>

7.4别名标签

  1.参数类型和返回值类型如果是引用数据类型,默认需要使用的是全路径名
  2.设置别名  别名不区分大小写 但是一般都使用全小写
    <typeAliases>
<!--        <typeAlias type="com.shangma.cn.entity.User" alias="user"/>-->
       ** 整个entity包下的类全部别名是类名的小写(不区分大小写)**
        <package name="com.shangma.cn.entity"/>
    </typeAliases>

7.5 映射文件

    <mappers>
    	  实际开发中的用法
        直接写包名,表示自动去对应的包下找到mapper接口和包下对应的同名的xml
        注意点:**如果要使用package,接口名称要和mapper文件名一致 并且在同一个目录下**
        <package name="com.shangma.cn.mapper"/>
    </mappers>

八.parameterType

可以取四种值:

  • 基本数据类型
    • 本质上就是官方系统的常用的引用数据类型的别名 如:java.lang.Integer -->int
  • 自定义类型
    • 如果起了别名,可以使用别名.
    • 如果没有起别名,那么必须是全路径名
  • 嵌套类型(对象套对象)
    • #{对象的属性名.属性名…}
  • map使用
    • #{key}
      parameterType可以省略

九.resultType

注意点:
   返回单个实体类和实体类集合时,mapper映射文件中的resultType的类型是一样的.

   这种单独resultType的方式的前提条件是属性名和表中的列名一致,所以数据会封装到实体中

   如果数据库表和实体类中遵守驼峰命名规范,可以在核心xml文件中使用mybaits开启驼峰命名

<settings>
	<!--        开启驼峰命名-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

十.resultMap

  如果表中的字段和实体类中的属性名不一致(表中字段,这里不可改实体类属性名),并且不符合驼峰命名规范,我们可以使用resultMap手动结果映射


resultMap手动结果映射
id:对应的resultMap的唯一标识
type:表示给哪一个类型进行手动结果映射
property:实体类中需要映射的属性名
column:数据库表中的列名

注意点:如果对应的属性和列名是主键,那么可以使用result标签,也可以使用id标签
官方推荐使用id标签,这样效率更高

    <resultMap id="resultId" type="user">
        <id property="userId" column="uid"></id>
        <result property="userAddress" column="abc"></result>
    </resultMap>
    <select id="findUserById" resultMap="resultId">
        <include refid="selectAll"></include> where uid = #{id}
    </select>

十一 动态标签

<where>:动态的判断是否使用 and

<if>:可以有判断的条件

<set>:动态的判断是否用 ,

<trim>:可以添加前缀和后缀,可以动态判断是否覆盖某个符号

<foreach>:遍历集合

11.1 (查)select的使用(where )

<select id="findUsers" resultType="user">
        select * from user
        <where>
        <if test="username != null and username != ''">
           username = #{username}
        </if>
        <if test="sex != null and sex != ''">
            and sex = #{sex}
        </if>
        <if test="address != null and address != ''">
            and address = #{address}
        </if>
        <if test="birthday != null">
            and birthday = #{birthday}
        </if>
        </where>
    </select>

11.2(改)update的使用(必然使用 set )

<update id="updateUser" parameterType="user">
        update user
        <set>
            <if test="username != null and username != ''">
                username = #{username},
            </if>
            <if test="sex != null and sex != ''">
                sex = #{sex},
            </if>
            <if test="birthday != null">
                birthday = #{birthday},
            </if>
            <if test="address != null and address != ''">
                address = #{address},
            </if>
        </set>
        where id = #{id}
    </update>

11.3(增) insert的使用(必然使用 trim )

<insert id="addUser">
        insert into user
        prefix:前缀 suffix:后缀   suffixOverrides:覆盖
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username != null and username != ''">
                username,
            </if>
            <if test="sex != null and sex != ''">
                sex,
            </if>
            <if test="birthday != null">
                birthday,
            </if>
            <if test="address != null and address != ''">
                address
            </if>
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username != null and username != ''">
                #{username},
            </if>
            <if test="sex != null and sex != ''">
                #{sex},
            </if>
            <if test="birthday != null">
                #{birthday},
            </if>
            <if test="address != null and address != ''">
                #{address},
            </if>
        </trim>
    </insert>

11.4(删) delete的使用(必然使用where)

<delete id="deleteUser">
        delete from user
        <where>
            <if test="username != null and username != ''">
                username = #{username}
            </if>
            <if test="sex != null and sex != ''">
                and sex = #{sex}
            </if>
            <if test="birthday != null">
                and birthday = #{birthday}
            </if>
            <if test="address != null and address != ''">
                and address = #{address}
            </if>
        </where>
    </delete>

11.5 批量删除


   批量删除多个id的用户信息
   delete from user where id in(3,8,9)

   foreach:对集合进行遍历
   collection:需要遍历的类型
   open:左边的符号
   close:右边的符号
   separator:遍历之后的元素的分隔符
   item:每一条数据的条目

    <delete id="deleteUsers">
        delete from user where id in
        <foreach collection="list" open="(" close=")" separator="," item="id">
            #{id}
        </foreach>
    </delete>

十二 使用mybatis进行多表查询

一个用户有一个购物车                       一对一

一个购物车对应多个购物车项                     一对多

一个购物车项对应一个商品                     一对一

一个用户可以选择多个商品,一个商品可以被多个用户选择       多对多

12.1 一对一查询

需求:查询用户以及他的购物车的信息

12.1.1生成cart实体类
public class Cart {

  private String cartId;
  private long userId;
  private long totalnum;
  private double totalmoney;
  public String getCartId() {
    return cartId;
  }
  public void setCartId(String cartId) {
    this.cartId = cartId;
  }
  public long getUserId() {
    return userId;
  }
  public void setUserId(long userId) {
    this.userId = userId;
  }
  public long getTotalnum() {
    return totalnum;
  }
  public void setTotalnum(long totalnum) {
    this.totalnum = totalnum;
  }
  public double getTotalmoney() {
    return totalmoney;
  }
  public void setTotalmoney(double totalmoney) {
    this.totalmoney = totalmoney;
  }
  @Override
  public String toString() {
    return "Cart{" +
            "cartId='" + cartId + '\'' +
            ", userId=" + userId +
            ", totalnum=" + totalnum +
            ", totalmoney=" + totalmoney +
            '}';
  }
}
12.1.2 在User类中添加cart属性,提供set和get和toString方法

在这里插入图片描述

12.1.3 在UserMapper接口中添加抽象方法
/**
     * 查询用户和购物车信息
     */
    List<User> selectUserAndCart();
12.1.4 在UserMapper.xml中添加代码
<!--
   多表查询之一对一
   sql语句   select * from user u,cart c where u.id = c.userId
   在user中需要描述一个cart
   association:描述的是一对一的关系
   javaType:要对哪一个类型进行描述
-->
    <resultMap id="userandcart" type="user">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="sex" column="sex"></result>
        <result property="birthday" column="birthday"></result>
        <result property="address" column="address"></result>
        手动映射 cart
        <association property="cart" javaType="cart">
            <id property="cartId" column="cartId"></id>
            <result property="userId" column="userId"></result>
            <result property="totalnum" column="totalnum"></result>
            <result property="totalmoney" column="totalmoney"></result>
        </association>
    </resultMap>
    <select id="selectUserAndCart" resultMap="userandcart">
        select * from user u,cart c where u.id = c.userId
    </select>
测试
	@Test
    public void test08(){
        List<User> users = userMapper.selectUserAndCart();
        users.forEach(user -> System.out.println(user));
    }

12.2 一对多查询

需求:查询购物车和对应的购物车条目项

12.2.1 创建CartMapper接口
public interface CartMapper {
    /**
     * 查询购物车和购物车项
     */
    List<Cart> selectCartAndCartItem();
}
12.2.2 创建CartMapper.xml
<mapper namespace="com.shangma.cn.mapper.CartMapper">
    <!--
    select * from cart c,cartitem ci where c.cartId = ci.cartId

    collection:描述的是一对多关系时,多的一方
    property: 属性名
    ofType:表示集合中的泛型类型
    -->
    <resultMap id="cartandcartitem" type="cart">
        <id property="cartId" column="cartId"></id>
        <result property="userId" column="userId"></result>
        <result property="totalnum" column="totalnum"></result>
        <result property="totalmoney" column="totalmoney"></result>
        <collection property="cartitems" ofType="cartitem">
            <id property="cartItemId" column="cartItemId"></id>
            <result property="cartId" column="cartId"></result>
            <result property="pid" column="pid"></result>
            <result property="pnum" column="pnum"></result>
            <result property="pmoney" column="pmoney"></result>
        </collection>
    </resultMap>
    <select id="selectCartAndCartItem" resultMap="cartandcartitem">
        select * from cart c,cartitem ci where c.cartId = ci.cartId
    </select>
</mapper>

12.3 多对多(四表联查)

需求:查询用户和用户购买的商品

12.3.1 在UserMapper接口中添加抽象方法
/**
     * 查询用户及用户的商品
     */
    List<User> selectUserAndGoods();
12.3.2 在UserMapper.xml中添加sql语句
<resultMap id="userandgood" type="user">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="sex" column="sex"></result>
        <result property="birthday" column="birthday"></result>
        <result property="address" column="address"></result>
        <association property="cart" javaType="cart">
            <id property="cartId" column="cartId"></id>
            <result property="userId" column="userId"></result>
            <result property="totalnum" column="totalnum"></result>
            <result property="totalmoney" column="totalmoney"></result>
            <collection property="cartitems" ofType="cartitem">
                <id property="cartItemId" column="cartItemId"></id>
                <result property="cartId" column="cartId"></result>
                <result property="pid" column="pid"></result>
                <result property="pnum" column="pnum"></result>
                <result property="pmoney" column="pmoney"></result>
                <association property="good" javaType="good">
                    <id property="pid" column="pid"></id>
                    <result property="pname" column="pname"></result>
                    <result property="price" column="price"></result>
                    <result property="pimg" column="pimg"></result>
                    <result property="pdesc" column="pdesc"></result>
                </association>
            </collection>
        </association>
    </resultMap>
<select id="selectUserAndGoods" resultMap="userandgood">
 select * from    user u,cart c,cartitem ci,good g    where    u.id = c.userId  
   and    c.cartId = ci.cartId    and ci.pid =g.pid
</select>

14 mybatis的延迟加载

  延迟加载又叫做懒加载(lazy load)表示关联查询时,当使用关联的数据时,才真正去数据库查询,可以减轻数据库的压力,提高查询的性能和效率
需求:查询用户和购物车信息

14.1默认延迟加载是关闭的需要在核心xml中打开权限

<!--        延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>

14.2在UserMapper中添加抽象方法

     使用懒加载的方式查询用户和购物车信息
    
    List<User> selectUserAndCartByLazyLoad();

14.3在UserMapper.xml中添加配置


select:需要执行的方法  一定要写全路径名
column:id   表示将select * from user的结果的id列的值传给select标签指定方法的参数

    <resultMap id="lazyMap" type="user">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="sex" column="sex"></result>
        <result property="birthday" column="birthday"></result>
        <result property="address" column="address"></result>
        <association property="cart" javaType="cart" select="com.shangma.cn.mapper.CartMapper.selectCartById" column="id"></association>
    </resultMap>
    <select id="selectUserAndCartByLazyLoad" resultMap="lazyMap">
        select * from user
    </select>

14.4在CartMapper中添加抽象方法

/**
     * 通过id查询购物车
     */
    Cart selectCartById(int userId);

14.5在CartMapper.xml中添加配置

<select id="selectCartById" resultType="cart">
        select * from cart where userId = #{id}
    </select>

14.6测试

结果

测试时发现,如果只是获取用户的基本信息,不会执行select * from cart where userId = #{id}语句,如果明确的指定要获取购物车信息,那么会执行select * from cart where userId = #{id}语句

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值