文档引用:http://www.mybatis.cn/archives/678.html

视频参考:https://www.bilibili.com/video/BV1NE411Q7Nx?p=15


 

注解与xml取舍

在没有注解之前,xml被广泛的应用于描述元数据,xml的维护越来越糟糕。

在需要紧耦合的地方,比xml该容易维护,阅读更方便。

在需要比较多参数设置时,使用xml更方便,而在将某个方法声明为服务时这种紧耦合的情况下,

比较适合注解。

xml是松耦合的,注解是紧耦合的,对于xml和注解的使用,要具体问题具体分析。

例如,这种情况下xml更胜一筹:MyBatis XML配置对抗MyBatis注解的一大杀器:SQL片段,抽取可重用的SQL语句

java的注解没有行为,只能有数据,实际上就是一组键值对而已。

通过解析类(Parse Class)就能把一个注解设置的键值对都找出来。

 

mybatis 注解与xml配置

因为最初设计时,MyBatis是一个XML驱动的框架。

配置信息是基于XML的,而且映射语句也是定义在XML中的。

而到了MyBatis3,有新的选择了:利用注解实现SQL的映射。

MyBatis3构建在全面而且强大的Java 注解(Java annotation)之上。

注解提供了一种便捷的方式来实现简单SQL映射语句,可以简化编写XML的过程。

MyBatis基于注解的用法,正在变得越来越流行,

但是需要注意的是:注解的方式还没有百分百覆盖所有XML标签,所以还是有一点点不足!


 

快速入门

【Mybatis】11 注解的使用_sql

新建一个CRUD的Mapper接口

public interface UserAnnotationMapper {
    
    @Select("SELECT * FROM `user`;")
    List<User> getAllUserList();
}

 

我们不需要再写Mapper接口配置了

直接再核心配置中注册接口即可

【Mybatis】11 注解的使用_xml_02

 

测试发生了错误

java.lang.ExceptionInInitializerError
    at SqlSessionTest.sqlTest(SqlSessionTest.java:124)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: org.apache.ibatis.exceptions.PersistenceException: 
### Error building SqlSession.
### The error may exist in cn/dai/mapper/UserAnnotationMapper.java (best guess)
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.binding.BindingException: Type interface cn.dai.mapper.UserAnnotationMapper is already known to the MapperRegistry.
    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
    at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:80)
    at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:64)
    at cn.dai.util.MybatisUtil.<clinit>(MybatisUtil.java:26)
    ... 26 more
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.binding.BindingException: Type interface cn.dai.mapper.UserAnnotationMapper is already known to the MapperRegistry.
    at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:121)
    at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:98)
    at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:78)
    ... 28 more
Caused by: org.apache.ibatis.binding.BindingException: Type interface cn.dai.mapper.UserAnnotationMapper is already known to the MapperRegistry.
    at org.apache.ibatis.binding.MapperRegistry.addMapper(MapperRegistry.java:63)
    at org.apache.ibatis.binding.MapperRegistry.addMappers(MapperRegistry.java:97)
    at org.apache.ibatis.binding.MapperRegistry.addMappers(MapperRegistry.java:105)
    at org.apache.ibatis.session.Configuration.addMappers(Configuration.java:771)
    at org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement(XMLConfigBuilder.java:365)
    at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:119)
    ... 30 more

经过检查发现使用接口注册就不能和包扫描同时使用

    <mappers>
        <mapper class="cn.dai.mapper.UserAnnotationMapper" />

        <!--<package name="cn.dai.mapper"/>-->
    </mappers>

 

再测试就可行

[SqlSessionTest]-- - - - TESTING - - - -
[org.apache.ibatis.logging.LogFactory]-Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
[org.apache.ibatis.logging.LogFactory]-Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
[org.apache.ibatis.io.VFS]-Class not found: org.jboss.vfs.VFS
[org.apache.ibatis.io.JBoss6VFS]-JBoss 6 VFS API is not available in this environment.
[org.apache.ibatis.io.VFS]-Class not found: org.jboss.vfs.VirtualFile
[org.apache.ibatis.io.VFS]-VFS implementation org.apache.ibatis.io.JBoss6VFS is not valid in this environment.
[org.apache.ibatis.io.VFS]-Using VFS adapter org.apache.ibatis.io.DefaultVFS
[org.apache.ibatis.io.DefaultVFS]-Find JAR URL: file:/C:/Users/Administrator/IdeaProjects/Mybatis/Mybatis02%20-%20Configure/target/classes/cn/dai/pojo
[org.apache.ibatis.io.DefaultVFS]-Not a JAR: file:/C:/Users/Administrator/IdeaProjects/Mybatis/Mybatis02%20-%20Configure/target/classes/cn/dai/pojo
[org.apache.ibatis.io.DefaultVFS]-Reader entry: LimitSqlParam.class
[org.apache.ibatis.io.DefaultVFS]-Reader entry: User.class
[org.apache.ibatis.io.DefaultVFS]-Listing file:/C:/Users/Administrator/IdeaProjects/Mybatis/Mybatis02%20-%20Configure/target/classes/cn/dai/pojo
[org.apache.ibatis.io.DefaultVFS]-Find JAR URL: file:/C:/Users/Administrator/IdeaProjects/Mybatis/Mybatis02%20-%20Configure/target/classes/cn/dai/pojo/LimitSqlParam.class
[org.apache.ibatis.io.DefaultVFS]-Not a JAR: file:/C:/Users/Administrator/IdeaProjects/Mybatis/Mybatis02%20-%20Configure/target/classes/cn/dai/pojo/LimitSqlParam.class
[org.apache.ibatis.io.DefaultVFS]-Reader entry: ����   1 Q      =      > ?
[org.apache.ibatis.io.DefaultVFS]-Find JAR URL: file:/C:/Users/Administrator/IdeaProjects/Mybatis/Mybatis02%20-%20Configure/target/classes/cn/dai/pojo/User.class
[org.apache.ibatis.io.DefaultVFS]-Not a JAR: file:/C:/Users/Administrator/IdeaProjects/Mybatis/Mybatis02%20-%20Configure/target/classes/cn/dai/pojo/User.class
[org.apache.ibatis.io.DefaultVFS]-Reader entry: ����   1 _      H      I      J K
[org.apache.ibatis.io.ResolverUtil]-Checking to see if class cn.dai.pojo.LimitSqlParam matches criteria [is assignable to Object]
[org.apache.ibatis.io.ResolverUtil]-Checking to see if class cn.dai.pojo.User matches criteria [is assignable to Object]
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection
[org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 1536471117.
[cn.dai.mapper.UserAnnotationMapper.getAllUserList]-==>  Preparing: SELECT * FROM `user`; 
[cn.dai.mapper.UserAnnotationMapper.getAllUserList]-==> Parameters: 
[cn.dai.mapper.UserAnnotationMapper.getAllUserList]-<==      Total: 16
User(user_id=1, user_name=杰哥, user_password=123456)
User(user_id=2, user_name=阿伟, user_password=123456)
User(user_id=3, user_name=空条承太郎, user_password=123456)
User(user_id=4, user_name=乔鲁诺乔巴纳, user_password=123456)
User(user_id=5, user_name=迪奥布兰多, user_password=123456)
User(user_id=6, user_name=乔瑟夫乔斯达, user_password=123456)
User(user_id=7, user_name=乔纳森乔斯达, user_password=123456)
User(user_id=8, user_name=丽萨丽萨, user_password=654321)
User(user_id=9, user_name=东方仗助, user_password=654321)
User(user_id=10, user_name=东方定助, user_password=654321)
User(user_id=11, user_name=花京院典明, user_password=654321)
User(user_id=12, user_name=波鲁纳雷夫, user_password=654321)
User(user_id=13, user_name=吉良吉影, user_password=654321)
User(user_id=14, user_name=布加拉提, user_password=654321)
User(user_id=15, user_name=葛德米斯达, user_password=131313)
User(user_id=18, user_name=哈吉咩, user_password=335577)
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@5b94b04d]
[org.apache.ibatis.datasource.pooled.PooledDataSource]-Returned connection 1536471117 to pool.

Process finished with exit code 0

 

但是我换了这个之后,也是可行的

    <mappers>
        <!--<mapper class="cn.dai.mapper.UserAnnotationMapper" />-->

        <package name="cn.dai.mapper"/>
    </mappers>

也就是说注册过的地方不可以重复注册

 

最后采用资源引用 + 接口完全限定名,两者都可以使用

    <mappers>
        <mapper class="cn.dai.mapper.UserAnnotationMapper" />

        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>

 

补全剩下的注解

package cn.dai.mapper;

import cn.dai.pojo.User;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.List;

/**
 * @author ArkD42
 * @file Mybatis
 * @create 2020 - 05 - 04 - 13:54
 */
public interface UserAnnotationMapper {

    @Select("SELECT * FROM `user`;")
    List<User> getAllUserList();

    @Select("SELECT * FROM `user` WHERE user_id = #{id};")
    User getUserById(Integer id);

    @Insert("INSERT INTO `user` VALUES(#{user_id},#{user_name},#{user_password});")
    int addUser(User user);

    @Update("UPDATE `user` SET user_name = #{user_name},user_password = #{user_password} WHERE user_id = #{user_id}")
    int updateUserById(User user);

    @Delete("DELETE FROM `user` WHERE user_id = #{id};")
    int deleteUserById(Integer id);
}

 

@Param注解类似结果集字段映射,

主要用于多个参数的绑定匹配

【Mybatis】11 注解的使用_ide_03

【Mybatis】11 注解的使用_sql_04

 

要注意的一点是,注解SQL不能和Mapper映射文件同时配置,

要么注解要么XML,不可以两个都配置同一个接口的抽象SQL方法

 

 

更多详细:http://www.mybatis.cn/archives/678.html