MyBatis框架使用过程中出现的问题以及解决方案

目录

使用场景:

数据库内容:

 实体类以及映射文件内容:

Employee映射文件:

Department映射文件:

mysql核心配置文件:

问题描述1

原因分析1:

解决方案1:

 问题描述2

原因分析2:

解决方案2:

 问题描述3

原因分析3:

解决方案3:

 问题描述4

原因分析4:

解决方案4:

 问题描述5

原因分析5:

解决方案5:

总结:

使用场景:

使用MyBatis框架对于员工实体以及部门实体进行添加、按条件查询时出现的问题。


数据库内容:

 

 实体类以及映射文件内容:

实体类(get()、set()方法以及toString()方法省略):

package com.apesource.entity;

// 员工实体类
public class Employee {
	private int empId; // 员工编号
	private String empName; // 员工姓名
	private double empSalary; // 月薪
	private Department dept; // 所在部门
	private String phoneNumber; // 手机号码
	
	// 无参构造
	public Employee() {
		
	}
	
	// 有参构造
	public Employee(String empName, double empSalary, int deptNo, String phoneNumber) {
		this.empName = empName;
		this.empSalary = empSalary;
		this.dept = new Department();
		this.dept.setDeptNo(deptNo);
		this.phoneNumber = phoneNumber;
	}
	
}
package com.apesource.entity;

import java.util.List;

// 部门实体类
public class Department {
	private int deptNo; // 部门编号
	private String deptName; // 部门名称
	private String deptManager; // 部门经理
	private List<Employee> employeeList; // 属于该部门的员工集合
	
	
	
}

Employee映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.apesource.mapper.EmployeeMapper">
	
	<!-- 添加新员工 -->
	<insert id="insertNewEmployee">
		INSERT INTO employee_info
		(emp_name, dept_id, emp_salary, phone_number)
		VALUES (#{empName},#{dept},#{empSalary}, #{phoneNumber})
	</insert>
	
	<!-- 按照指定部门名称列表查询 -->
	<resultMap type="com.apesource.entity.Employee" id="selectResult">
		<id column="emp_id" property="empId"/>
		<result column="emp_name" property="empName"/>
		<result column="phone_number" property="phoneNumber"/>
		<result column="emp_salary" property="empSalary"/>
		<association property="dept" javaType="com.apesource.entity.Department">
			<id column="dept_id" property="deptNo"/>
			<result column="dept_name" property="deptName"/>
			<result column="dept_manager" property="deptManager"/>
		</association>
	</resultMap>
	
	<select id="selectEmployeeListInDeptNames" resultType="selectResult">
		SELECT * FROM employee_info ei
		INNER JOIN department_info di ON ei.dept_id = di.dept_id
		WHERE dept_name IN
		<foreach collection="list" item="item" separator="," open="(" close=")">
			#{item}
		</foreach>
	</select>
	
	
	<!-- 按照员工姓名进行模糊查询,并按照员工编号,排序规则由OrderMode指定 -->
	<select id="selectWebsiteListLikeName" resultMap="selectResult">
		SELECT * FROM employee_info ei
		INNER JOIN department_info di ON ei.dept_id = di.dept_id
		WHERE emp_name LIKE concat('%',#{empName},'%') 
		ORDER BY emp_id ${order}
	</select>
	
	<!-- 按照条件进行动态查询 -->
	<select id="selectEmployeeListByCondition" resultMap="selectResult">
		SELECT * FROM department_info AS di
		INNER JOIN employee_info as ei ON di.dept_id = ei.dept_id 
		<where>
			<if test="empName != null and empName !=''">
				and emp_name like concat('%',#{empName},'%')
			</if>
			<if test="empSalary != null and empSalary !=''">
				and emp_salary &lt;= #{empSalary}
			</if>
			<if test="phoneNumber != null and phoneNumber !=''">
				and phone_number = #{phoneNumber}
			</if>
		</where>
	</select>
	
	
	<!-- 统计每个部门的最高工资、最低工资、平均工资、工资总和、部门名称 -->
	<resultMap type="com.apesource.entity.Condition" id="result">
		<result column="dept_name" property="name"/>
		<result column="AVG(ei.emp_salary)" property="avg"/>
		<result column="MIN(ei.emp_salary)" property="min"/>
		<result column="MAX(ei.emp_salary)" property="max"/>
		<result column="SUM(ei.emp_salary)" property="sum"/>
	</resultMap>
	
	<select id="statisticEmployeeGroupDept" resultMap="result">
		SELECT di.dept_name,AVG(ei.emp_salary),MIN(ei.emp_salary),MAX(ei.emp_salary),SUM(ei.emp_salary)
		FROM employee_info ei
		INNER JOIN department_info di ON ei.dept_id = di.dept_id
		GROUP BY dept_name
		order by SUM(ei.emp_salary)
	</select>
</mapper>

Department映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.apesource.mapper.DepartmentMapper">
	<!-- 按照编号查询部门 -->
	<resultMap type="com.apesource.entity.Department" id="selectResultMap">
		<id column="dept_id" property="deptNo"/>
		<result column="dept_name" property="deptName"/>
		<result column="dept_manager" property="deptManager"/>
		<collection property="employeeList" ofType="com.apesource.entity.Employee">
			<id column="emp_id" property="empId"/>
			<result column="emp_name" property="empName"/>
			<result column="emp_salary" property="empSalary"/>
			<result column="phone_number" property="phoneNumber"/>
		</collection>
	</resultMap>
	
	<select id="selectDepartmentById" resultMap="selectResultMap">
		SELECT * FROM department_info di
		INNER JOIN employee_info ei ON di.dept_id = ei.dept_id
		WHERE di.dept_id = #{id}
	</select>
</mapper>

mysql核心配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!-- 框架参数设置 -->
    <settings>
      <!-- 日志 -->  
      <setting name="logImpl" value="LOG4J" />
    </settings>
  
    <!-- 配置mybatis运行环境(数据库) -->
    <environments default="development">
        <environment id="development">
            <!-- 使用JDBC的事务管理 -->
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <!-- MySQL数据库驱动 -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver" />
                
                <!-- 连接数据库的URL -->
                <property name="url" value="jdbc:mysql://localhost:3306/zhangyong?charset=utf8mb4&amp;useSSL=false&amp;useTimezone=true&amp;serverTimezone=GMT%2B8" />
                <property name="username" value="********" />
                <property name="password" value="*********" />
            </dataSource>
        </environment>
    </environments>
  
    <mappers>
    	<package name="com.apesource.mapper"/>
    </mappers>
</configuration>

问题描述1

执行任意方法时:提示Cause: java.lang.ClassNotFoundException: Cannot find class: com.mysql.cj.jdbc.Driver

 


原因分析1:

添加了MyBatis的核心驱动包以及相关jar包,但忘记添加mysql驱动包,导致无法连接到数据库,所以在加载MyBatis配置文件时出错。


解决方案1:

下载mysql核心驱动包mysql-connector-java-8.0.21.jar并配置到MyBatis框架中

mysql-connector-java-8.0.21.jar下载地址:Central Repository: mysql/mysql-connector-java/8.0.21


 问题描述2

在进行批处理添加员工时,控制台显示Could not set parameters for mapping: ParameterMapping{property='dept', mode=IN, javaType=class java.lang.Object

无法给Employee实体的dept属性赋值。

 


原因分析2:

Employee实体的字段的类型是Department,因此在设置mapper映射文件时#{dept}无法将值正确与Employee实体映射。


解决方案2:

在EmployeeMapper文件中,修改映射文件的字段,将dept修改为#{dept.deptNo}就可以了

数据库中数据也就正确添加进去了。

 


 问题描述3

在按照指定部门名称列表查询数据时,当解析映射文件时, 显示 Cause: org.apache.ibatis.builder.BuilderException: Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'selectResult'.

 


原因分析3:

在设置映射文件时,ResultMap元素误写为ResultType,导致数据库在解析到数据后,不知道应该以哪一种方式存。


解决方案3:

重新修改返回结果元素ResultType为ResultMap即可

       将resultMap元素修改后,就可以查询到数据了

 


 

 问题描述4

在按照员工姓名进行模糊查询,并按照员工编号,排序规则由OrderMode指定,同时传入两个参数,映射文件中依旧使用形参进行传参,控制台报Parameter 'order' not found. Available parameters are [arg1, arg0, param1, param2]

 


原因分析4:

在查询时,如果传入的是一个参数,那么映射文件中的传参可以是任意字符,但如果是多个字符,映射文件就无法找到具体参数,从而无法完成SQL语句的编写。

解决方案4:

一般多个参数的传递可以通过注解@param来保证映射文件能识别参数,也可以通过封装多个参数为一个实体类来进行传参,因为我只传递两个参数,所以选择注解传参。

 

 


 问题描述5

在查询指定部门时,查询字段有部门名称、部门经理、员工列表,SQL语句在映射文件中已经完整拼接了,但结果集无法显示,控制台显示: Could not set property 'employeeList' of 'class com.apesource.entity.Department' with value'com.apesource.entity.Employee@64bce832' 

 


 

 

原因分析5:

在映射文件中,JavaType元素是在单步查询一对一时才使用的元素,而一个部门对应了多个员工,这就形成了一对多的关系,所以此时应该使用元素ofType才能匹配一对多问题。


解决方案5:

将collection标签中的javaType元素修改为ofType元素即可。

 

总结:

MyBatis作为一款完全开源的框架,对于原生的JDBC做了一个很好封装,简化了我们对于JDBC的操作,将更多的精力放在注重SQL映射文件上,给程序的维护带来了很大的便利,我们也可以结合数据库自身的特点灵活的控制SQL语句,因此能够实现比Hibernate等全自动ORM框架更高的查询效率,高效的完成复杂查询。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值