Mybatis-语法笔记

返回主键

1.XML方式

<insert id="bb" parameterType="XX.XX.XXEntity包" useGeneratedKeys="true" keyProperty="id">
 这里是insert语句
</insert> 

2.注解方式,要在接口方法上加两个注解,一个是insert,一个是selectKey

@Insert("这里是insert语句")
@SelectKey(statement = "SELECT last_insert_id() as id", keyProperty = "id", before = false, resultType = String.class, statementType = StatementType.STATEMENT)
//entity里要有id这个属性并且有getset方法,上面的resultType要注意,你的entity里的id是什么属性,就写什么,我的id是String,所以我写String.class,如果你的是int,那么请写Integer.class
public int insert(实体类 entity);

循环

本文展示了这样一个业务:根据多个ID删除多条数据

public Integer 方法名AA(@Param("bb") String[] ids);

1.Mybatis接口方式,接口方式的循环通常很好些,因为@param可以指定名字

<delete id="方法名AA" resultMap="如果是查询记得写返回值类型">
	  delete from 表 where id in
	  //如果是批量插入记得删掉open和close属性
	  <foreach collection="bb" item="item" index="index" open="("
	   separator="," close=")">
	   #{item}
	  </foreach>
</delete>

2.Mybatis映射方式,如果使用映射方式,bb如果不放到map中,那么mybatis会把他的名字变成list,所以如下写,不再用item属性了

<delete id="方法名AA" resultMap="如果是查询记得写返回值类型">
	  delete from 表 where id in
	  //如果是批量插入记得删掉open和close属性
	  <foreach collection="list"  index="index" item="aaa" open="("
	   separator="," close=")">
	   #{list[${index}]}
	  </foreach>
</delete>

注: 当mybatis以映射方式循环的时候,你们会发现循环语句中有个item=“aaa”,虽然我下面没有用到这个,但是item必须写,哪怕是item=“bbb”,item=“ccc”,必须要写,否则mybatis报错

加前缀后缀覆盖

下面的例子展示了如果传递用户名称,则将用户名称userName和年龄userAge作为条件进行或查询,但是由于前面有一个逻辑删除表示is_deleted = 0,这导致如果不进行特殊处理,后面name+age无法在一个括号里,但是如果在一个括号里(所以使用prefix+suffix),并且name前面的OR要消失,所以使用prefixOverrides

select * from 表 
where
is_deleted = 0
<trim prefix="(" suffix=")" prefixOverrides="OR">
    <if test="userName=null and userName!=''">
        OR t1.`name` = #{userName}
    </if>
    <if test="userAge=null and userAge!=''">
        OR t1.`age` = #{userAge}
    </if>
</trim>

递归

下面的示例展示了获取性别是’男’的人下面所有的子孙,新建一个entity,如下

public class User{
	private String name;
	public List<User> children;
	// 示例省略get set
}

dao接口(mapper)中有个方法,这个方法获取递归结构

public interface UserMapper{
	List<User> getRecursionTree(@Param("parentId") String parentId, @Param("sex") String sex);
}

sql.xml写法如下

<resultMap id="RecursionBaseResultMap" type="User">
     <id column="id" property="id"/>
     <result column="name" property="name"/>
     <result column="parent_id" property="parentId"/>
     <collection column="id" property="children" select="getChildren">
     <!-- 
     	column=id表示表中id字段作为下一个层级的parentId,
     	也就是说这个id,会自动作为内层sql getChildren的
     	#{pid},无论内层sql的parent_id = #{这里写什么都可以},
     	因为内层sql只有一个值,所以会自动将id匹配到内层sql的#{pid}
		property=children对应User类的children字段
		select=getChildren对应下面的内层sql的id字段
      -->
     </collection>
 </resultMap>
    
<!-- 外层sql -->
<!-- 注意resultMap和最上边的对应上 -->
<select id="getRecursionTree" resultMap="RecursionBaseResultMap">
    select *
    from scheme_scope
    where parent_id = #{pid}
      and sex= #{sex}
</select>


<!-- 内层sql -->
<!-- 注意resultMap和最上边的对应上 -->
<select id="getChildren" resultMap="RecursionBaseResultMap">
    select * from user
    where parent_id = #{pid}
</select>

Sql入参为Map

入参为map一般情况都是JSON_SET业务场景,不然用map不是智力有问题吗
Dao接口如下

void updateWuhan(@Param("wuhanMap") Map<String, String> wuhanMap);

SQL XML

<update id="updateWuhan">
        UPDATE 表
        SET 列1=JSON_SET(1,
        <foreach collection="wuhanMap" index="key" item="value"
                 separator=",">
            CONCAT("$.",#{key}),#{value}
        </foreach>
        )
</update>

Sql返回值为Map

这个功能通常用于批量查询,主要操作就是@MapKey注解

Dao接口如下

@MapKey("userId")
Map<String, UserEntity> findUserMap(@Param("userIds") List<Integer> userIds);

XML的sql正常写就行,没什么特殊的,如下

<select id="findUserMap" resultType="xxx.xxx.UserEntity">
	   SELECT * FROM user WHERE user_id IN
	   <if test="userIds!= null and userIds.size() > 0">
	       <foreach collection="userIds" item="userId" open="(" separator="," close=")">
	           #{userId}
	       </foreach>
	   </if>
</select>

Sql入参为枚举

注:这个操作需要TypeHandler,后文有自定义TypeHandler

假设有个性别枚举类,如下

public enum UserSex {
	WOMEN,
    MAN;
}

恰好数据库中sex字段0表示女,1表示男,如果要查询所有性别是男的数据,则
dao层接口如下

public interface UserMapper{
	List<User> findBySex(@Param("sex") UserSex sex);
}

sql.xml如下

<select id="findBySex" resultType="xxx.xxx.UserEntity">
    select * from `user`
    where sex = #{sex,javaType=com.xxx.UserSex,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}
</select>

NOTE:根据枚举名称取值的解析器是org.apache.ibatis.type.EnumTypeHandler

Sql返回值为枚举

实现这个其实就是自定义TypeHandler(我个人觉得叫TypeResolver更好理解一些)

上个例子已经说过,枚举其实就是使用的mybatis自己实现的TypeHandler,具体实现是EnumTypeHandler,下面的例子阐述我们自己实现一个TypeHandler,假设我的数据库中是下面这个样子的,如图
在这里插入图片描述
当我查询的时候,我希望返回如下数据结构:

public class Order {
	private String id;
	private String orderNum;
	private List<OrderDetail> details;// 注意此处
}
public class OrderDetail{
	private String key;
	private String value;
}

很明显可以看到order_detail字段,应该对应2个OrderDetail实例,那么如何把{"name":"皮冻","type":"英短"}这个JSON字符串变成2个OrderDetail实例呢?需要两步
1.创建一个解析器(TypeHandler)
2.在SQL XML中指定order_detail字段使用该解析器

自定义解析器(TypeHandler)

public class SwtTypeHandler implements TypeHandler<List<OrderDetail>> {

    @Override
    public void setParameter(PreparedStatement ps, int i, List<OrderDetail> parameter, JdbcType jdbcType) throws SQLException {
        // NOOP
        // 此处可能查询带参数的时候会使用???
        // 因为源码没有注释,而且我自己也没有测试此处,以后需要的时候再补此处吧
    }

    @Override
    public List<OrderDetail> getResult(ResultSet rs, String columnName) throws SQLException {
        String updateText = rs.getString(columnName);
        return parseDetails(updateText);
    }

    @Override
    public List<OrderDetail> getResult(ResultSet rs, int columnIndex) throws SQLException {
        String updateText = rs.getString(columnIndex);
        return parseDetails(updateText);
    }

    @Override
    public List<OrderDetail> getResult(CallableStatement cs, int columnIndex) throws SQLException {
        String updateText = cs.getString(columnIndex);
        return parseDetails(updateText);
    }

    public List<OrderDetail> parseDetails(String updateText) {
        if (StringUtils.hasLength(updateText)) {
            List<OrderDetail> detailList= new ArrayList<>();
            JSONObject jsonObject = JSON.parseObject(updateText);
            for (String element : jsonObject.keySet()) {
            	OrderDetail detail = new OrderDetail();
            	detail.setKey(element);
            	detail.setValue(jsonObject.getString(element));
                detailList.add(detail);
            }
            return detailList;
        }
        return new ArrayList<>();
    }
}

SQL XML

<resultMap id="Test666" type="com.xx.xx.Order">
        <id column="id" jdbcType="INTEGER" property="id"/>
        <result column="order_num" jdbcType="VARCHAR" property="orderNum"/>
        <result column="order_detail" 		<!--对应数据库的字段-->
        		property="details"			<!--对应entity的字段-->
                javaType="java.util.List"	<!--entity中该字段的类型-->
                <!--通过SwtTypeHandler解析器将数据库中order_detail字段的值,转换成entity中detils字段的值-->
                typeHandler="com.xx.xx.SwtTypeHandler"/> 
    </resultMap>

    <select id="随便起个名字" resultMap="Test666">
        select * from `order`
    </select>
MyBatis是一种开源持久层框架,它可以帮助我们实现将Java对象映射到关系型数据库中的数据。下面是MyBatis的详细笔记: 1. MyBatis的介绍 MyBatis是一种Java持久层框架,它可以帮助我们实现将Java对象映射到关系型数据库中的数据。MyBatis是一种比较灵活的框架,它不会对应用程序中的Java对象进行任何修改,而是直接使用对象。 2. MyBatis的核心组件 MyBatis的核心组件包括SqlSessionFactory、SqlSession、Mapper和XML映射文件。 SqlSessionFactory:SqlSessionFactory是MyBatis的核心组件之一,它负责创建SqlSession对象。它是线程安全的,因此可以被多个线程共享。 SqlSession:SqlSession是MyBatis的另一个核心组件,它提供了与数据库交互的方法,包括查询、插入、更新和删除。SqlSession是非线程安全的,因此每个线程都应该有自己的SqlSession对象。 Mapper:Mapper是一个接口,它定义了与数据库交互的方法。MyBatis可以根据Mapper接口创建代理对象,从而实现对数据库的访问。 XML映射文件:XML映射文件定义了Java对象与数据库表之间的映射关系。它包含了SQL语句、参数映射和结果映射等信息。 3. MyBatis的配置 MyBatis的配置文件包括以下几个部分: 数据源配置:数据源是与数据库建立连接的入口。MyBatis支持多种数据源,包括JDBC、C3P0和Druid等。 事务管理器配置:MyBatis支持事务管理,可以通过配置事务管理器来实现事务控制。 Mapper配置:Mapper接口与XML映射文件的配置。 4. MyBatis的使用 MyBatis的使用可以分为以下几个步骤: 创建SqlSessionFactory对象:SqlSessionFactory是MyBatis的核心组件之一,它负责创建SqlSession对象。 创建SqlSession对象:SqlSession是MyBatis的另一个核心组件,它提供了与数据库交互的方法,包括查询、插入、更新和删除。 执行SQL语句:MyBatis支持多种SQL语句,包括查询、插入、更新和删除等。 关闭SqlSession对象:SqlSession是非线程安全的,因此每个线程都应该有自己的SqlSession对象。使用完SqlSession对象后应该将其关闭,以释放资源。 5. MyBatis的优点 MyBatis具有以下优点: 灵活性:MyBatis是一种比较灵活的框架,它不会对应用程序中的Java对象进行任何修改,而是直接使用对象。 易于使用:MyBatis的使用非常容易,可以通过简单的配置文件和Mapper接口来实现对数据库的访问。 高效性:MyBatis的性能非常高,它可以通过SQL语句的优化来提高查询的效率。 6. MyBatis的缺点 MyBatis的缺点包括以下几个方面: 学习曲线较陡峭:MyBatis的学习曲线比较陡峭,需要一定的Java和SQL知识才能使用。 XML映射文件较复杂:MyBatis的XML映射文件比较复杂,需要深入了解其语法和规则才能编写正确的映射文件。 7. 总结 MyBatis是一种开源持久层框架,它可以帮助我们实现将Java对象映射到关系型数据库中的数据。MyBatis具有灵活、易于使用和高效等优点,但学习曲线较陡峭,XML映射文件较复杂。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值