Mybatis入门

news2024/11/25 15:33:59

 详细的Mybatis介绍/使用,可以访问:

  地址:mybatis – MyBatis 3 | 简介

目录

一、Mybatis介绍

二、依赖

三、什么是rowmapper

四、Mybatis demo 演示

4.1 背景

4.2 JDBC执行sql的流程 &Mybatis 关键要素

4.3  项目的整体结构:

4.4 Mybatis XML简单配置

4.5  数据库表及对应的实体类

4.6 mapper(封装sql)

4.7 运行入口

五、Mybatis 总配置

5.1 多数据库配置

5.2 数据库表中的字段与自定义类的属性对应关系。

5.3 xml配置文件,使用变量properties

六、sql注解版 mapper

七、xml 配置 mapper ,增删改查

7.1 xml 配置 mapper ,中sql 参数传递&查

7.1.1 通过变量传递sql参数&查

7.1.2 通过对象传递sql参数

7.2 增删改

八、注解版mapper ,增删改查

九、获取自增主键的值

9.1 注解mapper ,获取自增主键的值

9.2 xml mapper ,获取自增主键的值

十、动态sql

10.1 背景

10.2 xml mapper动态sql

10.3 注解版mapper 动态sql

十一、批量插入

11.1 xml 批量插入

11.2 sql注解批量插入

十二、批量删除

12.1 xml 批量删除

12.2 sql注解删除


一、Mybatis介绍

MyBatis 可能是当前互联网公司数据库持久层框架的首页。为啥?因为Mybatis比JDBC方便。

1、MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。

2、MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。 

二、依赖

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.20</version>
        </dependency>

三、什么是rowmapper

这里强行插一下rowmapper的解释,因为我总是忘了它是干嘛的。

row,行。数据库的中一行数据,也就是一条数据。

mapper,映射。将一条数据,组装成一个实体类。

我们在执行查询sql的时候,返回结果是以什么形式存在的呢?我们将返回结果组装成了我们自定义类的实例。

rowmapper里面,就是写的我们具体组装的逻辑。如下

        List<TbUser> tbUsers1 = testRowMapper(sql, null, new RowMapper<TbUser>() {

            // 重写map
            @Override
            public TbUser map(ResultSet rs) throws SQLException {
                TbUser tbUser = new TbUser();
                // 给tbUser赋值
                tbUser.setId(rs.getLong(1));
                tbUser.setName(rs.getString(2));
                return tbUser;
            }
        });

传参中,需要传一个rowmapper,mapper就是我们具体将一条数据封装到我们自定义类里的详细逻辑。(我们将返回结果/一条数据,)组装到了我们自定义类里。

return的时候,不是return的一大堆字符串,而是一个对象。

四、Mybatis demo 演示

4.1 背景

表MyStudent

CREATE TABLE `MyStudent` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(64) NOT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=201200000 DEFAULT CHARSET=utf8;

在表里插入数据

insert into MyStudent values(201215121,'李勇',20),(201215122,'刘晨',19),(201215123,'王敏',18);

 执行查询SQL,select * from MyStudent,收集查询结果。

4.2 JDBC执行sql的流程 &Mybatis 关键要素

当我们使用jdbc 执行sql时,流程是这样的

1、配置数据库的相关信息(url、username、password)等

2、与数据库建立连接

3、执行sql

4、将执行sql的返回结果进行封装,返回。

使用 Mybatis 执行sql,这几个关键步骤都是要有的,但是具体形式是不一样的。

1、XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源

2、mapper,这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息。(啥是映射?就是将sql执行后,得到的数据,组装成我们自定义的类的实例)。

我对mapper的理解,就是1、封装要执行的sql 2、将封装好的sql与mapper的类的方法做关联。

当具体要执行sql的时候,我们调用mapper的某个方法,这个方法的本质就是去调用了我们封装的sql。

4.3  项目的整体结构:

4.4 Mybatis XML简单配置

XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。后面会再探讨 XML 配置文件的详细内容,这里先给出一个简单的示例:

xml模版:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <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>
  </environments>
  <mappers>
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>

手动将模版中数据库相关信息,替换成自己的数据库信息。我们需要修改2个点。

1、其中<dataSource type="POOLED"> 内,配置的是数据库连接信息。

2、<mappers> mappers 元素则包含了一组映射器(mapper),这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息。(啥是映射?就是将sql执行后,得到的数据,组装成我们自定义的类的实例)

在resources文件夹下,新建mytatis-config.xml文件。配置我们自己的相关信息。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://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.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://124.70.87.136/chen?useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="$123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
    </mappers>
</configuration>

注意:我们在写url时,url中符号&在xml文件中,需要转义,使用&amp;

如原来url

jdbc:mysql://124.70.87.16/chen?useUnicode=true&characterEncoding=UTF-8

转义后:

jdbc:mysql://124.70.87.16/chen?useUnicode=true&amp;characterEncoding=UTF-8

4.5  数据库表及对应的实体类

在我们的项目代码中,要有一个对应的类。MyStudent类

设置无参构造器、所有参数的构造器

package beans;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class MyStudent {
    private long id;
    private String name;
    private int age;

    public MyStudent(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

4.6 mapper(封装sql)

<mappers> mappers 元素则包含了一组映射器(mapper),这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息。(啥是映射?就是将sql执行后,得到的数据,组装成我们自定义的类的实例)

我对mapper的理解,就是1、封装要执行的sql 2、将封装好的sql与mapper的类的方法做关联。

当具体要执行sql的时候,我们调用mapper的某个方法,这个方法的本质就是去调用了我们封装的sql。

我们执行的是select * 的sql语句,返回结果是一个list。

编写mapper接口----MyStudentMapper(里面就是将sql封装成了方法)

package mapper;

import beans.MyStudent;

import java.util.List;

public interface MyStudentMapper {
    List<MyStudent> findAll();
    MyStudent findById(long id);

}

然后在MyStudentMapper.xml中,配置MyStudentMapper接口中的sql相关信息

MyStudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace 与mapper接口的全类名保持一致-->
<mapper namespace="mapper.MyStudentMapper">
    <!--id要和mapper接口的方法名保持一致 -->
    <!-- resultType 与sql返回值对应的类的全类名保持一致-->
    <select id="findAll" resultType="beans.MyStudent">
        select * from MyStudent
    </select>
    <select id="findById" resultType="beans.MyStudent">
        select * from MyStudent where id = #{id}
    </select>
</mapper>

解释:

1、namespace 与mapper接口的全类名保持一致。这样将来调用mapper类方法的时候,才能找我我们这个映射

2、id要和mapper接口的方法名保持一致,这样将来调用mapper类方法的时候,才能找我我们这个方法

3、resultType 与sql返回值对应的类的全类名保持一致。这样才能将返回结果组装成我们自定义的实体类。(这里是通过反射实现的,通过类名,得到实例)

4、里面有具体的sql语句。select * from MyStudent

5、sql中的参数传递,使用#{xx}

4.7 运行入口

app

package main;

import beans.MyStudent;
import mapper.MyStudentMapper;
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 {
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        // 选择不同的数据库,指定数据库
        // SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in,"test");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 得到MyStudent表的mapper    
        MyStudentMapper myStudentMapper = sqlSession.getMapper(MyStudentMapper.class);
        // 调用mapper的方法
        List<MyStudent> all = myStudentMapper.findAll();
        System.out.println("all = " + all);
        MyStudent byId = myStudentMapper.findById(201215121);
        System.out.println("byId = " + byId);
        sqlSession.close();



    }
}

解释:

1、连接数据库,建立连接。(读取数据库配置文件,然后建立连接)

        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        // 选择不同的数据库,指定数据库
        // SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in,"test");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        SqlSession sqlSession = sqlSessionFactory.openSession();

2、(通过mapper)执行sql

// 得到MyStudent表的mapper    
MyStudentMapper myStudentMapper = sqlSession.getMapper(MyStudentMapper.class);
// 调用mapper的方法
        List<MyStudent> all = myStudentMapper.findAll();

3、关闭连接,千万别忘了关闭连接

sqlSession.close();

五、Mybatis 总配置

我们接着第四节讲。

5.1 多数据库配置

数据库连接,在mybatis-config.xml中,进行配置。

1、修改默认库

同一个库,有一个开发库,一个测试库。如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!-- 开启自动驼峰命名-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://124.70.87.136/chen?useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
        <environment id="test">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://124.70.87.136/chen?useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/MyStudentMapper.xml"/>
    </mappers>
</configuration>

 id就是数据库的名字,

<environments default="development">

设置,默认使用的数据库。可以更换成test库。

则我们在生成SqlSessionFactory的时候,生成的就是我们默认的那个数据库。

        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        // 选择不同的数据库,指定数据库
        // SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in,"test");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);

2、在生成SqlSessionFactory的时候,指定对应的数据库

我们不同的业务模块,连接的是不同的数据库。在生成SqlSessionFactory的时候,指定对应的数据库id。

        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        // 选择不同的数据库,指定数据库
         SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in,"test");

5.2 数据库表中的字段与自定义类的属性对应关系。

在第四节中,数据库的表。

 

 数据库中的列名,与我们的自定义类属性名,一摸一样。这样框架就会自动的把数据给我们组装成一个实体类。

那我们表的列名与类的属性名称不一致,咋整?

情况一:开启驼峰命名自动映射

数据库命名与java命名规范是不一致的。

如,Your Student表,列名为下划线,user_id

 但是依照我们java命名规范,对应的实体类属性为驼峰格式,userId,userName。

package beans;

import lombok.Data;

@Data
public class YourStudent {
    private long userId;
    private String userName;
    private int userAge;
}

两边列名是不一致的。我们可以在Mybatis的总配置文件mybatis-config.xml中,开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。

mapUnderscoreToCamelCase是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。

 在mybatis-config.xml中,配置setting模块就好。

情况二:表的列名与自定义类的属性名称不一致,且也不是驼峰映射的情况。

如表中的列名,id 对应 类中的myId,name对应类中的designation。

我们需要手动的,去写列名与类属性名的一一对应关系。应该去哪里写呢?

正常情况下,这个映射实在row mapper里完成的。mybatis里的mapper,是一个xml配置文件。

我们需要去MyStudentMapper.xml 中配置。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="mapper.YourStudentMapper">
    <resultMap id="yourStudent" type="beans.YourStudent">
        <id column="id" property="myId"/>
        <result column="name" property="designation"/>
        <result column="age" property="year"/>
    </resultMap>

    <select id="findAll" resultMap ="yourStudent">
        select * from MyStudent
    </select>
</mapper>

 在resultMap中,编写列名与属性名的映射关系。

<resultMap id,这里的id是这个Map的名称,可以随意命名。

type=,写的对应的实体类的全类名

<id /> <result /> 中,写的具体映射关系,column表的列名,property实体类的属性名。

<id /> 表的主键,<result /> 表中普通的列。

注意,写完Map后,写到sql语句的resultMap上。注意(这里是resultMap,不是resultType=)

5.3 xml配置文件,使用变量properties

方式一:在xml中设置变量property (这种方式不常用。)

在 <properties> 中,设置变量,引用变量时,${xxx}

方式二:在xml配置文件中,引入数据库配置文件

我们习惯性的将数据库配置mysql.properties中。

mysql.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://124.70.87.136/chen?useUnicode=true&characterEncoding=UTF-8
userName=root
password=123456

然后在mybatis-config.xml配置文件中,引入mysql.properties。

然后设置变量。

六、sql注解版 mapper

以上,我们讲的使用mapper来构造执行sql语句的方法,由2部分组成。

1部分是接口,里面有用户行为的方法

2部分就是xml的mapper配置文件,里面写了具体执行的sql,以及对应的类,类的方法,返回数据类型。

然后在mybatis主配置文件mybatis-config.xml中,mappers模块下,配置这个我们mapper xml文件的路径。

mapper注解版,就是讲1与2,合二为一。我们在接口的方法中,通过注解,来写对应的sql。

举例,上面那个查询全部的行为。

package mapper;

import beans.MyStudent;
import org.apache.ibatis.annotations.Select;

import java.util.List;

public interface MyStudentMapper {
    @Select("select * from MyStudent")
    List<MyStudent> findAll();

}

我们只需要在mapper接口,对应的行为上,注解对应的sql语句就可以了。

这样,类方法与sql对应的关系、sql返回的数据类型,框架都可以识别到,不需要我们再去xml文件中配置了。

然后我们再修改mybatis主配置文件mybatis-config.xml中,mappers模块下,将原来的resource=xml的路径,改成class = 接口的全类名,这样我们就可以找到对应的接口了。

当我们使用xml 配置mapper 时,有多个xml文件时,需要配置多个xml文件。

当我们使用注解接口时,有多个接口,也要分别写多个接口的class。

 <mapper class="mapper.MyStudentMapper" />

我们还可以写这些接口所在的包,框架会去扫描包下所有的接口。

        <package name="mapper"/>
    <mappers>
        <!--<mapper resource="mapper/MyStudentMapper.xml"/> -->
        <!--<mapper class="mapper.MyStudentMapper" /> -->
        <package name="mapper"/>
    </mappers>

项目结构:

七、xml 配置 mapper ,增删改查

7.1 xml 配置 mapper ,中sql 参数传递&查

7.1.1 通过变量传递sql参数&查

1、在接口,有三个方法,分别需要传0个,1个,2个参数。

package mapper;

import beans.MyStudent;

import java.util.List;

public interface MyStudentMapper {
    List<MyStudent> findAll();
    MyStudent findById(long id);
    MyStudent findByName(String name,int age);
    
}

2、对应的xml配置,sql 参数

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace 与mapper接口的全类名保持一致-->
<mapper namespace="mapper.MyStudentMapper">
    <!--id要和mapper接口的方法名保持一致 -->
    <!-- resultType 与sql返回值对应的类的全类名保持一致-->
    <select id="findAll" resultType="beans.MyStudent">
        select * from MyStudent
    </select>

    <select id="findById" resultType="beans.MyStudent">
        select * from MyStudent where id = #{id}
    </select>

    <select id="findByName" resultType="beans.MyStudent">
        select * from MyStudent where name = #{name} and age = #{age}
    </select>
</mapper>

规则:

1、方法中,只需要一个参数时,sql语句中的变量名,可以任意命名。

如 id= #{id},可以任意命名 id= #{abcd},

2、方法中,需要多个参数时,sql语句中的变量名,需要与方法中的变量名保持一致。

如在方法中,

    MyStudent findByName(String name,int age);

则sql语句中的变量就要为 #{name} #{age}

select * from MyStudent where name = #{name} and age = #{age}

如果想要sql语句中的变量,与方法中的变量名称不一致,我们需要在方法中使用@Parm注解,来指定sql中的变量名称。

public interface MyStudentMapper {
    List<MyStudent> findAll();
    MyStudent findById(long id);
    MyStudent findByName(@Param("myName") String name, @Param("myAge") int age);

}

方法中的变量name 对应sql中的myName变量

    <select id="findByName" resultType="beans.MyStudent">
        select * from MyStudent where name = #{myName} and age = #{myAge}
    </select>

7.1.2 通过对象传递sql参数

sql中,我们需要传递多个参数。我们可以new一个对象,然后传递这个对象。

接口的方法,传参为一个对象

具体的sql语句中,还是一个个变量,系统会去我们传递的对象中,找对应的属性,来填充sql中的变量。

举例:

MyStudent实体类,有三个属性,我们根据name、age这两个属性去做查询。

先改造MyStudent,给它一个无参构造器和name、age这两个属性的构造器。

package beans;

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class MyStudent {
    private long id;
    private String name;
    private int age;

    public MyStudent(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

然后在接口中,新增一个传参为MyStudent实体类的方法。

MyStudent findByObject(MyStudent myStudent);

public interface MyStudentMapper {
    List<MyStudent> findAll();
    MyStudent findById(long id);
    MyStudent findByName(@Param("myName") String name, @Param("myAge") int age);
    MyStudent findByObject(MyStudent myStudent);
}

在mapper xml中配置这个方法

    <select id="findByObject" resultType="beans.MyStudent" parameterType="beans.MyStudent">
        select * from MyStudent where name = #{name} and age = #{age}
    </select>

parameterType="beans.MyStudent" ,传参对象的类型

name = #{name} and age = #{age},#{name} 会去对象中,匹配属性。

方法使用,我们在调用这个方法时,直接传一个对象就好了。

        MyStudent byObject = myStudentMapper.findByObject(new MyStudent("王敏", 18));
        System.out.println("byObject = " + byObject);

7.2 增删改

接口

package mapper;

import beans.MyStudent;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface MyStudentMapper {
    List<MyStudent> findAll();
    MyStudent findById(long id);
    MyStudent findByName(@Param("myName") String name, @Param("myAge") int age);
    MyStudent findByObject(MyStudent myStudent);
    // 增
    int add(MyStudent myStudent);
    // 改
    int update(MyStudent myStudent);
    // 删除
    int delete(long id);
}

mapper xml 配置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace 与mapper接口的全类名保持一致-->
<mapper namespace="mapper.MyStudentMapper">
    <!--id要和mapper接口的方法名保持一致 -->
    <!-- resultType 与sql返回值对应的类的全类名保持一致-->
    <select id="findAll" resultType="beans.MyStudent">
        select * from MyStudent
    </select>

    <select id="findById" resultType="beans.MyStudent">
        select * from MyStudent where id = #{id}
    </select>

    <select id="findByName" resultType="beans.MyStudent">
        select * from MyStudent where name = #{myName} and age = #{myAge}
    </select>

    <select id="findByObject" resultType="beans.MyStudent" parameterType="beans.MyStudent">
        select * from MyStudent where name = #{name} and age = #{age}
    </select>

    <insert id="add" parameterType="beans.MyStudent">
        insert into MyStudent (name,age) values (#{name},#{age})
    </insert>

    <update id="update" parameterType="beans.MyStudent">
        update MyStudent set name = #{name},age = #{age} where id = #{id}
    </update>

    <delete id="delete">
        delete from MyStudent where id = #{id}
    </delete>


</mapper>

add 方法为增

update 方法为改

delete 方法为删

注意:

1、在xml配置文件中,我们的增 与 改,传参都是对象。需要设置对象类型parameterType="beans.MyStudent"

删,是根据long类型的id,进行删除的,传参为基本类型时,不需要设置传参的类型

2、delete 删除,我们很少使用,一般是逻辑删除。

方法的调用

package main;

import beans.MyStudent;
import mapper.MyStudentMapper;
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 {
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        // 选择不同的数据库,指定数据库
         SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in,"development");
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        // 得到MyStudent表的mapper
        MyStudentMapper myStudentMapper = sqlSession.getMapper(MyStudentMapper.class);
        // 调用mapper的方法
        MyStudent byId = myStudentMapper.findById(201215121);
        System.out.println("byId = " + byId);
        MyStudent byName = myStudentMapper.findByName("王敏", 18);
        System.out.println("byName = " + byName);
        MyStudent byObject = myStudentMapper.findByObject(new MyStudent("王敏", 18));
        System.out.println("byObject = " + byObject);

        int i = myStudentMapper.add(new MyStudent("张三", 19));
        System.out.println("i = " + i);

        int update = myStudentMapper.update(new MyStudent(201215125, "李四", 19));
        System.out.println("update = " + update);

        int delete = myStudentMapper.delete(201215125);
        System.out.println("delete = " + delete);

//        sqlSession.commit();
        sqlSession.close();


    }
}

1、增、删、改行为,执行sql,都需要提交事物。

方法一,在创建sqlSession 时,添加true,开启自动提交事物

        SqlSession sqlSession = sqlSessionFactory.openSession(true);

方法二,我们在执行sql后,手动提交事物。


        int delete = myStudentMapper.delete(201215125);
        System.out.println("delete = " + delete);

        sqlSession.commit();

八、注解版mapper ,增删改查

mapper接口,MyStudentMapper,方法与sql写一起

package mapper;

import beans.MyStudent;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface MyStudentMapper {
    @Select("select * from MyStudent")
    List<MyStudent> findAll();

    @Select("select * from MyStudent where id = #{id}")
    MyStudent findById(long id);

    @Select("select * from MyStudent where name = #{myName} and age = #{myAge}")
    MyStudent findByName(@Param("myName") String name, @Param("myAge") int age);

    @Select("select * from MyStudent where name = #{name} and age = #{age}")
    MyStudent findByObject(MyStudent myStudent);

    // 增
    @Insert("insert into MyStudent (name,age) values (#{name},#{age})")
    int add(MyStudent myStudent);

    // 改
    @Update("update MyStudent set name = #{name},age = #{age} where id = #{id}")
    int update(MyStudent myStudent);

    // 删除
    @Delete("delete from MyStudent where id = #{id}")
    int delete(long id);

}

方法调用

package main;

import beans.MyStudent;
import mapper.MyStudentMapper;
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 {
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        // 选择不同的数据库,指定数据库
         SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in,"test");
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        // 得到MyStudent表的mapper
        MyStudentMapper myStudentMapper = sqlSession.getMapper(MyStudentMapper.class);
        // 调用mapper的方法
        List<MyStudent> all = myStudentMapper.findAll();
        System.out.println("all = " + all);

        // 调用mapper的方法
        MyStudent byId = myStudentMapper.findById(201215121);
        System.out.println("byId = " + byId);
        MyStudent byName = myStudentMapper.findByName("王敏", 18);
        System.out.println("byName = " + byName);
        MyStudent byObject = myStudentMapper.findByObject(new MyStudent("王敏", 18));
        System.out.println("byObject = " + byObject);

        int i = myStudentMapper.add(new MyStudent("张三", 19));
        System.out.println("i = " + i);

        int update = myStudentMapper.update(new MyStudent(201215126, "李四", 19));
        System.out.println("update = " + update);

        int delete = myStudentMapper.delete(201215126);
        System.out.println("delete = " + delete);
        sqlSession.close();



    }
}

九、获取自增主键的值

背景:

表MyStudent,id是自增主键。

 当我们插入数据时,(一共3个字段),name与age是我们手动插入的,id是系统自动生成的。

我们如何取到系统生成的id的值呢?

insert into MyStudent (name,age) values (#{name},#{age}

9.1 注解mapper ,获取自增主键的值

接口配置


    // 增
    @Insert("insert into MyStudent (name,age) values (#{name},#{age})")
    @Options(useGeneratedKeys = true,keyProperty = "id")
    int add(MyStudent myStudent);

使用注解@Options。keyProperty="id",MyStudent 实体类中的属性值。

调用:

        MyStudent myStudent = new MyStudent("张三", 19);
        int i = myStudentMapper.add(myStudent);
        System.out.println("i = " + i);
        System.out.println("myStudent = " + myStudent);

9.2 xml mapper ,获取自增主键的值

xml mapper配置文件 

    <insert id="add" parameterType="beans.MyStudent" useGeneratedKeys="true" keyProperty="id">
        insert into MyStudent (name,age) values (#{name},#{age})
    </insert>

useGeneratedKeys="true" keyProperty="id"

keyProperty="id",MyStudent 实体类中的属性值。

调用


        MyStudent myStudent = new MyStudent("张三", 19);
        int i = myStudentMapper.add(myStudent);
        System.out.println("i = " + i);
        System.out.println("myStudent = " + myStudent);

十、动态sql

10.1 背景

动态sql,就是给sql赋予一段处理逻辑。

如我们原来的sql

select * from MyStudent where name = #{name} and age = #{age}

根据name and age 去做查询。当我们只需要一个条件name或者age去查询的时候如何做处理? 

没有必要再写一个新的sql,我们给它加一段逻辑。当name与age 都不为空时,用这两个条件去查询。当有一个条件为空时,用另一个条件去查询。 

10.2 xml mapper动态sql

方式一:

修改mapper xml sql语句,使用<where>

    <select id="findByList" resultType="beans.MyStudent" parameterType="beans.MyStudent">
        select * from MyStudent
        <where>
            <if test="name != null">
                and name = #{name}
            </if>
            <if test="age != null">
                and age = #{age}
            </if>
        </where>
    </select>

注意,这里每个条件前边,都加了一个and。

为啥要加and? 因为当我们多个条件同时查询时,需要用and连接。 这个<where> 应该是对只用一个条件查询时,做了特殊处理,比如方式二,用了1=1做了处理。

方式二:

修改mapper xml sql语句,使用1=1

    <select id="findByList" resultType="beans.MyStudent" parameterType="beans.MyStudent">
        select * from MyStudent where  1=1
        <if test="name != null">
            and name = #{name}
        </if>
        <if test="age != null">
            and age = #{age}
        </if>
    </select>

注意,这里每个条件前边,都加了一个and。

为啥要加and? 因为当我们多个条件同时查询时,需要用and连接。 

为啥要加1=1?因为当我们只用一个条件查询时,sql就变成了这样

select * from MyStudent where  and name = #{name}

条件里,多了一个and,我们在前边加一个1=1,sql就变成了正常sql了。

select * from MyStudent where  1=1 and name = #{name}

10.3 注解版mapper 动态sql

修改,接口方法上的sql注解。

    @Select("<script>         select * from MyStudent\n" +
            "        <where>\n" +
            "            <if test=\"name != null\">\n" +
            "                and name = #{name}\n" +
            "            </if>\n" +
            "            <if test=\"age != null\">\n" +
            "                and age = #{age}\n" +
            "            </if>\n" +
            "        </where></script>")
            
    List<MyStudent> findByList(MyStudent myStudent);

有个简便的方法,就是我们先在xml里写好了sql,在复制到这个接口上。

复制这个:

然后粘贴到 接口的注解上

 注意,这里多了一个<script></script>

十一、批量插入

11.1 xml 批量插入

在接口中,增加批量插入的方法

    // 批量插入
    int insertAll(List<MyStudent> list);

修改xml文件

    <insert id="insertAll" parameterType="beans.MyStudent">
        insert into MyStudent (name,age) values
        <foreach collection="list" separator="," item="item">
            (#{item.name},#{item.age})
        </foreach>
    </insert>

解释:

正常情况下,批量插入的sql语句,格式为

insert into MyStudent (name,age) values (name1,age1),(name2,age2),(name3,age3)

我们这里也是使用函数,来拼成这个格式。

collection="list",我们传入的是一个list集合,List<MyStudent>

separator="," 我们sql中,多个元素之间,使用逗号进行分割的

item="xx", xx指代集合中的每一个元素。

#{item.name} 集合中,每个元素的name值

调用:

        ArrayList<MyStudent> students = Lists.newArrayList(new MyStudent("张三三", 19), new MyStudent("李思思", 19));
        int all = myStudentMapper.insertAll(students);
        System.out.println("all = " + all);

11.2 sql注解批量插入

 在接口中,增加批量插入的方法

    // 批量插入
    int insertAll(List<MyStudent> list);

给方法增加sql注解

    // 批量插入
    @Insert("<script>        insert into MyStudent (name,age) values\n" +
            "        <foreach collection=\"list\" separator=\",\" item=\"item\">\n" +
            "            (#{item.name},#{item.age})\n" +
            "        </foreach> </script>")
    int insertAll(List<MyStudent> list);

这个注解,看起来有点复杂,我们还是直接复制xml版本的sql语句,

复制到这个@Insert("<script></script>")里面就可以

调用

        ArrayList<MyStudent> students = Lists.newArrayList(new MyStudent("张三三", 19), new MyStudent("李思思", 19));
        int all = myStudentMapper.insertAll(students);
        System.out.println("all = " + all);

十二、批量删除

12.1 xml 批量删除

 在接口中,增加批量删除的方法

    // 批量删除,long... 可变长参数
    int deleteAll(long... ids);

解释:

...表示 可变参数,我们进行删除时,(根据id进行删除)sql大概这个格式

delete from MyStudent where id in (20112,202223,20334)

传入的参数是一个可变长度的数组,数组的每个元素是long类型。

修改xml文件

    <delete id="deleteAll">
        delete from MyStudent where id in 
        <foreach collection="array" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </delete>

解释:

我们最终要拼成的sql,大概是这个格式

delete from MyStudent where id in (20112,202223,20334)

collection="array" 我们传入的参数就是一个数组,array

open="(" close=")" ,sql中,我们的参数在一个括号() 中。这个是来拼接这个()的

item="id" 数组中,每个元素

separator="," 数组中,每个元素用逗号分割

调用:

        int deleteAll = myStudentMapper.deleteAll(201215137, 201215138);
        System.out.println("deleteAll = " + deleteAll);

12.2 sql注解删除

 在接口中,增加批量删除的方法

    int deleteAll(long... ids);

给方法增加sql注解

    // 批量删除,long... 可变长参数
    @Delete("<script>        delete from MyStudent where id in \n" +
            "        <foreach collection=\"array\" open=\"(\" close=\")\" item=\"id\" separator=\",\">\n" +
            "            #{id}\n" +
            "        </foreach> </script>")
    int deleteAll(long... ids);

这个注解,看起来有点复杂,我们还是直接复制xml版本的sql语句,

复制到这个@Insert("<script></script>")里面就可以

调用:

        int deleteAll = myStudentMapper.deleteAll(201215137, 201215138);
        System.out.println("deleteAll = " + deleteAll);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/52951.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

kubernetes 实战学习

文章目录kubernetes 实战学习1. 资源创建方式2. Namespace3. Pod3.1 使用命令行创建一个 Pod3.2 使用 YAML 文件创建一个 pod3.3 查看 pod 日志3.4 查看 pod IP3.5 进入 pod 查看信息3.6 一个 pod 里同时运行多个容器3.7 pod 和宿主机之间文件拷贝4. Deployment4.1 deployment …

功能测试(一)—— web项目环境与测试流程、业务流程测试

目录 目标 一、web项目环境说明 【了解】 ​编辑 1.1 环境的定义 1.2 环境(服务器)的组成 1.3 面试题&#xff1a;你们公司有几套环境&#xff1f; 二、熟悉商城项目 【了解】 2.1 商城项目的核心业务 2.2 商城项目的核心功能模块 三、测试流程的应用 【重点】 3.1 需…

Java 基础数据类型占用内存空间和字符串编码简介(二)

Java 基础数据类型占用内存空间简介一 计算机简介1.基本概念2.CPU 三级缓存3.本机参数查看二 数据占用内存情况1.多线程Demo2.结果解析1.直接计算2.volatile 计算3.缓存行填充一 计算机简介 结合多线程计算机的硬件&#xff0c;从侧面理解数据存储如何影响我们的程序 1.基本概…

数据结构学习笔记(Ⅶ):查找

目录 1 查找 1.1 定义 1.2 查找操作 1.3 算法评价指标 2 查找算法 2.1 顺序查找 1.算法思想 2.实现 3.查找效率 4.算法优化 2.2 折半查找 1.算法思想 2.算法实现 3.查找判定树 4.折半查找效率 2.3 分块查找 1.算法思想 2.查找效率分析 3 B树 3.1 B树概念 3…

Java#30(扩展知识:可变参数与Collections)

目录 一.可变参数 二.Collections 1.Collections常用的API 一.可变参数 本质: 可变参数本质上是一个数组 作用: 在形参中接收多个数据 格式: 数据类型...参数名称 例如: int...a 代码示范: package Demo;public class Test {public static void main(String[] args) {int s…

单目标优化:蜣螂优化算法(Dung beetle optimizer,DBO)

蜣螂优化算法&#xff08;Dung beetle optimizer&#xff0c;DBO&#xff09;由Jiankai Xue和Bo Shen于2022年提出&#xff0c;该算法主要受蜣螂的滚球、跳舞、觅食、偷窃和繁殖行为的启发所得。 一、蜣螂优化算法 1.1蜣螂滚球 &#xff08;1&#xff09;当蜣螂前行无障碍时…

redis基础3——配置文件核心参数实测+RDB持久化、AOF持久化核心参数详解

文章目录一、redis.conf配置文件详解1.1 查看配置文件位置1.2 启动需指定配置文件1.3 单位大小写不敏感1.4 引用其他配置文件&#xff08;包含&#xff09;1.4.1 测试参数存放前后位置1.4.1.1 反例1.4.1.2 正例1.4.2 测试引用参数有效性1.5 网络相关1.5.1 绑定IP1.5.2 保护模式…

全球领先飞瞳引擎™云服务全球两千+企业用户,集装箱识别集装箱箱况残损检测,正常箱号识别率99.98%以上,箱信息识别及铅封识别免费

全球领先飞瞳引擎™AI集装箱识别检测云服务全球两千企业用户&#xff0c;集装箱识别集装箱箱况残损检测&#xff0c;正常箱号识别率99.98%以上&#xff0c;箱信息识别及铅封识别免费。CIMCAI中集飞瞳是全球应用落地最广&#xff0c;规模最大&#xff0c;最先进的的港航人工智能…

链游新发展方向:告别高强度打金,回归游戏本质

2022 年伊始&#xff0c;加密领域最瞩目的项目要属区块链游戏了。随着 Axie Infinity、Genopets 和 Perion 等公司大获成功&#xff0c;区块链游戏生态系统逐渐进入主流圈。值得一提的是&#xff0c;游戏和 NFT 这两个备受关注的类别在 Web 3 世界中互相成就&#xff0c;创造出…

【简单总结】SLAM 算法的 Benchmark 及相关数据集的结果对比

前言与参考 主要是copy一下总结&#xff0c;方便自己后续找方案特定使用&#xff0c;所有的出处均在标题处和原链接跳转&#xff0c;此处仅做各个benchmark收集使用&#xff0c;如果有原作者觉得侵权&#xff0c;请联系我 将全力配合相关内容和链接删除 如果网友有其他更新的…

代码随想录刷题day51 309.最佳买卖股票时机含冷冻期;714.买卖股票的最佳时机含手续费

代码随想录刷题day51 309.最佳买卖股票时机含冷冻期&#xff1b;714.买卖股票的最佳时机含手续费 股票买卖&#xff0c;前两天的有点忘了正好也复习一下。 309.最佳买卖股票时机含冷冻期 309. 最佳买卖股票时机含冷冻期 - 力扣&#xff08;Leetcode&#xff09; 不是很好优…

Java---SpringBoot---SpringBoot

SpringBoot1&#xff0c;SpringBoot简介1.1 SpringBoot快速入门1.1.1 开发步骤1.1.1.1 创建新模块1.1.1.2 创建 Controller1.1.1.3 启动服务器1.1.1.4 进行测试1.1.2 对比1.1.3 官网构建工程1.1.3.1 进入SpringBoot官网1.1.3.2 选择依赖1.1.3.3 生成工程1.1.4 SpringBoot工程快…

尚医通-预约下单中rabbitmq的使用

需求描述 在挂号界面选择完需要挂号的医生和排版后&#xff0c;添加就诊人&#xff0c;确认挂号 附上业务流程图 技术分析 我们今天主要来看看这块 mq 的运用&#xff0c;也是一个思考&#xff0c;我还是挑着重要的来讲&#xff0c;这里讲讲我们这里怎么使用 mq 的 这里会用…

关于λ-optimal的初始化解算法在(元)启发式中的应用

关于λ-optimal算法在启发式中初始化解的应用TSP问题介绍λ-optimal定理与定义算法描述与伪代码算法的优化参考文献这里讨论组合优化中初始解的生成问题。组合优化问题&#xff0c;很多情况下&#xff0c;解的生成是随机的或者是采用某种直观上满足题意的初始化方法&#xff0c…

12月1日(第三天)

四舍五入 Math.round()整形 字符串输出字符串&#xff0c;加字符则输出整形if else if&#xff0c;是互斥关系&#xff0c;同时满足条件&#xff0c;只会被执行前面那个&#xff0c;if if&#xff0c;是并列的关系&#xff0c;条件满足都会执行ORACLE中的操作&#xff08;来自…

使用SpringBoot将图片上传至阿里云OSS

一. 对象存储OSS 1. 什么是OSS? 官方的解释是这样的&#xff1a;阿里云对象存储OSS&#xff08;Object Storage Service&#xff09;是一款海量、安全、低成本、高可靠的云存储服务&#xff0c;提供99.9999999999%(12个9)的数据持久性&#xff0c;99.995%的数据可用性。 官网…

我开发的开源项目,让.NET7中的EFCore更轻松地使用强类型Id

在领域驱动设计&#xff08;DDD&#xff09;中&#xff0c;有一个非常重要的概念&#xff1a;“强类型Id”。使用强类型Id来做标识属性的类型会比用int、Guid等通用类型能带来更多的好处。比如有一个根据根据Id删除用户的方法的签名如下&#xff1a; void RemoveById(long id)…

【毕业设计】9-基于STM32无刷直流电机控制器的设计仿真与实现(原理图+源码+仿真工程+论文+PPT+参考英文文献)

毕业设计】基于STM32无刷直流电机控制器的设计仿真与实现&#xff08;原理图源码仿真工程论文PPT参考英文文献&#xff09; 文章目录毕业设计】基于STM32无刷直流电机控制器的设计仿真与实现&#xff08;原理图源码仿真工程论文PPT参考英文文献&#xff09;任务书设计说明书摘要…

能迪科技智能控制系统对中央空调进行精准、单独调控医院案例

案例背景​ 梅州市妇女儿童医院新院区&#xff08;以下简称“新院区”&#xff09;是省、市重点项目工程&#xff0c;建设地点位于江南新城客都大道北侧&#xff0c;一期项目总投资4.8亿元&#xff0c;占地面积50亩&#xff0c;总建筑面积87000平方米&#xff0c;按照三级妇幼保…

blender cycles引擎

文章目录简介属性一 Scene采样二 光程最多反弹次数钳制焦散快速GI近似三 体积步进速率四 曲线简介 1 cycles与EV的区别在于cy是传统渲染引擎&#xff0c;效果好&#xff0c;速度慢&#xff0c;ev是实时引擎&#xff0c;速度快&#xff0c;效果差 2 切换渲染引擎&#xff0c;属…