MyBatis的注解

一、MyBatis支持的标签注解

1、增删改查

标签注解作用
@Update更新
@Select查询
@Insert插入
@Delete删除

 

2、SqlProvider

标签注解作用
@SelectProvider提供一条查询sql语句
@InsertProvider提供一条插入sql语句
@UpdateProvider提供一条更新sql语句
@DeleteProvider提供一条删除sql语句

 

3、结果映射相关

标签注解作用
@ResultMap用于引用其他的@Results的映射
@Results相当于<resultMap>标签,用于说明映射关系
@Result相当于<resultMap>里的<result>标签,如果设置属性id = true则相当于标签
@ConstructorArgs相当于<constructor>标签
@Arg相当于<constructor>里的<arg>标签,如果设置属性id = true则相当于标签
@Many相当于<Collection>标签,但对于一条语句来完成N - N的情况无法处理,如果有请告诉我
@One相当于<association>标签
@AutomapConstructor一个标记注解基本没啥用

 

4、缓存相关

标签注解作用
@CacheNamespace相当于<cache>标签,用于设置二级缓存的属性
@CacheNameSpcaeRef共享其他二级缓存的配置与实例对象
@Options该注解有两个作用:设置语句的缓存、设置是否自增主键

 

5、主键相关

标签注解作用
@SelectKey用于设置自增主键的生成语句
@Options是否开启自增主键

 

6、鉴别器

标签注解作用
@TypeDiscriminator相当于<discrimnator>标签
@Case相当于<case>标签

 

7、其他

标签注解作用
@MapKey通过一个唯一值建立相关联的对象的映射 https://www.cnblogs.com/heliusKing/p/12210319.html
@Flush用在批量操作中,https://blog.csdn.net/daliucheng/article/details/120251984

 
entity:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Phone implements Serializable {
    private String id;
    private String phone;
    private PhoneTypeEnum type;

    private User user;
}
--------------------------
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {

    private String id;
    private String phoneId;
    private String name;
    private Integer age;

    private List<Phone> phone;
}
---------------------------
public enum  PhoneTypeEnum {
    TYPE1("中国移动"),
    TYPE2("中国联通");
    private String name;

    PhoneTypeEnum(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    public Integer getOrdinal(){
        return this.ordinal();
    }

    @Override
    public String toString() {
        return "PhoneType: {"+" name = " + getName() + " ordinal = " + getOrdinal() + "}";
    }
}    

 

二、简单的增删改查

public interface AnnocationPhoneMapper {

    // -------------------------- 添加 ----------------------
    @Insert(value = "insert into phone values(#{id}, #{phone}, #{type, javaType = com.bihai.mybatis_study.bean.PhoneTypeEnum, jdbcType=VARCHAR, typeHandler = org.apache.ibatis.type.EnumOrdinalTypeHandler})", databaseId = "mysql")
    Boolean insert(Phone phone);

    // ------------------------- 修改 -------------------------
    @Update(value = "update  phone set phone = #{phone} where id = #{id}", databaseId = "mysql")
    @Update(value = "update  phone set phone = #{phone} where id = #{id}", databaseId = "oracle")
    Boolean updateById(Phone phone);

    //--------------------------查询---------------------------
    @Results(id = "phone",value = {
            @Result(id = true, column = "id", property = "id"),
            @Result(column = "phone", property = "phone"),
            @Result(column = "type", property = "type", javaType = PhoneTypeEnum.class, jdbcType = JdbcType.VARCHAR, typeHandler = EnumOrdinalTypeHandler.class)
    })
    @Select(value = "select * from phone where id = #{value}")
    Optional<Phone> selectById(String id);

    //------------------------删除---------------------------------
    @Delete(value = "delete from phone where id = #{id}")
    Boolean deleteById(String id);
}

此处的databaseId用于指定数据库id,可以与配置文件中的databaseIdProvider 搭配使用。
 

<databaseIdProvider type="DB_VENDOR">
  <property name="SQL Server" value="sqlserver"/>
  <property name="DB2" value="db2"/>
  <property name="Oracle" value="oracle" />
</databaseIdProvider>

要吐槽的是不支持集合形式的Optional,真是食之无味,弃之可惜。

 

三、SqlProvider

public class PhoneProvider {

    public String insert(){
        return "insert into phone values(#{id}, #{phone}, #{type, javaType = com.bihai.mybatis_study.bean.PhoneTypeEnum, jdbcType=VARCHAR, typeHandler = org.apache.ibatis.type.EnumOrdinalTypeHandler})";
    }

    public String updateById(){
        return "update  phone set phone = #{phone} where id = #{id}";
    }

    public String selectById(){
        return "select * from phone where id = #{value}";
    }

    public String deleteById(){
        return "delete from phone where id = #{id}";
    }
}


public interface AnnocationPhoneMapper {
    @InsertProvider(type = PhoneProvider.class, method = "insert")
    Boolean insertSqlProvider(Phone phone);

    @UpdateProvider(type = PhoneProvider.class, method = "updateById")
    Boolean updateByIdSqlProvider(Phone phone);

    @SelectProvider(type = PhoneProvider.class, method = "selectById")
    @ResultMap(value = "phone")
    Optional<Phone> selectByIdSqlProvider(String id);

    @DeleteProvider(type = PhoneProvider.class, method = "deleteById")
    Boolean deleteByIdSqlProvider(String id);
}

此处的@RsultMap里面的value引用的是前面定义的@Results里面的内容。
 
关于单参数、多参数情况,请参考:

mybatis 3 中 @SelectProvider的用法总结 - MyBatis中文官网

 

四、缓存与自增主键

此处介绍的缓存为二级缓存

1、缓存

1、再mybatis-config中开启二级缓存:

<settings>
        <setting name="cacheEnabled" value="true"/>
</settings>

 
2、标注@CacheNamespace注解,相当于标签,很多都是默认配置,可以根据情况修改

@CacheNamespace()
public interface AnnocationPhoneMapper {
    .....
}

 
3、默认情况下,对某个映射接口开启缓存,那么该接口下的查询、修改语句都会默认开启缓存,可以通过一下设置不开启当前语句的缓存

@Results(id = "phoneMap",value = {
    @Result(id = true, column = "id", property = "id"),
    @Result(column = "phone", property = "phone"),
    @Result(column = "type", property = "type", javaType = PhoneTypeEnum.class, jdbcType = JdbcType.VARCHAR, typeHandler = EnumOrdinalTypeHandler.class)
})
@Select(value = "SELECT * FROM phone")
@Options(useCache = false) //如果不设置为false, 则默认开启缓存, 即便你没有使用@Options注解
List<Phone> selectAll();

 

2、自增主键

2.1 使用@Options

在此情况下需要数据库支持生成自增主键,keyColumn用于设置为那个字段生成主键,keyProperty用于设置回显的属性,设置如下:

@Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id")
//@InsertProvider(type = PhoneProvider.class, method = "insert")
@Insert(value = "insert into phone values(#{id}, #{phone}, #{type, javaType = com.bihai.mybatis_study.bean.PhoneTypeEnum, jdbcType=VARCHAR, typeHandler = org.apache.ibatis.type.EnumOrdinalTypeHandler})", databaseId = "mysql")
Boolean insertUseGeneratedKey(Phone phone);

 
测试:

/**
 * 数据库自带的自增主键测试
 */
@Test
public void test4(){
    try(SqlSession sqlSession = sqlSessionFactory.openSession()){
        AnnocationPhoneMapper mapper = sqlSession.getMapper(AnnocationPhoneMapper.class);
        Phone phone = new Phone();
        phone.setPhone("13467236809");
        phone.setType(PhoneTypeEnum.TYPE1);
        Boolean aBoolean = mapper.insertUseGeneratedKey(phone);
        System.out.println("是否插入成功:" + aBoolean + " id = " + phone.getId());
        sqlSession.commit();
    }
}
// 是否插入成功:true id = 23

 

2.2 使用@SelectKey

如果数据库不支持主键自增的话,并且你也没有传入id值,可以使用@SelectKey,但并不推荐:

 @SelectKey(before = true, keyProperty = "id", keyColumn = "id",resultType = String.class,statement = {
     "select CONCAT(\"NO: \",count(1)) from phone"
 })
//@InsertProvider(type = PhoneProvider.class, method ="insert")
@Insert(value = "insert into phone values(#{id}, #{phone}, #{type, javaType = com.bihai.mybatis_study.bean.PhoneTypeEnum, jdbcType=VARCHAR, typeHandler = org.apache.ibatis.type.EnumOrdinalTypeHandler})", databaseId = "mysql")
Boolean insertUseSelectKey(Phone phone);

 

五、@MapKey

@MapKey(value = "id")
@Select(value = "SELECT * FROM phone")
@ResultMap(value = "phoneMap")
Map<String,Phone> selectAllMapKey();

 

六、N - 1

1、方式一

先查询出phone信息,再通过phone的Id来查询user信息

public class AnnocationPhoneMapper{ 
    // -----------N - 1 通过电话id,查询出phone以及与之关联的user信息---------------
    @Results(id = "phoneUser", value = {
        @Result(id = true, property = "id", column = "id"),
        @Result(property = "phone", column = "phone"),
        @Result(column = "type", property = "type", javaType = PhoneTypeEnum.class, jdbcType = JdbcType.VARCHAR, typeHandler = EnumOrdinalTypeHandler.class),
        @Result(property = "user", column = "id",javaType = User.class, one = @One(
            fetchType = FetchType.LAZY,
            select = "com.bihai.mybatis_study.mapper.AnnocationUserMapper.selectUserByPhoneId"
        ))
    })
    @Select(value = "SELECT * FROM phone")
    List<Phone> selectPhoneUserAll();

}
------------------------------
 public interface AnnocationUserMapper {

    @Select(value = "SELECT * FROM user WHERE phoneId = #{value}")
    User selectUserByPhoneId(String phoneId);
}

尽管这样的查询进行延迟加载,当加载记录列表之后立刻就遍历列表以获取嵌套的数据,就会触发所有的延迟加载查询,性能可能会变得很糟糕。

 

2、方式二

//-------------N - 1 通过一个查询语句----------------

@Results(id = "phoneUserOne", value = {
    @Result(id = true, property = "id", column = "pId"),
    @Result(property = "phone", column = "phone"),
    @Result(column = "type", property = "type", javaType = PhoneTypeEnum.class, jdbcType = JdbcType.VARCHAR, typeHandler = EnumOrdinalTypeHandler.class),
    @Result(id = true, column = "id", property = "user.id"),
    @Result(column = "name", property = "user.name"),
    @Result(column = "phoneId", property = "user.phoneId"),
    @Result(column = "age", property = "user.age")
})
@Select(value = "SELECT p.id as pId, phone, type, u.* FROM phone p LEFT JOIN user u ON p.id = u.phoneId")
List<Phone> selectPhoneUserAllOne();

 

七、N - N

public interface AnnocationUserMapper {


    // ---------------N - N 查询user、phone信息------------
    @Results(id = "userPhone", value = {
        @Result(id = true, column = "id", property = "id"),
        @Result(column = "name", property = "name"),
        @Result(column = "phoneId", property = "phoneId"),
        @Result(column = "age", property = "age"),
        @Result(column = "phoneId", property = "phone", javaType = List.class, many = @Many(
            fetchType = FetchType.LAZY,
            select = "com.bihai.mybatis_study.mapper.AnnocationPhoneMapper.selectPhoneById"
        ))
    })
    @Select(value = "select * from user")
    List<User> selectUserPhoneAll();

}

----------------------------------------------
public class AnnocationPhoneMapper{    
    @ResultMap(value = "phoneMap")
    @Select(value = "SELECT * FROM phone WHERE id = #{value}")
    List<Phone> selectPhoneById(String id);
}

针对N - N的方式暂时没有找到一条语句就可以处理,并且全部使用注解的形式。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值