MyBatis增删改查和配置文件

MyBatis增删改查

MyBatis新增

新增用户
  1. 持久层接口添加方法

    java 复制代码
    void add(User user);
  2. 映射文件添加标签

    xml 复制代码
    <insert id="add" parameterType="com.mybatis.pojo.User">
       insert into user(username,sex,address) values(# {username},# {sex},# {address})
    </insert>
  3. 编写测试方法

    java 复制代码
    @Test
    public void testAdd() throws Exception {
      InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
      SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
      SqlSessionFactory factory = builder.build(is);
      SqlSession session = factory.openSession();
      UserMapper userMapper = session.getMapper(UserMapper.class);
      User user = new User("程序员", "男", "上海");
      userMapper.add(user);
      // 提交事务
      session.commit();
      session.close();
      is.close();
    }

注意:

  1. 当接口方法的参数类型为POJO类型时,SQL语句中绑定参数时使用# {POJO的属性名}即可。
  2. MyBatis事务默认手动提交,所以在执行完增删改方法后,需要手动调用SqlSession对象的事务提交方法,否则数据库将不发生改变。

MyBatis修改

优化测试类

我们发现MyBatis的测试方法在操作数据库前都需要获取代理对象,操作数据库后都需要释放资源,可以利用Junit的前置后置方法,优化测试类代码。

java 复制代码
InputStream is = null;
SqlSession session = null;
UserMapper userMapper = null;


@Before
public void before() throws IOException {
  // (1)读取核心配置文件
  is = Resources.getResourceAsStream("SqlMapConfig.xml");
  // (2)创建SqlSessionFactoryBuilder对象
  SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
  // (3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
  SqlSessionFactory factory = builder.build(is);
  // (4)SqlSessionFactory对象获取SqlSession对象
  session = factory.openSession();
  // (5)获取代理对象
  userMapper = session.getMapper(UserMapper.class);
}


@After
public void after() throws IOException {
  // 释放资源
  session.close();
  is.close();
}

这样Junit就会自动执行获取代理对象和释放资源的方法。

修改用户
  1. 持久层接口添加方法

    java 复制代码
    void update(User user);
  2. 映射文件添加标签

    xml 复制代码
    <update id="update" parameterType="com.mybatis.pojo.User">
       update user
       set username = #{username},
       sex    = #{sex},
       address=#{address}
       where id = #{id}
    </update>
  3. 编写测试方法

    java 复制代码
    @Test
    public void testUpdate(){
      User user = new User(8,"程序员1","女","深圳");
      userMapper.update(user);
      session.commit();
    }

MyBatis删除、根据Id查询

删除用户
  1. 持久层接口添加方法

    java 复制代码
    void delete(int userId);
  2. 映射文件添加标签

    xml 复制代码
    <delete id="delete" parameterType="int">
       delete from user where id = #{id}
    </delete>

    注:当方法的参数类型是简单数据类型时,#{}中可以写任意名称

    • 简单数据类型:基本数据类型、字符串等
  3. 编写测试方法

    java 复制代码
    @Test
    public void testDelete(){
      userMapper.delete(8);
      session.commit();
    }
根据ID查询用户
  1. 持久层接口添加方法

    java 复制代码
    User findById(int userId);
  2. 映射文件添加标签

    xml 复制代码
    <select id="findById" parameterType="int" resultType="com.mybatis.pojo.User">
       select * from user where id = #{userId}
    </select>
  3. 编写测试方法

    java 复制代码
    @Test
    public void testFindById(){
      User user = userMapper.findById(1);
      System.out.println(user);
    }

MyBatis模糊查询

使用#定义参数
  1. 持久层接口添加方法

    java 复制代码
    List<User> findByNameLike(String username);
  2. 映射文件添加标签

    xml 复制代码
    <select id="findByNameLike" parameterType="string" resultType="com.mybatis.user.User">
       select * from user where username like #{name}
    </select>
  3. 编写测试方法

    java 复制代码
    @Test
    public void testFindByNameLike(){
      List<User> users = userMapper.findByNameLike("%王%");
      for (User user:users){
        System.out.println(user);
       }
    }

我们看到在映射文件中,parameterType的值为string而没有写java.lang.String,这是为什么呢?

  • 参数/返回值类型为基本数据类型/包装类/String等类型时,我们可以写全类名,也可以写别名。
数据类型 别名
byte _byte
long _long
short _short
int _int
int _integer
double _double
float _float
boolean _boolean
String string
Byte byte
Long long
Short short
Integer int/integer
Double double
Float float
Boolean boolean
Date date
BigDecimal decimal/bigdecimal
Object object
Map map
HashMap hashmap
List list
ArrayList arraylist
Collection collection
Iterator iterator
使用$定义参数

模糊查询如果不想在调用方法时参数加%,可以使用拼接参数的方式设置Sql:

xml 复制代码
<select id="findByUsernameLike" parameterType="string" resultType="com.mybatis.pojo.User">
   select * from user where username like '%${value}%'
</select>

测试方法写法如下:

java 复制代码
@Test
public void testFindByNameLike(){
  List<User> users = userMapper.findByUsernameLike("张三");
  users.forEach(System.out::println);
}

#和$的区别:

  1. #表示sql模板的占位符,$表示将字符串拼接到sql模板中。
  2. #可以防止sql注入,一般能用#就不用$。
  3. ${}内部的参数名必须写value。
使用< bind>定义参数

如果使用#还不想在调用方法的参数中添加%,可以使用<bind>标签,<bind>标签允许我们在 Sql语句以外创建一个变量,并可以将其绑定到当前的Sql语句中。用法如下:

xml 复制代码
<select id="findByUsernameLike" parameterType="string" resultType="com.mybatis.pojo.User">
  <bind name="likeName" value="'%'+username+'%'"/>
   select * from user where username like #{likeName}
</select>

测试方法写法如下:

java 复制代码
@Test
public void testFindByNameLike(){
  List<User> users = userMapper.findByUsernameLike("张三");
  users.forEach(System.out::println);
}

MyBatis分页查询

分页查询时,Sql语句使用limit关键字,需要传入开始索引和每页条数两个参数。MyBatis的多参数处理有以下方式:

顺序传参

Sql中的参数使用arg0,arg1...或param1,param2...表示参数的顺序。此方法可读性较低,在开发中不建议使用。

  1. 持久层接口方法

    java 复制代码
    /**
       * 分页查询
       * @param startIndex 开始索引
       * @param pageSize 每页条数
       * @return
       */
    List<User> findPage(int startIndex,int pageSize);
  2. 映射文件

    xml 复制代码
    <select id="findPage" resultType="com.mybatis.mapper.User">
       select * from user limit #{arg0},#{arg1}
    </select>
    
    
    <select id="findPage" resultType="com.mybatis.mapper.User">
       select * from user limit #{param1},#{param2}
    </select>
  3. 测试类

    java 复制代码
    @Test
    public void testFindPage(){
      List<User> users = userMapper.findPage(0,3);
      users.forEach(System.out::println);
    }
@Param传参

在接口方法的参数列表中通过@Param定义参数名称,在Sql语句中通过注解中所定义的参数名称指定参数位置。此方式参数比较直观的,推荐使用。

  1. 持久层接口方法

    java 复制代码
    List<User> findPage1(@Param("startIndex") int startIndex, @Param("pageSize")int pageSize);
  2. 映射文件

    xml 复制代码
    <select id="findPage1" resultType="com.mybatis.mapper.User">
      select * from user limit #{startIndex},#{pageSize}
    </select>
  3. 测试类

    java 复制代码
    @Test
    public void testFindPage1(){
      List<User> users = userMapper.findPage1(3,3);
      users.forEach(System.out::println);
    }
POJO传参

自定义POJO类,该类的属性就是要传递的参数,在SQL语句中绑定参数时使用POJO的属性名作为参数名即可。此方式推荐使用。

  1. 自定义POJO

    java 复制代码
    public class PageQuery {
      private int startIndex;
      private int pageSize;
        // 省略getter/setter/构造方法
    }
  2. 持久层接口方法

    java 复制代码
    List<User> findPage2(PageQuery pageQuery);
  3. 映射文件

    xml 复制代码
    <select id="findPage2" resultType="com.mybatis.pojo.User" parameterType="com.mybatis.pojo.PageQuery">
       select * from user limit #{startIndex},#{pageSize}
    </select>
  4. 测试类

    java 复制代码
    @Test
    public void testFindPage2(){
      PageQuery pageQuery = new PageQuery(3, 3);
      List<User> users = userMapper.findPage2(pageQuery);
      users.forEach(System.out::println);
    }
Map传参

如果不想自定义POJO,可以使用Map作为传递参数的载体,在SQL语句中绑定参数时使用Map的Key作为参数名即可。此方法推荐使用。

  1. 持久层接口方法

    java 复制代码
    List<User> findPage3(Map<String,Object> params);
  2. 映射文件

    xml 复制代码
    <select id="findPage3" resultType="com.mybatis.pojo.User" parameterType="map">
       select * from user limit #{startIndex},#{pageSize}
    </select>
  3. 测试类

    java 复制代码
    @Test
    public void testFindPage3(){
      Map<String,Object> params = new HashMap();
      params.put("startIndex",0);
      params.put("pageSize",4);
      List<User> users = userMapper.findPage3(params);
      users.forEach(System.out::println);
    }

MyBatis聚合查询、主键回填

查询用户总数
  1. 持久层接口方法

    java 复制代码
    int findCount();
  2. 映射文件

    xml 复制代码
    <select id="findCount" resultType="int">
       select count(id) from user
    </select>
  3. 测试类

    java 复制代码
    @Test
    public void testFindCount(){
      System.out.println(userMapper.findCount());
    }
主键回填

有时我们需要获取新插入数据的主键值。如果数据库中主键是自增的,这时我们就需要使用MyBatis的主键回填功能。

  1. 持久层接口方法

    java 复制代码
    void add(User user);
  2. 映射文件

    xml 复制代码
    <insert id="add" parameterType="com.mybatis.user.User">
      <!-- keyProperty:主键属性名,keyColumn:主键列名,resultType:主键类型,order:执行时机 -->
      <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
         SELECT LAST_INSERT_ID();
      </selectKey>
       insert into user(username,sex,address) values(#{username},#{sex},#{address})
    </insert>

    SELECT LAST_INSERT_ID():查询刚刚插入的记录的主键值,只适用于自增主键,且必须和insert语句一起执行。

  3. 测试类

    java 复制代码
    @Test
    public void testAdd(){
      User user = new User("×××", "男", "北京");
      userMapper.add(user);
      session.commit();
      System.out.println(user.getId());
    }

MyBatis配置文件

< properties>标签

MyBatis配置文件结构:

xml 复制代码
-configuration
    -properties(属性)
        -property
    -settings(全局配置参数)
        -setting
    -plugins(插件)
        -plugin
    -typeAliases(别名)
        -typeAliase
        -package
    -environments(环境)
        -environment
            -transactionManager(事务管理)
            -dataSource(数据源)
    -mappers(映射器)
        -mapper
        -package
properties

属性值定义。properties标签中可以定义属性值,也可以引入外部配置文件。无论是内部定义还是外部引入,都可以使用 ${name} 获取值。

例如:我们可以将数据源配置写到外部的db.properties中,再使用properties标签引入外部配置文件,这样可以做到动态配置数据源。

  1. 编写db.properties

    properties 复制代码
    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mybatis
    jdbc.username=root
    jdbc.password=root
  2. 在配置文件中引入db.properties

    xml 复制代码
    <properties resource="db.properties"></properties>
    
    <environments default="mysql">
      <environment id="mysql">
        <transactionManager type="JDBC"></transactionManager>
        <dataSource type="POOLED">
          <property name="driver" value="${jdbc.driver}"/>
          <property name="url" value="${jdbc.url}"/>
          <property name="username" value="${jdbc.username}"/>
          <property name="password" value="${jdbc.password}"/>
        </dataSource>
      </environment>
    </environments>

当然我们也可以将数据源数据通过<properties>配置到MyBatis配置文件内,但这样做没什么意义。

xml 复制代码
<properties>
  <property name="jdbc.driver" value="com.mysql.jdbc.Driver"></property>
  <property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatis"></property>
  <property name="jdbc.username" value="root"></property>
  <property name="jdbc.password" value="root"></property>
</properties>


<environments default="mysql">
  <environment id="mysql">
    <transactionManager type="JDBC"></transactionManager>
    <dataSource type="POOLED">
      <property name="driver" value="${jdbc.driver}"/>
      <property name="url" value="${jdbc.url}"/>
      <property name="username" value="${jdbc.username}"/>
      <property name="password" value="${jdbc.password}"/>
    </dataSource>
  </environment>
</environments>

< settings>标签

<settings>是配置MyBatis运行时的一些行为的,例如缓存、延迟加载、命名规则等一系列控制性参数。后期我们会使用该标签配置缓存和延迟加载等。

< plugins>标签

<plugins>是配置MyBatis插件的。插件可以增强MyBatis功能,比如进行sql增强,打印日志,异常处理等。后期我们会使用该标签配置分页插件。

< typeAliases>标签

MyBatis对常用类有默认别名支持,比如java.lang.Stirng的别名为string。除此之外,我们也可以使用<typeAliases>设置自定义别名。

为一个类配置别名
xml 复制代码
<typeAliases>
    <typeAlias type="全类名" alias="别名"></typeAlias>
</typeAliases>

此时我们即可在映射文件中使用自定义别名,如:

  1. 配置文件:

    xml 复制代码
    <typeAliases>
        <typeAlias type="com.mybatis.pojo.User" alias="User">     </typeAlias>
    </typeAliases>
  2. 映射文件:

    xml 复制代码
    <select id="findAll" resultType="User">
       select * from user
    </select>
为一个所有包下的所有类配置别名
xml 复制代码
<typeAliases>
  <package name="包名"></package>
</typeAliases>

此时该包下的所有类都有了别名,别名省略包名,和类名相同。如:

  1. 配置文件:

    xml 复制代码
    <typeAliases>
      <package name="com.mybatis.pojo"></package>
    </typeAliases>
  2. 映射文件:

    xml 复制代码
    <select id="findPage2" resultType="User" parameterType="PageQuery">
       select * from user limit #{startIndex},#{pageSize}
    </select>

< environments>标签

<environments>可以为MyBatis配置数据环境。

事务管理
xml 复制代码
<environments default="mysql">
  <environment id="mysql">
    <!-- JDBC:使用JDBC的提交和回滚 MANAGED:不做事务处理-->
    <transactionManager type="JDBC"></transactionManager>
  </environment>
</environments>
连接池
xml 复制代码
<environments default="mysql">
  <environment id="mysql">
    <transactionManager type="JDBC"></transactionManager>
    <!-- 连接池设置 -->
    <dataSource type="POOLED">
      <!-- 数据源设置... -->
    </dataSource>
  </environment>
</environments>

dataSource的type属性:

  • POOLED:使用连接池管理连接,使用MyBatis自带的连接池。
  • UNPOOLED:不使用连接池,直接由JDBC连接。
  • JNDI:由JAVAEE服务器管理连接,如果使用Tomcat作为服务器则使用Tomcat自带的连接池管理。

< mappers>标签

<mappers>用于注册映射文件或持久层接口,只有注册的映射文件才能使用,共有四种方式都可以完成注册:

  1. 使用相对路径注册映射文件

    xml 复制代码
    <mappers>
     <mapper resource="com/mybatis/mapper/UserMapper.xml"/>
    </mappers>
  2. 使用绝对路径注册映射文件

    xml 复制代码
    <mappers>  
      <mapper url="file:///C:\Users\a\IdeaProjects\mybatiscase\mybatisDemo1\src\main\resources\com\mybatis\mapper\UserMapper.xml"/> 
    </mappers>
  3. 注册持久层接口

    xml 复制代码
    <mappers>  
      <mapper class="com.mybatis.mapper.UserMapper"/> 
    </mappers>
  4. 注册一个包下的所有持久层接口

    xml 复制代码
    <mappers>
      <package name="com.mybatis.mapper"/>
    </mappers>
相关推荐
NCIN EXPE2 小时前
redis 使用
数据库·redis·缓存
MongoDB 数据平台2 小时前
为编码代理引入 MongoDB 代理技能和插件
数据库·mongodb
极客on之路2 小时前
mysql explain type 各个字段解释
数据库·mysql
代码雕刻家2 小时前
MySQL与SQL Server的基本指令
数据库·mysql·sqlserver
lThE ANDE2 小时前
开启mysql的binlog日志
数据库·mysql
yejqvow122 小时前
CSS如何控制placeholder文字的颜色_使用--placeholder伪元素
jvm·数据库·python
oLLI PILO3 小时前
nacos2.3.0 接入pgsql或其他数据库
数据库
m0_743623923 小时前
HTML怎么创建多语言切换器_HTML语言选择下拉结构【指南】
jvm·数据库·python
pele3 小时前
Angular 表单中基于下拉选择动态启用字段必填校验的完整实现
jvm·数据库·python