• 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

  • 相关阅读:
    第01组 Beta冲刺(4/4)
    第01组 Beta冲刺(3/4)
    2019年安徽省黄山与湖北省武汉空气质量的数据分析
    爬取2019年hg录取分数线
    简单介绍下gbk和utf-8这两种编码的区别
    词云大作业(普哥、硕哥快来看啊!!!)
    分享一种下载python第三方库wordcloud库的一种方法
    介绍一种安装python第三方库jieba库的方法
    《C语言程序设计》实验报告(六)
    《C语言程序设计》实验报告(五)
  • 原文地址:https://www.cnblogs.com/rainful/p/15092091.html
Copyright © 2020-2023  润新知