软件设计之SSM(8)

软件设计之SSM(8)

路线图推荐:
【Java学习路线-极速版】【Java架构师技术图谱】
尚硅谷新版SSM框架全套视频教程,Spring6+SpringBoot3最新SSM企业级开发
资料可以去尚硅谷官网免费领取

学习内容:

Mybatis

  1. 数据输出
  2. 多表映射
  3. 动态语句

1、数据输出

数据输出总体上有两种形式:

  • 增删改操作返回的受影响行数:直接使用 int 或 long 类型接收即可
  • 查询操作的查询结果

单个简单类型

指定返回值类型就是指定resultType

  1. 类的全限定符号
<select id = "queryNameById" resultType ="java.lang.String">
</select>
  1. 别名简称
    mybatis 提供了72种默认别名,基于常用的数据类型
  • 基本数据类型 intdouble -> _int_double
  • 包装数据类型 IntegerDouble ->intdouble
  • 集合容器类型MapList -> maplist
  1. 自定别名
<!-- 给类单独定义别名-->
<typeAliases>
  <typeAlias alias="worker" type="com.atguigu.Employee"/>
</typeAliases>
<!-- 批量将包下的类定义别名,别名是类首字母小写-->
<typeAliases>
  <package name="com.atguigu.pojo"/>
</typeAliases>

实体对象类型

在 MyBatis 中,返回单个实体类型时,“列名与属性名一致” 是指:数据库查询结果中的列名需要与 Java 实体类(POJO)中的属性名相匹配,以便 MyBatis 能够正确地将 SQL 查询结果映射为 Java 对象。

mybatis-config.xml设置里,支持驼峰式自动映射。
即: emp_id --> empId

<!-- 在全局范围内对Mybatis进行配置 -->
<settings>
 
  <!-- 具体配置 -->
  <!-- 从org.apache.ibatis.session.Configuration类中可以查看能使用的配置项 -->
  <!-- 将mapUnderscoreToCamelCase属性配置为true,表示开启自动映射驼峰式命名规则 -->
  <!-- 规则要求数据库表字段命名方式:单词_单词 -->
  <!-- 规则要求Java实体类属性名命名方式:首字母小写的驼峰式命名 -->
  <setting name="mapUnderscoreToCamelCase" value="true"/>

</settings>

List类型

查询结果返回多个实体类对象,希望把多个实体类对象放在List集合中返回。此时不需要任何特殊处理,在resultType属性中还是设置实体类类型即可

List<Employee> selectAll();
<!-- List<Employee> selectAll(); -->
<select id="selectAll" resultType="com.atguigu.mybatis.entity.Employee">
  select emp_id empId,emp_name empName,emp_salary empSalary
  from t_emp
</select>

返回主键值

  1. 主键回显:是指在数据库执行插入操作时,数据库会自动生成并返回插入数据的主键值
  2. 自增长类型主键
<!-- int insertEmployee(Employee employee); -->
<!-- useGeneratedKeys属性字面意思就是“使用生成的主键” -->
<!-- keyProperty属性可以指定主键在实体类对象中对应的属性名,Mybatis会将拿到的主键值存入这个属性 -->
<insert id="insertEmployee" useGeneratedKeys="true" keyProperty="empId">
  insert into t_emp(emp_name,emp_salary)
  values(#{empName},#{empSalary})
</insert>
  1. 非自增长类型主键
    插入 UUID 作为字符串类型主键
<insert id="insertUser" parameterType="User">
    <selectKey keyProperty="id" resultType="java.lang.String"
        order="BEFORE">
        SELECT UUID() as id
    </selectKey>
    INSERT INTO user (id, username, password) 
    VALUES (
        #{id},
        #{username},
        #{password}
    )
</insert>

ResultMap自定义映射

实体类属性和数据库字段对应
使用resultMap标签定义对应关系,再在后面的SQL语句中引用这个对应关系

<!-- 专门声明一个resultMap设定column到property之间的对应关系 -->
<resultMap id="selectEmployeeByRMResultMap" type="com.atguigu.mybatis.entity.Employee">

  <!-- 使用id标签设置主键列和主键属性之间的对应关系 -->
  <!-- column属性用于指定字段名;property属性用于指定Java实体类属性名 -->
  <id column="emp_id" property="empId"/>

  <!-- 使用result标签设置普通字段和Java实体类属性之间的关系 -->
  <result column="emp_name" property="empName"/>

  <result column="emp_salary" property="empSalary"/>

</resultMap>

<!-- Employee selectEmployeeByRM(Integer empId); -->
<select id="selectEmployeeByRM" resultMap="selectEmployeeByRMResultMap">

  select emp_id,emp_name,emp_salary from t_emp where emp_id=#{empId}

</select>

2、多表映射

实体类设计

对一,属性中包含对方对象

对多,属性中包含对方对象集合

只有真实发生多表查询时,才需要设计和修改实体类,否则不提前设计和修改实体类!

无论多少张表联查,实体类设计都是两两考虑!

在查询映射的时候,只需要关注本次查询相关的属性!例如:查询订单和对应的客户,就不要关注客户中的订单集合!

public class Customer {

  private Integer customerId;
  private String customerName;
  private List<Order> orderList;// 体现的是对多的关系
}

public class Order {

  private Integer orderId;
  private String orderName;
  private Customer customer;// 体现的是对一的关系
  
}

//查询客户和客户对应的订单集合  不要管!

对一映射

在MyBatis中实现多表映射时,常见的场景之一是对一映射,即一个实体类关联另一个实体类的情况。这通常用于像“用户-地址”这样的关系。实现步骤主要包括:

假设有两个表 User 和 Address,用户表(User)地址表(Address)之间存在一对一的关系。
流程:
在这里插入图片描述
UserMapper.xml:

<mapper namespace="com.example.mapper.UserMapper">
    <resultMap id="UserResultMap" type="com.example.domain.User">
        <id property="id" column="user_id"/>
        <result property="name" column="user_name"/>
        
        <!-- 对一映射 -->
        <association property="address" javaType="com.example.domain.Address">
            <id property="id" column="address_id"/>
            <result property="street" column="street"/>
            <result property="city" column="city"/>
        </association>
    </resultMap>

    <!-- 查询语句 -->
    <select id="selectUserById" resultMap="UserResultMap">
        SELECT u.id AS user_id, u.name AS user_name, a.id AS address_id, a.street, a.city
        FROM User u
        JOIN Address a ON u.address_id = a.id
        WHERE u.id = #{id};
    </select>
</mapper>

对多映射

在MyBatis中,对多映射(一对多)通常用于表示“一个实体类包含多个子类”的关系,比如“一个用户有多个订单”的场景。MyBatis 提供了collection标签来处理这种一对多映射。

假设有两个表:User 和 Order,用户(User)订单(Order)之间是一对多的关系。
流程:
在这里插入图片描述
UserMapper.xml:

<mapper namespace="com.example.mapper.UserMapper">
    <!-- 配置 UserResultMap -->
    <resultMap id="UserResultMap" type="com.example.domain.User">
        <id property="id" column="user_id"/>
        <result property="name" column="user_name"/>

        <!-- 一对多映射 -->
        <collection property="orders" ofType="com.example.domain.Order">
            <id property="id" column="order_id"/>
            <result property="orderNumber" column="order_number"/>
            <result property="userId" column="user_id"/>
        </collection>
    </resultMap>

    <!-- 查询语句 -->
    <select id="selectUserById" resultMap="UserResultMap">
        SELECT u.id AS user_id, u.name AS user_name, o.id AS order_id, o.order_number, o.user_id
        FROM User u
        LEFT JOIN `Order` o ON u.id = o.user_id
        WHERE u.id = #{id};
    </select>
</mapper>

3、动态语句

JDBC字符串拼接

繁琐: 随着查询条件的增加,SQL 语句的拼接会变得复杂,代码不易维护。
易错: 手动拼接容易遗漏空格、标点等,导致语法错误。
安全问题: 手动拼接 SQL 会引发 SQL 注入风险,如果参数未经正确处理,攻击者可以插入恶意 SQL。

String sql = "SELECT * FROM User WHERE 1=1";
if (name != null) {
    sql += " AND name = '" + name + "'";  // 手动拼接参数,易引发 SQL 注入风险
}
if (age != null) {
    sql += " AND age = " + age;
}
PreparedStatement ps = conn.prepareStatement(sql);

if和where标签

<if> 标签用于根据传入的参数或条件决定是否生成某段 SQL 语句。它通常与条件判断结合使用,能够根据不同的输入动态调整查询、插入或更新的 SQL 逻辑。

<where> 标签主要用于动态构建 WHERE 子句,它不仅能动态生成条件,还能自动处理 SQL 语句开头的逻辑连接符(如 AND、OR 等)。如果在没有任何条件时,<where> 标签会去除 SQL 中无效的 WHERE 子句。

<!-- List<Employee> selectEmployeeByCondition(Employee employee); -->
<select id="selectEmployeeByCondition" resultType="employee">
    select emp_id,emp_name,emp_salary from t_emp
    <!-- where标签会自动去掉“标签体内前面多余的and/or” -->
    <where>
        <!-- 使用if标签,让我们可以有选择的加入SQL语句的片段。这个SQL语句片段是否要加入整个SQL语句,就看if标签判断的结果是否为true -->
        <!-- 在if标签的test属性中,可以访问实体类的属性,不可以访问数据库表的字段 -->
        <if test="empName != null">
            <!-- 在if标签内部,需要访问接口的参数时还是正常写#{} -->
            or emp_name=#{empName}
        </if>
        <if test="empSalary &gt; 2000">
            or emp_salary>#{empSalary}
        </if>
        <!--
         第一种情况:所有条件都满足 WHERE emp_name=? or emp_salary>?
         第二种情况:部分条件满足 WHERE emp_salary>?
         第三种情况:所有条件都不满足 没有where子句
         -->
    </where>
</select>

foreach标签

在 MyBatis 中,<foreach> 标签用于处理 SQL 语句中的批量操作,例如批量插入、批量更新或者在 IN 子句中传递多个参数。它能够遍历集合或数组,并动态生成 SQL 语句,避免手动拼接多个参数,代码更加简洁、可维护。

<select id="selectUsersByIds" resultType="User">
    SELECT * FROM User WHERE id IN
    <foreach collection="list" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>
</select>

参数传递:

List<Integer> ids = Arrays.asList(1, 2, 3, 4);
List<User> users = userMapper.selectUsersByIds(ids);

生成的 SQL 语句为:

SELECT * FROM User WHERE id IN (1, 2, 3, 4);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值