热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Mybatis一:理论知识和增删改查

目录1概述1.1简介1.2核心对象1.3mybatis配置文件1.4mybatis映射文件2入门程序2.1xml方式2.2annotation方式3增删改查3.1xml方式3.2a

目录



  • 1 概述

    • 1.1 简介

    • 1.2 核心对象

    • 1.3 mybatis配置文件

    • 1.4 mybatis映射文件



  • 2 入门程序

    • 2.1 xml方式

    • 2.2 annotation方式



  • 3 增删改查

    • 3.1 xml方式

    • 3.2 annotation方式




1 概述

1.1 简介



  1. mybatis是个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注SQL语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。

  2. mybatis通过xml或annotation的方式将要执行的各种statement配置起来,并通过java对象和statement中SQL的动态参数进行映射生成最终执行的SQL语句,最后由mybatis框架执行SQL并将结果映射为java对象并返回。

  3. 采用ORM(Object Relational Mappging对象关系映射)思想解决了实体和数据库映射的问题,对jdbc进行了封装,屏蔽了jdbc api底层访问细节,使我们不用与jdbc api打交道,就可以完成对数据库的持久化操作。


1.2 核心对象



  • 在使用MyBatis框架时,主要涉及两个核心对象:SqlSessionFactory和SqlSession,它们在MyBatis框架中起着至关重要的作用,图解如下,下面进行详解。





  1. SqlSessionFactory



    1. SqlSessionFactory是单个数据库映射关系经过编译后的内存镜像,主要作用是创建SqlSession。



    2. SqlSessionFactory是线程安全的,一旦被创建整个应用执行期间都会存在。如果多次的创建同一个数据库的SqlSessionFactory,那么数据库资源很容易被耗尽,因此在构建SqlSessionFactory实例时,一般使用单例模式。

      // 创建SqlSessionFactory代码
      InputStream inputStream = Resources.getResourceAsStream("配置文件位置");
      SqlSessionFactory sqlSessiOnFactory= new SqlSessionFactoryBuilder().build(inputStream);




  2. SqlSession



    1. SqlSession是应用程序与持久层之间执行交互操作的一个单线程对象,是线程不安全的。SqlSession使用完后,要及时关闭它。



    2. SqlSession方法如下(了解即可,IDEA中可以点击ctrl+鼠标左键查看)

      // 注:若使用mybatis的传统开发方式(即编写接口的实现类)需要用到以下方法,但不推荐使用此方式,推荐用xml或annotation
      public interface SqlSession extends Closeable {
      // statement是在配置文件中,
      select * from t_user






2 入门程序

-- SQL脚本如下
CREATE TABLE `t_user` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`birthday` datetime default NULL COMMENT '生日',
`sex` char(1) default NULL COMMENT '性别',
`address` varchar(256) default NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `t_user`(`id`,`username`,`birthday`,`sex`,`address`)
values (41,'张三','2018-02-27 17:47:08','男','北京'),
(42,'小明','2018-03-02 15:09:37','女','北京金燕龙'),
(43,'小明','2018-03-04 11:34:34','女','北京金燕龙'),
(45,'李四','2018-03-04 12:04:06','男','北京金燕龙'),
(46,'王五','2018-03-07 17:37:26','男','北京'),
(48,'赵六','2018-03-08 11:44:00','女','北京修正');

2.1 xml方式



  • 普通maven工程,结构图如下





  1. 依赖


    org.mybatis
    mybatis
    3.5.5


    mysql
    mysql-connector-java
    8.0.21


    log4j
    log4j
    1.2.17


    org.projectlombok
    lombok
    1.18.22



  2. 实体类

    package cn.pojo;
    import lombok.ToString;
    import java.util.Date;
    @ToString
    public class User {
    private Integer id;
    private String username;
    private Date birthday;
    private String six;
    private String address;
    }


  3. 持久层

    package cn.dao;
    import cn.pojo.User;
    import java.util.List;
    public interface UserDao {
    List findAll();
    /**
    * 注:在实际发开中,都是越简单越好,故不采用写Dao实现类的方式,使用xml或annotation都行。
    * 虽然不推荐写Dao实现类,但是mybatis是支持写实现类的。
    */
    }


  4. 配置

    # resources/log4j.properties,把下面内容直接粘贴过去即可
    # Set root category priority to INFO and its only appender to CONSOLE.
    #log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
    log4j.rootCategory=debug, CONSOLE, LOGFILE
    # Set the enterprise logger category to FATAL and its only appender to CONSOLE.
    log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
    # CONSOLE is set to be a ConsoleAppender using a PatternLayout.
    log4j.appender.COnSOLE=org.apache.log4j.ConsoleAppender
    log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
    log4j.appender.CONSOLE.layout.COnversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
    # LOGFILE is set to be a File appender using a PatternLayout.
    log4j.appender.LOGFILE=org.apache.log4j.FileAppender
    log4j.appender.LOGFILE.File=d:\axis.log
    log4j.appender.LOGFILE.Append=true
    log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
    log4j.appender.LOGFILE.layout.COnversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n



































  5. 运行

    package cn;
    import cn.dao.UserDao;
    import cn.pojo.User;
    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;
    import java.util.List;
    public class App {
    public static void main(String[] args) throws IOException {
    //1.读取配置文件
    InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    //2.创建SqlSessionFactory工厂
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
    //3.使用工厂生产SqlSession对象
    SqlSession session = factory.openSession();
    //4.使用SqlSession创建Dao接口的代理对象
    UserDao userDao = session.getMapper(UserDao.class);
    //5.使用代理对象执行方法
    List users = userDao.findAll();
    for (User user : users) {
    System.out.println(user);
    }
    //6.释放资源
    session.close();
    inputStream.close();
    }
    /**
    * 结果
    * User(id=41, username=张三, birthday=Tue Feb 27 17:47:08 CST 2018, six=null, address=北京)
    * User(id=42, username=小明, birthday=Fri Mar 02 15:09:37 CST 2018, six=null, address=北京金燕龙)
    * User(id=43, username=小明, birthday=Sun Mar 04 11:34:34 CST 2018, six=null, address=北京金燕龙)
    * User(id=45, username=李四, birthday=Sun Mar 04 12:04:06 CST 2018, six=null, address=北京金燕龙)
    * User(id=46, username=王五, birthday=Wed Mar 07 17:37:26 CST 2018, six=null, address=北京)
    * User(id=48, username=赵六, birthday=Thu Mar 08 11:44:00 CST 2018, six=null, address=北京修正)
    */
    }



2.2 annotation方式



  • 普通maven工程,结构图如下





  1. 依赖


    org.mybatis
    mybatis
    3.5.5


    mysql
    mysql-connector-java
    8.0.21


    log4j
    log4j
    1.2.17


    junit
    junit
    4.12


    org.projectlombok
    lombok
    1.18.22



  2. 实体类



    • 同 xml 方式实体类



  3. 持久层

    package cn.dao;
    import cn.pojo.User;
    import org.apache.ibatis.annotations.Select;
    import java.util.List;
    public interface UserDao {
    @Select("select * from t_user")
    List findAll();
    }


  4. 配置



    1. log4j.properties 日志配置同上面 xml 方式,略



    2. mybatis-config.xml 配置如下
























  5. 测试

    package cn.dao;
    import cn.pojo.User;
    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 org.junit.Test;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    public class UserDaoTest {
    @Test
    public void findAll() throws IOException {
    InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
    SqlSession session = factory.openSession();
    UserDao userDao = session.getMapper(UserDao.class);
    List users = userDao.findAll();
    for (User user : users) {
    System.out.println(user);
    }
    session.close();
    inputStream.close();
    }
    /**
    * 结果
    * User(id=41, username=张三, birthday=Tue Feb 27 17:47:08 CST 2018, six=null, address=北京)
    * User(id=42, username=小明, birthday=Fri Mar 02 15:09:37 CST 2018, six=null, address=北京金燕龙)
    * User(id=43, username=小明, birthday=Sun Mar 04 11:34:34 CST 2018, six=null, address=北京金燕龙)
    * User(id=45, username=李四, birthday=Sun Mar 04 12:04:06 CST 2018, six=null, address=北京金燕龙)
    * User(id=46, username=王五, birthday=Wed Mar 07 17:37:26 CST 2018, six=null, address=北京)
    * User(id=48, username=赵六, birthday=Thu Mar 08 11:44:00 CST 2018, six=null, address=北京修正)
    */
    }



3 增删改查

  1. SQL脚本同上面的入门程序,略



  2. #{}${} 的对比



























    #{}${}
    一个占位符一个sql串
    自动进行java类型和jdbc类型转换不进行jdbc类型转换
    防止sql注入无法防止sql注入
    可以接收简单类型值或pojo属性值,
    如果parameterType传输单个简单类型值,
    #{}括号中可以是value或其它名称。
    可以接收简单类型值或pojo属性值,
    如果parameterType传输单个简单类型值,
    ${}括号中只能是value


    1. #{}相当于JDBC中的"?",而 "#{id}"表示该占位符待接收参数的名称为id。

    2. 拼接sql串时若想防止sql注入,可用mysql中的concat()函数。eg. select * from t_customer where username like concat('%',#{value},'%')




3.1 xml方式



  • 普通maven工程,结构图如下



  • 整个项目基于上面入门程序的xml方式改造,因此下文仅展示不同部分的代码,相同部分略





  1. 实体类

    package cn.pojo;
    import lombok.Data;
    import java.util.Date;
    @Data
    public class User {
    // 特意加个前缀user于列名不同,主要是用于测试resultMap映射
    private Integer userId;
    private String userName;
    private String userAddress;
    private String userSex;
    private Date userBirthday;
    }

    package cn.pojo;
    import lombok.Data;
    @Data
    public class FindPojo {
    User user;
    }


  2. 持久层

    package cn.mapper;
    import cn.pojo.FindPojo;
    import cn.pojo.User;
    import java.util.List;
    /**
    * mapper层即持久层,与以前的dao层一样。
    * 也可以写dao.UserDao,配置文件写成UserDao.xml
    * 但是mybatis提供的是mapper标签,因此用mapper居多,
    * 也可以写成dao层,两者完全一样
    */
    public interface UserMapper {
    void addUser(User user);
    void deleteUser(Integer id);
    void updateUser(User user);
    //包装类参数(注意xml中文件参数写法)
    List findByPojo(FindPojo pojo);
    List findAll();
    }


  3. 配置





    INSERT INTO t_user (username, birthday, sex, address)
    VALUES (#{userName}, #{userBirthday}, #{userSex}, #{userAddress})




    DELETE
    FROM t_user
    WHERE id = #{id}


    UPDATE t_user
    SET username = #{userName},
    address = #{userAddress},
    sex = #{userSex},
    birthday = #{userBirthday}
    WHERE id = #{userId}


















  4. 测试

    package cn.mapper;
    import cn.pojo.FindPojo;
    import cn.pojo.User;
    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 org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Date;
    import java.util.List;
    public class UserMapperTest {
    /**
    * 注:增删改提交事务的方法都放在 @After public void destory()方法中
    * 别没看全以为不用提交事务!
    */
    private InputStream inputStream;
    private SqlSession sqlSession;
    private UserMapper userMapper;
    @Before
    public void init() throws IOException {
    inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
    sqlSession = factory.openSession();
    userMapper = sqlSession.getMapper(UserMapper.class);
    }
    @After
    public void destory() throws IOException {
    //释放资源前提交事务,写在destory()内可以减少代码冗余,免得都写
    sqlSession.commit();
    //6.释放资源
    sqlSession.close();
    inputStream.close();
    }
    @Test
    public void addUser() {
    User user = new User();
    user.setUserName("张良");
    user.setUserBirthday(new Date());
    user.setUserSex("男");
    user.setUserAddress("郑州");
    userMapper.addUser(user);
    }
    @Test
    public void deleteUser() {
    userMapper.deleteUser(48);
    }
    @Test
    public void updateUser() {
    User user = new User();
    user.setUserName("孙悟空");
    user.setUserBirthday(new Date());
    user.setUserSex("男");
    user.setUserAddress("水帘洞");
    user.setUserId(46);
    userMapper.updateUser(user);
    }
    @Test
    public void findByPojo() {
    FindPojo pojo = new FindPojo();
    User user = new User();
    user.setUserName("%小%");
    pojo.setUser(user);
    List users = userMapper.findByPojo(pojo);
    System.out.println(users);
    }
    @Test
    public void findAll() {
    List users = userMapper.findAll();
    for (User user : users) {
    System.out.println(user);
    }
    }
    }



3.2 annotation方式


常用注解




































































序号注解说明
1@Insert
2@Delete
3@Update
4@Select
5@Result实现结果集封装
6@Results可以与@Result一起使用,封装多个结果集
7@ResultMap实现引用@Results定义的封装
8@One实现一对一结果集封装
9@Many实现一对多结果集封装
10@SelectProvider实现动态SQL映射
11@CacheNamespace实现注解二级缓存的使用

复杂注解映射说明




  1. @Results注解代替的是标签,该注解可以使用单个@Result,也可以使用@Result集合。

    1. 样例: @Results(@Result()) 或 @Results({@Result(),@Result()})



  2. @Result注解代替的是标签,属性如下

    1. id : 是否是主键字段

    2. property : 需要装配的属性名

    3. column : 数据库的列名

    4. one : 需要使用@One注解 ( @Result(One=@One) )

    5. many : 需要使用@Many注解 ( @Result(many = @Many) )



  3. @One注解(一对一)代替的是标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。

    1. 其select属性指定用来多表查询的sqlMapper。

    2. 样例: @Result(property="",column=" ",One=@One(select="")



  4. @Many注解(一对多)代替的是标签,是多表查询的关键,在注解中用来指定子查询返回对象集合。

    1. 注意:聚集元素用来处理“一对多”的关系。需要指定映射的Java实体类的属性,属性的javaType(一般为ArrayList)但是注解中可以不定义。

    2. 样例: @Result(property="",column="",many=@Many(select=""))




代码




  • 普通maven工程,结构图如下。



  • 整个项目基于上面增删改查xml方式改造,因此下文仅展示不同部分的代码,相同部分略





  1. 持久层

    package cn.mapper;
    import cn.pojo.FindPojo;
    import cn.pojo.User;
    import org.apache.ibatis.annotations.*;
    import java.util.List;
    /**
    * 个人建议:短sql用注解,太长的sql写在xml文件中,否则方法上一大堆太丑
    * 注:定义了@Results(id = "userMap")之后,以后可以用@ResultMap("userMap")进行引用,
    * 例如下面的findByPojo方法可以不写SQL别名,添加注解@ResultMap("userMap")即可
    * 定义@Results的方法(即findAll方法)无需使用,若是加上会编译报错!!!
    */
    public interface UserMapper {
    @Insert("INSERT INTO t_user (username, birthday, sex, address)" +
    "VALUES (#{userName}, #{userBirthday}, #{userSex}, #{userAddress})")
    void addUser(User user);
    @Delete("DELETE FROM t_user WHERE id = #{id}")
    void deleteUser(Integer id);
    @Update("UPDATE t_user SET username = #{userName}, address = #{userAddress}," +
    "sex = #{userSex}, birthday = #{userBirthday} WHERE id = #{userId}")
    void updateUser(User user);
    @Select("SELECT ID AS userId, USERNAME AS userName, BIRTHDAY AS userBirthday," +
    "SEX AS userSex, ADDRESS AS userAddress FROM t_user WHERE USERNAME LIKE #{user.userName}")
    List findByPojo(FindPojo pojo); // 包装类参数
    @Select("SELECT * FROM t_user")
    @Results(id = "userMap",
    value = {
    @Result(property = "userId", column = "id"),
    @Result(property = "userName", column = "username"),
    @Result(property = "userAddress", column = "address"),
    @Result(property = "userSex", column = "sex"),
    @Result(property = "userBirthday", column = "birthday")
    }
    )
    List findAll();
    }


  2. 配置 mybatis-config.xml






  3. 测试



    • 同上面增删改查xml方式代码,略。






推荐阅读
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
author-avatar
挚远-十年
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有