MyBatis初识

Mybaties-9.28

环境

  • JDK 1.8
  • Mysql 5.7
  • maven 3.6.1
  • IDEA

关键词

  • 持久化就是数据在持久态和瞬时态转化的过程

  • POJO (Plain Ordinary Java Object)

  • iBatis

  • DAOS(Data Access Objects)

  • 持久层

依赖配置

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>

Start

下面步骤均以官网显示的推荐步骤进行,对于官网一些的一些部分加以说明

环境为mavaen环境

1.配置依赖

在Maven配置中配置

2.使用xml进行配置文件

mybatis-config.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!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="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
          <!--上面四项就是平时进行配置的driver,url,name,password,进行替换即可-->
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
      <!--此项必须配置,路径为xml文件的位置,这里建议如果是maven项目,请将BlogMaaper.xml文件放在resources目录下-->
  </mappers>
</configuration>

3.编写实体类

和数据库对应即可

public class User {
    int id;
    String name;
    String pwd;

    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public User() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
}

4.编写接口文件

接口文件的作用就是定义返回类型和具体方法名

public interface UserMapper {
    /**
     * 获取所有用户列表
     * @return 用户列表
     */
    List<User> getUserList();
}

5.创建MyBatis工具类

为了保证统一获取sqlSession

public class MyBatisUtils {
    private static SqlSessionFactory sqlSessionFactory = null;

    // 获取sqlSessionFactory对象
    static {
        InputStream inputStream = MyBatisUtils.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
        // 这里因为放在了resources文件夹里面可以很方便的直接使用类加载器读取文件
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    public static SqlSession getSqlSession(){
        // 从 SqlSessionFactory 中获取 SqlSession
        // sqlSession 类似于 connection
        return sqlSessionFactory.openSession();
    }

}

6.编写Mapper文件指定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">
<mapper namespace="day01.dao.UserMapper">
    <!--namespace是接口-->
    <select id="getUserList" resultType="day01.pojo.User">
    <!--id指的是获取的方法,resultType指的是返回的结果是什么类-->
        select * from rainful_mybatis.User
    <!--这里编写sql语句-->
    </select>
</mapper>

7.调用

这里使用junit调用

public class UserMapperTest {
    public static void main(String[] args) {
        try(SqlSession sqlSession = MyBatisUtils.getSqlSession()) {
            // 使用try resource语法可以方便后期减少sqlSession.close()
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> list = mapper.getUserList();
            System.out.println(list);
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

可能遇到的问题

  • xml文件没有放在resources文件夹内放在了类的旁边导致maven进行打包的时候忽略了xml文件,此时需要在maven的pom文件里面增加下面这句话防止xml文件和properties文件被maven打包时忽略
<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>
  • 因为没有修改2步骤里面的一些文件导致空指针异常等

CRUD

namespace

命名空间中的包名和 Dao/mapper 接口的包名一致

select

  • id就是对应的namespace中的方法名
  • returnType sql执行语句的返回值类型(如果是自定义类型就需要包名全称或者别名)
  • parameterType 参数类型,同上
<select id="getUserById" parameterType="int" resultType="day01.pojo.User">
    select *
    from rainful_mybatis.User
    where id = #{id}
    # 直接使用 #{参数名} 可以获得参数
</select>

insert

<insert id="insertUser" parameterType="day01.pojo.User">
# 注意这个里  insert就是insert标签 select就是select标签
# 写错会导致报错,而且提交成功
    insert into rainful_mybatis.User (id, name, pwd) value (#{id}, #{name}, #{pwd})
    # 这里的参数可以直接取user里面的属性名
</insert>

update

<update id="updateUser" parameterType="day01.pojo.User">
    update rainful_mybatis.User
    set name = #{name},
        pwd  = #{pwd}
    where id = #{id}
</update>

delete

<delete id="delUser" parameterType="int">
    delete
    from rainful_mybatis.User
    where id = #{id}
</delete>
  • 注意增删改需要提交事务
  • return null 是因为select和insert这种标签问题

  • mybatis配置文件里面的resource配置路径又应该是 / 分隔

使用Map替代实体类

好处在于当实体类参数过多的时候可以不用写不需要的参数

但是如果实体类有空参,set方法== ,是不是就不需要了

/**
 * 插入一个新用户
 * @param map 一个map里面只包含需要更改的字段
 * @return 返回受影响的行数
 */
int insertUser2(Map<String, Object> map);
<insert id="insertUser2" parameterType="Map">
    insert into rainful_mybatis.User (name, pwd) value (#{username}, #{password});
    # 这里可以看到后面的参数类型可以是其他名称不需要和前面对象
    # 但是需要和map里面的字段对应
</insert>
@Test
public void insertUser2(){
    try(SqlSession sqlSession = MyBatisUtils.getSqlSession()) {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        HashMap<String, Object> map = new HashMap<>();
        map.put("username", "赵六");
        map.put("password", "123456");
        int row = mapper.insertUser2(map);
        if (row > 0){
            System.out.println("插入成功");
            sqlSession.commit();
        }
    }
}

下面试一试空参构造使用set来

/**
 * 插入一个新用户
 * @param user 一个空参构造的User,只需要设置一些需要更改的字段
 * @return 返回受影响的行数
 */
int insertUser3(User user);
<insert id="insertUser3" parameterType="day01.pojo.User">
    insert into rainful_mybatis.User (name, pwd) value (#{name}, #{pwd})
</insert>
@Test
public void insertUser3(){
    try(SqlSession sqlSession = MyBatisUtils.getSqlSession()) {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        User user = new User();
        user.setName("十全");
        user.setPwd("123123123");
        int row = mapper.insertUser3(user);
        if (row > 0){
            System.out.println("插入成功");
            sqlSession.commit();
        }
    }
}

模糊查询

  • 通过xml配置
<select id="getUserListByFuzzyQuery" parameterType="String" resultType="day01.pojo.User">
    select *
    from rainful_mybatis.User
    where name like concat('%', #{value}, '%')
</select>
@Test
public void selectUser(){
    try(SqlSession sqlSession = MyBatisUtils.getSqlSession()) {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        List<User> userList = mapper.getUserListByFuzzyQuery("赵");
        for (User user : userList) {
            System.out.println("user = " + user);
        }
    }
}
  • 或者直接在调用处"%赵%"

  • 在sql里面使用 ’%${value}%‘ 的方式会触发sql注入问题

  • 总结

    • #{ }是预编译处理,MyBatis在处理#{ }时,它会将sql中的#{ }替换为?,然后调用PreparedStatement的set方法来赋值,传入字符串后,会在值两边加上单引号,使用占位符的方式提高效率,可以防止sql注入。
    • ${}:表示拼接sql串,将接收到参数的内容不加任何修饰拼接在sql中,可能引发sql注入。

配置解析

核心配置文件

mybatis-config.xml

参数

configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

环境配置

可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境

  • 每个数据库对应一个 SqlSessionFactory 实例

  • 如果需要指定非默认环境使用方法

    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
    
  • 如果忽略了环境参数将会加载默认环境

    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);
    

eg:

<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://ip:port/数据库名s"/>
            <property name="username" value="root"/>
            <property name="password" value="xxxx"/>
            <!--上面四项就是平时进行配置的driver,url,name,password,进行替换即可-->
        </dataSource>
    </environment>
    <environment id="test">
        <transactionManager type="JDBC" />
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://ip:port/数据库名"/>
            <property name="username" value="root"/>
            <property name="password" value="xxxx"/>
        </dataSource>
    </environment>
</environments>
  • 这里配置了一个test环境
sqlSessionFactory = new SqlSessionFactoryBuilder().build(in, "test");
  • sqlSession可以指定test环境进行

事务管理器

分为 JDBC | MANAGED

  • JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
  • MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。

如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。

数据源

有三种数据源类型 UNPOOLED | POOLED JNDI

UNPOOLED 每次请求后都会关闭,对于可用性要求不高的简单应用程序可以使用

  • 仅需配置下面5项
    • driver – 这是 JDBC 驱动的 Java 类全限定名(并不是 JDBC 驱动中可能包含的数据源类)。
    • url – 这是数据库的 JDBC URL 地址。
    • username – 登录数据库的用户名。
    • password – 登录数据库的密码。
    • defaultTransactionIsolationLevel – 默认的连接事务隔离级别。
    • defaultNetworkTimeout – 等待数据库操作完成的默认网络超时时间(单位:毫秒)。查看 java.sql.Connection#setNetworkTimeout() 的 API 文档以获取更多信息。

POOLED 使用了连接池

  • 增加配置
    • poolMaximumActiveConnections – 在任意时间可存在的活动(正在使用)连接数量,默认值:10
    • poolMaximumIdleConnections – 任意时间可能存在的空闲连接数。
    • poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20 秒)
    • poolTimeToWait – 这是一个底层设置,如果获取连接花费了相当长的时间,连接池会打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直失败且不打印日志),默认值:20000 毫秒(即 20 秒)。
    • poolMaximumLocalBadConnectionTolerance – 这是一个关于坏连接容忍度的底层设置, 作用于每一个尝试从缓存池获取连接的线程。 如果这个线程获取到的是一个坏的连接,那么这个数据源允许这个线程尝试重新获取一个新的连接,但是这个重新尝试的次数不应该超过 poolMaximumIdleConnectionspoolMaximumLocalBadConnectionTolerance 之和。 默认值:3(新增于 3.4.5)
    • poolPingQuery – 发送到数据库的侦测查询,用来检验连接是否正常工作并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动出错时返回恰当的错误消息。
    • poolPingEnabled – 是否启用侦测查询。若开启,需要设置 poolPingQuery 属性为一个可执行的 SQL 语句(最好是一个速度非常快的 SQL 语句),默认值:false。
    • poolPingConnectionsNotUsedFor – 配置 poolPingQuery 的频率。可以被设置为和数据库连接超时时间一样,来避免不必要的侦测,默认值:0(即所有连接每一时刻都被侦测 — 当然仅当 poolPingEnabled 为 true 时适用)。

JNDI 为了容器而实现的

属性

对于properties,可以在外面进行配置,并可以进行动态替换

在外部的db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://ip:port/数据库名
username=root
password=密码
<properties resource="db.properties"/>
    <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>

这里动态进行名称引用

甚至还可以在properties里面进行额外参数的设置

甚至还可以额外写最后在SqlSessionFactoryBuilder.build()方法里面进行传值

  • 如果一个属性在多个地方进行了配置,那么mybatis将会按照下面的顺序进行加载

    • 首先读取properties元素内部指定的值
    • 然后根据properties元素中的resource属性读取属性文件的值,或根据 url 属性指定的路径读取属性文件,并覆盖前面的值
    • 最后读取作为方法参数传递的属性,并覆盖之前的同名属性
  • 可以配置默认值,但是需要额外配置

  • : 修改默认字符防止混乱

类型别名

为java类设置一个别名,防止完全限定类名的冗余

<typeAliases>
  <typeAlias alias="Author" type="domain.blog.Author"/>
  <typeAlias alias="Blog" type="domain.blog.Blog"/>
  <typeAlias alias="Comment" type="domain.blog.Comment"/>
  <typeAlias alias="Post" type="domain.blog.Post"/>
  <typeAlias alias="Section" type="domain.blog.Section"/>
  <typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>

为一个包取别名

<typeAliases>
  <package name="domain.blog"/>
</typeAliases>
<!--里面所有的类默认以首字母小写为别名,如果有注解则为注解值-->
@Alias("author")
public class Author {
    ...
}

设置

设置名 描述 有效值 默认值
cacheEnabled 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 true | false true
lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 true | false false
logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 未设置

其他

~

生命周期和作用域

SqlSessionFactoryBuilder

一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)

SqlSessionFactory

一旦被创建就应该在应用的运行期间一直存在,使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,最简单的就是使用单例模式或者静态单例模式。

SqlSession

SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。

解决属性名和字段名不一致的问题

1.起别名

没意思, pass

2.resultMap

简单级别

<resultMap id="UserMap" type="user">
    <result column="pwd" property="password"/>
    <!--column是数据库的列名, property是java类的属性-->
</resultMap>
<!--namespace是接口-->
<select id="getUserList" resultMap="UserMap">
    <!--id指的是获取的方法,resultMap指的是使用那个id的resultMap-->
    select * from rainful_mybatis.User
    <!--这里编写sql语句-->
</select>

这里使用的是部分映射,将数据库的pwd字段映射给类的password字段

将所有的列映射到 HashMap 的键上,假如你的程序更可能会使用 JavaBean 或 POJO,MyBatis 会在幕后自动创建一个 ResultMap,再根据属性名来映射列到 JavaBean 的属性上。如果列名和属性名不能匹配上,可以在 SELECT 语句中设置列别名,也可以显示配置外部的resultMap,这也是解决列名不匹配的另外一种方式。

<resultMap id="userResultMap" type="User">
  <id property="id" column="user_id" />
  <result property="username" column="user_name"/>
  <result property="password" column="hashed_password"/>
</resultMap>

然后在引用它的语句中设置 resultMap 属性就行了(注意我们去掉了 resultType 属性)

<select id="selectUsers" resultMap="userResultMap">
  select user_id, user_name, hashed_password
  from some_table
  where id = #{id}
</select>

高级级别

~

日志

日志工厂

  • LOG4J(需要导包)
  • STDOUT_LOGGING (掌握)
  • 其他
    • 如果报错classNotFound 一般是没导包,类名或者包名写错
Opening JDBC Connection
Created connection 1752203484.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@687080dc]
==>  Preparing: select * from rainful_mybatis.User 
==> Parameters: 
<==    Columns: id, name, pwd
<==        Row: 1, 张三, 123456
<==        Row: 2, 李四, 123457
<==        Row: 3, 王五, 123458
<==        Row: 4, 赵六, 123459
<==        Row: 8, 王五, 1234356
<==        Row: 9, 赵六, 123456
<==        Row: 10, 十全, 123123123
<==      Total: 7
User{id=1, name='张三', password='123456'}
User{id=2, name='李四', password='123457'}
User{id=3, name='王五', password='123458'}
User{id=4, name='赵六', password='123459'}
User{id=8, name='王五', password='1234356'}
User{id=9, name='赵六', password='123456'}
User{id=10, name='十全', password='123123123'}
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@687080dc]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@687080dc]
Returned connection 1752203484 to pool.

Log4J

  • 导入依赖

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    
  • 配置mybatis-config.xml

    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    
  • 配置log4j.properties文件

    #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
    log4j.rootLogger=DEBUG,console,file
    
    #控制台输出的相关设置
    log4j.appender.console = org.apache.log4j.ConsoleAppender
    log4j.appender.console.Target = System.out
    log4j.appender.console.Threshold=DEBUG
    log4j.appender.console.layout = org.apache.log4j.PatternLayout
    log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
    
    #文件输出的相关设置
    log4j.appender.file = org.apache.log4j.RollingFileAppender
    log4j.appender.file.File=./log/kuang.log
    log4j.appender.file.MaxFileSize=10mb
    log4j.appender.file.Threshold=DEBUG
    log4j.appender.file.layout=org.apache.log4j.PatternLayout
    log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
    
    #日志输出级别
    log4j.logger.org.mybatis=DEBUG
    log4j.logger.java.sql=DEBUG
    log4j.logger.java.sql.Statement=DEBUG
    log4j.logger.java.sql.ResultSet=DEBUG
    log4j.logger.java.sql.PreparedStatement=DEBUG
    
  • 自己调用Log4J打印信息

    public class UserMapperTest {
        private final Logger logger = Logger.getLogger(UserMapperTest.class);
    
        @Test
        public void testLog4j(){
            logger.info("info:这是info级别信息");
            logger.debug("debug:这是debug级别信息");
            logger.error("error:这是error级别信息");
        }
    }
    

分页

使用limit分页

接口

/**
 * 用户列表分页
 * @param map 参数列表
 * @return 用户列表
 */
List<User> getUserByLimit(Map<String, Integer> map);
// 可以看到这里用的是map进行了参数的封装
// 如果不想使用map封装那么必须使用 (@Param("name") String name, @Param("pwd") String pwd) 这种方式显式声名参数

Mapper配置

<select id="getUserByLimit" resultMap="UserMap" parameterType="map">
    select * from rainful_mybatis.User limit #{startIndex},#{pageSize}
</select>

测试

@Test
public void getUserByLimitTest(){
    try(SqlSession sqlSession = MyBatisUtils.getSqlSession()) {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Map<String, Integer> map = new HashMap<String, Integer>(){{
            put("startIndex", 0);
            put("pageSize", 2);
        }};
        List<User> users = mapper.getUserByLimit(map);
        for (User user : users) {
            System.out.println("user = " + user);
        }
    }
}

RowBounds(了解)

这里不记录

分页插件

MyBatis 分页插件 PageHelper

使用注解开发

面向接口编程

根本原因:解耦,可拓展,提供复用,分层开发中,上层不用管下层的实现,大家遵守共同的标准,是的开发变得容易,提高规范性

理解

接口是从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离

接口本身反应了系统设计人员对系统的抽象理解

接口应有两类

​ 对个体的抽象,对应一个抽象体(abstract class)

​ 对某一方面的抽象,对应一个抽象面(interface)

三个面向区别

  • 面向对象是指,考虑问题时,以对象为单位,考虑属性和方法
  • 面向过程是指,考虑问题时,以一个具体流程问单位
  • 接口设计与非接口设计是对于复用技术而言的,与面向对象(过程)不是一个问题,更多的体现对系统整体的架构

Start

对于简单的sql,可以直接在接口方法上面直接写

对于复杂的还是xml配置

接口方法配置

/**
 * 使用注解获取数据库对象
 * @return 用户列表
 */
@Select("select * from User")
List<User> getUserByAnnotation();

mybatis-config.xml配置

<mappers>
    <mapper class="dao.UserMapper"/>
</mappers>

测试

@Test
public void getUserByAnnotation(){
    try(SqlSession sqlSession = MyBatisUtils.getSqlSession()) {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserByAnnotation();
        for (User user : userList) {
            System.out.println("user = " + user);
        }
    }
}

使用注解增删改查

接口配置

/**
 * 根据用户名和密码查找用户
 * @param name 用户名
 * @param pwd 密码
 * @return 返回一个User对象
 */
@Select("select * from User where name = #{name} and pwd = #{pwd}")
User getUserByAnnotation2(@Param("name") String name, @Param("pwd") String pwd);

xml配置

<mappers>
    <mapper class="dao.UserMapper"/>
</mappers>

测试

@Test
public void getUserByAnnotation2(){
    try(SqlSession sqlSession = MyBatisUtils.getSqlSession()) {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserByAnnotation2("张三", "123456");
        System.out.println("user = " + user);
    }
}

在openSession(true)的话设置自动提交

但是建议不要用吧

接口配置

/**
 * 插入一个新的User对象
 * @param user 新的User对象
 * @return 受影响的行数
 */
@Insert("insert into User (name, pwd) value (#{name}, #{pwd})")
int insertUser(User user);
// 注意此时注解的名字

xml配置同上

测试

@Test
public void insertUser(){
    try(SqlSession sqlSession = MyBatisUtils.getSqlSession()) {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int row = mapper.insertUser(new User(0, "十一", "123123435"));
        if (row > 0){
            System.out.println("插入成功");
            sqlSession.commit();
        }
    }
}

接口配置

/**
 * 更新用户
 * @param user 新的用户对象
 * @return 受影响的行数
 */
@Update("update User set pwd = #{pwd} where name = #{name}")
int updateUser(User user);
@Test
public void updateUser(){
    try(SqlSession sqlSession = MyBatisUtils.getSqlSession()) {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int row = mapper.updateUser(new User(0, "十一", "aaa"));
        if (row > 0){
            System.out.println("更新成功");
            sqlSession.commit();
        }
    }
}

/**
 * 根据id删除用户
 * @param id id
 * @return 受影响的行数
 */
@Delete("delete from User where id = #{id}")
int deleteUser(int id);
@Test
public void deleteUser(){
    try(SqlSession sqlSession = MyBatisUtils.getSqlSession()) {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int row = mapper.deleteUser(11);
        if (row > 0){
            System.out.println("删除成功");
            sqlSession.commit();
        }
    }
}

关于@Param()

  • 基本类型的参数或者String类型需要加上这个
  • 引用类型不需要加
  • 如果只有一个基本类型也不需要,但是建议加上
  • SQL中引用的就是 @Param() 中设定的属性名

#{} ${}

前面是预编译 后面是拼接sql

posted @ 2021-08-02 22:40  Rainful  阅读(35)  评论(0编辑  收藏  举报