MyBatis的基本使用

一、框架

为了简化开发步骤,省去开发细节,提高编写代码的效率,可以使用框架来完成一些底层的操作。例如:

  • 数据类型转换 => 交给框架
  • 数据校验 => 交给框架
  • 将增删改查集中管理 => 交给框架
  • 异常的统一处理
  • 简化jdbc => 交给框架
  • 使用框架组合各种技术

(一) 框架分类

  1. 持久性框架
    与数据库打交道
    ORM框架: object(java)对象 relationship (关系型数据库 mysql) mapping (映射-java对象和数据库之间)
    常用的有:mybatis(大型项目-直接管理sql),hibernate(小型项目-不需要直接写sql语句),jpa,jooq …

  2. mvc 框架
    跟 web 应用程序打交道
    Model(模型-数据) View(视图-数据展现方式) Controller(控制器)
    把模型数据准备好, 把数据放入作用域, 最后通过jsp视图展现数据
    常用的有:springmvc, struts2

  3. spring 框架 (容器技术)
    把各种框架进行集成,让他们协同工作

二、MyBatis

MyBatis 是支持自定义SQL、存储过程以及高级映射的优秀的持久层框架。避免了JDBC 代码和手动设置参数以及获取结果集。可以使用简单的XML或注解来进行配置。

以前 iBatis ->被收购后 apache MyBatis

(一) MyBatis使用步骤

  1. 添加依赖
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>
  1. 添加配置文件 mybatis-config.xml
    用这个配置文件来告诉 mybatis 如何连接数据库
    告诉 mybatis 到哪里去找映射关系

  2. 提供一个 映射文件
    用来管理 sql 语句,描述 sql 语句与数据库表之间的映射关系

  3. .调用 mybatis api 使用映射文件真正执行增删改查

InputStream in = Resources.getResourceAsStream("配置文件的路径");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = factory.openSession();

sqlSession
    .insert("命名空间+sql的名字", sql需要的参数对象)
    .update("命名空间+sql的名字", sql需要的参数对象)
    .delete("命名空间+sql的名字", sql需要的参数对象)
    .selectOne("命名空间+sql的名字", sql需要的参数对象)  结果只有一个时 
    .selectList("命名空间+sql的名字", sql需要的参数对象) 结果是list集合

对增删改
sqlSession.commit();

关闭
sqlSession.close();

(二) Mybatis 映射文件

  1. 新增
<!-- #{sname} 用来获取 Student 参数对象中的 sname属性-->
<!-- useGeneratedKeys="true" 是告诉 mybatis 要使用由数据库产生的主键值 -->
<!-- keyProperty="主键对应的属性名" -->
<insert id="abc" parameterType="domain.Student"
        useGeneratedKeys="true" keyProperty="sid">
    insert into student(sid, sname, birthday, sex)
        values ( null, #{name}, #{birthday}, #{sex})
</insert>
  1. 删除
<delete id="delete" parameterType="int">
    delete from student where sid = #{sid}
</delete>
  1. 查询所有
<select id="findAll" resultType="domain.Student">
    select sid,sname name,birthday,sex from student
</select>
  1. 根据id查询
<select id="findById" resultType="domain.Student" parameterType="int">
    select sid,sname name,birthday,sex from student where sid = #{sid}
</select>
  1. 更新
<update id="update" parameterType="domain.Student">
    update student set sname=#{name}, birthday=#{birthday}, sex=#{sex} where sid=#{sid}
</update>
动态更新:
<!-- 动态更新列
Student stu = new Student();
stu.setSid(1001);
stu.setSex("男");

update student set sex=#{sex} where sid=#{sid}
用  set 标签可以去除多余的逗号
-->
<update id="update" parameterType="domain.Student">
    update student
    <set>
        <if test="name != null">
            sname=#{name},
        </if>
        <if test="birthday != null">
            birthday=#{birthday},
        </if>
        <if test="sex != null">
            sex=#{sex},
        </if>
    </set>
    where sid=#{sid}
</update>
  1. 分页查询
<!-- m , n
java.util.Map -> map
java.util.List -> list
java.lang.String -> string
map.put("m", 0);
map.put("n", 5);
-->
<select id="findByPage" parameterType="map" resultType="domain.Student">
    select sid,sname name,birthday,sex from student limit #{m}, #{n}
</select>

(三) 通过日志工具监控mybatis生成的sql语句

  1. 添加logback依赖
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>
  1. 添加一个 logback.xml 到 resources文件夹
<!-- 用来控制查看那个类的日志内容(对mybatis name 代表命名空间) -->
<logger name="mapper.StudentMapper" level="DEBUG" additivity="false">
    <appender-ref ref="STDOUT"/>
    <appender-ref ref="FILE"/>
</logger>

三、动态sql和Mapper接口

(一) 动态 sql 生成

  1. foreach 循环

delete from 表 where id in(1008,1011,1012);

<!-- list (1008,1011,1012, 1013) -->
<delete id="" parameterType="list">
delete  from 表 where id in  
 <foreach collection="list" item="x" open="(" close=")" separator=",">#{x}</foreach>
</delete>
  1. if where 生成动态sql
<where> 能够生成 where 关键字,并去除多余的 and
<if test="条件"> sql 片段 </if>
  1. 对于大于小于条件的处理
    方法1: 对每个特殊字符转转义,例如 < <
    方法2: <![CDATA[ 内容 ]]>

  2. #{ } 与 ${ } 的区别

  • #{ } 底层是替换为 ?, 只能占位值
  • ${ } 底层是直接拼接字符串, 有注入攻击问题
  • 尽量使用 #{ } , 只有在某些功能不能用 #{ } 实现时(例如排序)采用 ${ }

(二) Mapper 接口

  1. 基础接口
  • @Insert
  • @Option(useGeneratedKeys =true.keyProperty=“sid”)
  • @Update
  • @Delete
  • @Select
@Insert("insert into student(sid,sname,birthday,sex) values(null,#{sname}, #{birthday}, #{sex})")
@Options(useGeneratedKeys = true, keyProperty = "sid")
void insert(Student student);

@Update("update student set sname=#{sname}, birthday=#{birthday}, sex=#{sex} where sid=#{sid}")
void update(Student student);

@Delete("delete from student where sid=#{sid}")
void delete(int sid);

@Select("select * from student")
List<Student> findAll();

@Select("select * from student where sid = #{sid}")
Student findById(int sid);

@Select("select * from student limit #{m}, #{n}")
List<Student> findByPage(Map map);
  1. 原理
// 这个类是使用了 jdk的动态代理技术 在代码运行期间生成的类 
public class $Proxy10 implements StudentMapper{
    private SqlSession sqlSession;
    public $Proxy10(SqlSession sqlSession) {
        this.sqlSession = sqlSession;
    }
// 其中 sql语句从@Insert注解获得, 参数对象就是student
public void insert(Student student) {
     sqlSession.insert(sql, 参数对象)
  }

// 其中 sql语句从@Select注解获得
public List<Student> findAll() {
     return sqlSession.selectList(sql);
  }
}
  1. 基本使用
(1)在mybatis的配置文件中指定映射接口的包名,类名
<mappers>
        <!-- 指定映射接口的 包名.类名 -->
        <mapper class="mapper.StudentMapper"></mapper>
</mappers>
(2)在mapper接口中写好sql语句
public interface StudentMapper {
    @Insert("insert into student(sid,sname,birthday,sex) values(null,#{sname}, #{birthday}, #{sex})")
    @Options(useGeneratedKeys = true, keyProperty = "sid")
    void insert(Student student);
 }   
(3)使用mapper接口执行sql语句
public class TestStudentMapper {
    static SqlSessionFactory factory;
    static {
        // 读取配置文件
        try(InputStream in = Resources.getResourceAsStream("mybatis-config.xml")){
            // 创建 sqlSession 工厂类
            factory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Test
    public void testInsert() throws ParseException {
        SqlSession sqlSession = factory.openSession();
        // 先通过 sqlSession 获得接口对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        Student stu = new Student();
        stu.setSname("啊啊啊");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        stu.setBirthday(sdf.parse("1999-5-5"));
        stu.setSex("男");
        // 通过接口对象中声明的方法 执行sql语句
        mapper.insert(stu);

        sqlSession.commit();
        sqlSession.close();
    }
}

(三) Mapper接口的不足

  1. 接口方法不能直接应用多个方法参数
    解决方法:
    (1) 用map传递多个参数, 每个参数对应map中的一个键值对
    (2) 用@Param注解
@Select("select * from student limit #{m}, #{n}")
List<Student> findByPage(Map map);

// 同时根据姓名和性别查询
@Select("select * from student where sname=#{a} and sex=#{b}")
List<Student> find1(@Param("a") String sname, @Param("b") String sex);
  1. Mapper 接口中不能有方法的重载
    解决方法:定义方法时不要方法名冲突
异常信息:
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for 接口名.方法名(重复的)
  1. 使用Mapper接口方式实现动态sql比较复杂
    解决方法: 结合Mapper接口和xml文件,接口和xml中必须一一对应
    在这里插入图片描述

(四) 复杂sql映射

除xml mapper 以外,还可以利用 @DeleteProvider @InsertProvider @SelectProvider @UpdateProvider
生成复杂sql

public class StudentSqlProvider {
    // 1, 2, 3,  list参数名 固定为 list
    public static String getDeleteByIdsSql(@Param("list") List<Integer> aaa) {
        StringBuilder sb = new StringBuilder(128);
        sb.append("delete from student where sid in");
        sb.append("(");
        for (int i = 0; i < aaa.size(); i++) {
            sb.append(aaa.get(i));
            if(i < aaa.size()-1) {
                sb.append(",");
            }
        }
        sb.append(")");
        return sb.toString();
    }
}

public interface StudentMapper {
    // 由 @DeleteProvider 注解找到一条sql语句,供 deleteByIds 方法使用
    @DeleteProvider(type = StudentSqlProvider.class,method = "getDeleteByIdsSql")
    void deleteByIds(List<Integer> ids);
    }

(五) 高级映射

当表列 与 属性名 不一致 时==> 给列起别名

四、缓存

select * from student where id = 1001 student

select * from student where id = 1001

  • sqlsession 自带缓存功能,缓存没有才查库,缓存中有,直接返回缓存的结果,称为一级缓存
  • 在sqlsession创建时建立,sqlsession.close 时清空
  • 每个sqlsession有自己独立的缓存

二级缓存:
需要额外设置,但可以允许多个 sqlsession 共享缓存数据,二级缓存中的对象需要实现序列化接口
好处: 可以较大提升查询效率, 但是增删改频繁的情况下,不适合开启二级缓存
xml mapper 二级缓存的配置: 在 xml 映射文件中添加<cache/>标签即可
接口 mapper 二级缓存的配置: 在接口上添加 @CacheNamespace 注解

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值