Mybatis框架 -- 连接池 动态SQL 多表关联查询

一、Mybatis 连接池

1. Mybatis中数据源分类
Mybatis dataSource分类.png
Mybatis将它自己的数据源分为三类:

  • UNPOOLED,不使用连接池的数据源
  • POOLED,使用连接池的数据源
  • JNDI,使用 JNDI 实现的数据源

2. Mybatis中数据源的配置

<environments default="mysql">
    <environment id="mysql">
        <!--事务管理器-->
        <transactionManager type="jdbc"/>
        <!--连接池配置-->
        <dataSource type="pooled">
            <!--获取配置文件中的key对应的值 -->
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
</environments>

MyBatis在初始化时,解析此文件,根据<dataSource>的 type 属性来创建相应类型的的数据源DataSource,即:

  • type="POOLED": MyBatis 会创建 Pooled DataSource 实例;

  • type="UNPOOLED" : MyBatis 会创建 Unpooled DataSource 实例;

  • type="JNDI": MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用。


二、Mybatis动态SQL

1. <if>

<!--条件查询:id、name-->
<!--ognl表达式语言 Object-Graph Navigation Language-->
<!--mybatis获取对象的值就用到了ognl表达式。开源的项目。-->
<select id="findByCondition" parameterType="queryvo" resultType="com.zz.entity.User">
    select * from user where 1=1
    <!-- 条件判断 -->
    <if test="user!= null and user.id != 0">
        and id=#{user.id}
    </if>
    <if test="user!= null and user.username != null">
        and username=#{user.username}
    </if>
</select>

2. <where>

<!--条件查询:id、name-->
<select id="findByCondition" parameterType="queryvo" resultType="com.zz.entity.User">
    select * from user
    <where>
        <!-- 条件判断 -->
        <if test="user!= null and user.id != 0">
            and id=#{user.id}
        </if>
        <if test="user!= null and user.username != null">
            and username=#{user.username}
        </if>
    </where>
</select>

3. <foreach>

<!--条件查询:id、name-->
<select id="findByCondition" parameterType="queryvo" resultType="com.itheima.entity.User">
    
    select * from user
    <where>
        <!-- 条件判断 -->
        <if test="user!= null and user.id != 0">
            and id=#{user.id}
        </if>
        <if test="user!= null and user.username != null">
            and username=#{user.username}
        </if>
        <!-- 根据多个id查询,需要遍历条件 -->
        <!--
        SELECT * FROM USER WHERE 1=1 and id IN (1,2)
        foreach 遍历集合
            collection 要遍历的集合
            item       临时变量存储当前遍历的集合的每一个元素
            open       拼接sql的开始
            close      拼接sql的结束
            seperator  分隔符,连接遍历的每一个值
        -->
        <if test="ids!=null and ids.size()>0">
            <foreach item="num" collection="ids" open="and id IN (" separator="," close=")">
                #{num}
            </foreach>
        </if>
    </where>
</select>

4. <include>

<!--定义通用的Sql片段-->
<sql id="selectUser">
    select * from user
</sql>

<!--条件查询:id、name-->
<select id="findByCondition" parameterType="queryvo" resultType="user">

    <!--引用Sql片段-->
    <include refid="selectUser"></include>
    <where>
        <!-- 条件判断 -->
        <if test="user!= null and user.id != 0">
            and id=#{user.id}
        </if>
        <if test="user!= null and user.username != null">
            and username=#{user.username}
        </if>
    </where>
</select>

注意:如果引用其它mapper.xml的sql片段,则在引用时需要加上namespace,如:<include refid="namespace.sql 片段"/>


三、Mybatis的多表关联查询

1. 一对一

实体类:

public class Account {

    private int accountId;
    private double money;
    //账户与用户一对一
    private User user;
	
	...
}

public class User {

    private int id;
    private String username;
    private String sex;
    private String address;
    private Date birthday;
    //一个用户有多个账户
    private List<Account> accounts;

	...
}

AccountDao接口:

public interface AccountDao {

    List<Account> findAccountByUserId(int userId);
}

AccountDao.xml

<mapper namespace="com.zz.dao.AccountDao">

    <resultMap id="userResultMap" type="account">
        <!--1.先封装账户信息-->
        <id property="accountId" column="accountId" />
        <result property="money" column="money"/>

        <!--2.封装用户信息-->
        <!--
        association 一对一关系配置。可以给Account的对象的user属性封装数据
            property 要封装的对象的属性
            javaType 对象类型
            column   外键字段(账户的用户id外键)
        -->
        <association property="user" javaType="com.zz.entity.User" column="uid">
            <!--封装用户信息-->
            <id property="id" column="id"/>
            <result property="username" column="username"/>
            <result property="sex" column="sex"/>
            <result property="address" column="address"/>
            <result property="birthday" column="birthday"/>
        </association>
    </resultMap>
    
    <!--查询(把账户、用户都通过连接查询查询出来)-->
    <select id="findAccountByUserId" parameterType="int" resultMap="userResultMap">
        SELECT a.*,u.* FROM account a INNER JOIN USER u ON a.uid=u.id where a.uid=#{userId}
    </select>
</mapper>

2. 一对多

UserDao接口:

public interface UserDao {

    //查询全部用户,同时还要查询出用户对应的全部账户信息)
    List<User> findAll();
}

UserDao.xml

<mapper namespace="com.zz.dao.UserDao">

    <!--通过resultMap封装结果数据-->
    <resultMap id="accountResultMap" type="user">
        <!--1.封装用户信息-->
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="sex" column="sex"/>
        <result property="address" column="address"/>
        <result property="birthday" column="birthday"/>
        <!--2.封装账户集合-->
        <!--
        collection 一对多配置
            property 集合属性
            ofType   集合元素类型
            javaType (可选)表示集合的类型:java.util.List
            column   (可选)表示用户的主键:id
        -->
        <collection property="accounts" ofType="com.zz.entity.Account" >
            <id property="accountId" column="accountId" />
            <result property="money" column="money"/>
        </collection>
    </resultMap>

    <!--查询(把用户、用户的账户都通过关联查询查询出来)-->
    <select id="findAll" resultMap="accountResultMap">
        SELECT u.*,a.* FROM USER u LEFT JOIN account a  ON a.uid=u.id
    </select>
</mapper>

3. 多对多

多对多可以理解为双向一对多


四、常见SQL

1. 注解中判断某个字符串参数是否为null或者空字符串

<when>:
@Select({"<script>",
        "select * from user_info where 1=1",
        "<when test='name!=null and name!=\"\"'>",
        "and name = #{name}",
        "</when>",
        "<when test='password!=null and password!=\"\"'>",
        "and password= #{password}",
        "</when>",
        "</script>"})
public User selectByNamePassword(String name,String password);

<if>:
@Select({"<script>",
        "select * from user_info where 1=1",
        "<if test='name!=null and name!=\"\"'>",
        "and name = #{name}",
        "</if>",
        "<if test='password!=null and password!=\"\"'>",
        "and password= #{password}",
        "</if>",
        "</script>"})
public User selectByNamePassword(String name,String password);

2. Mybatis插入数据时获取自增的主键Id

  • ServiceImpl
@Override
public void insertProject(String areaName, String project, String status) {

    try {
    	// 查找areaId,未找到则插入area表中
        Integer areaId = areaMapper.findAreaId(areaName);
        if (areaId == null) {
            Area area = new Area();
            area.setAreaName(areaName);
            area.setStatus(0);
            areaMapper.insertArea(area);
            // 获取主键
            areaId = area.getAreaId();
        }
        projectMapper.insertProject(project, areaId, status);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
/**
 * 表AREA_T插入数据,获取自增主键 AreaId
 * keyProperty: 主键实体类属性名   keyColumn: 主键表列名
 */
@Insert("insert into AREA_T(area_name,del_flag) values(#{areaName},#{status});")
@Options(useGeneratedKeys = true, keyProperty = "areaName", keyColumn = "area_name")
void insertArea(Area area);

注:现在不用注解即可,MyBatis插入area后,area的主键会被MyBatis返回并赋值,直接用get方法即可获取到主键ID,即使不是自增主键也可获取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值