1、搭建数据库
tbl_employee表【d_id 是外键 对应 tbl_dept表】
id last_name gender email d_id 1 mike 0 [email protected] 1 2 book 0 [email protected] 2 3 tom 1 [email protected] 2 4 jerry 1 [email protected] 1
tbl_dept表:
id dept_name 1 开发部 2 测试部
2、编辑 javabean
Employee.java
package com.mybatis.bean; public class Employee { private int id; private String lastName; private String email; private String gender; private Department department; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } @Override public String toString() { return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + "]"; } }
Department.java
package com.mybatis.bean; import java.util.List; public class Department { private Integer id; private String departmentName; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getDepartmentName() { return departmentName; } public void setDepartmentName(String departmentName) { this.departmentName = departmentName; } @Override public String toString() { return "Department [id=" + id + ", departmentName=" + departmentName + "]"; } }
3、编辑接口文件
EmployeeMapper.java
package com.mybatis.mapper; import java.util.List; import com.mybatis.bean.Employee; public interface EmployeeMapper { public Employee getEmpByIdStep(Integer id); }
DepartmentMapper.java
package com.mybatis.mapper; import com.mybatis.bean.Department; public interface DepartmentMapper { public Department getDeptById(Integer id); }
4、编辑sql映射文件
DepartmentMapper.xml
<?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.mybatis.mapper.DepartmentMapper"> <!--public Department getDeptById(Integer id); --> <select id="getDeptById" resultType="com.mybatis.bean.Department"> select id,dept_name departmentName from tbl_dept where id=#{id} </select> </mapper>
EmployeeMapper.xml
<?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.mybatis.mapper.EmployeeMapper"> <!--自定义某个javaBean的封装规则 type:自定义规则的Java类型 id:唯一id方便引用 --> <!-- 使用association进行分步查询: 1、先按照员工id查询员工信息 2、根据查询员工信息中的d_id值去部门表查出部门信息 3、部门设置到员工中; --> <!-- id last_name email gender d_id --> <resultMap type="com.mybatis.bean.Employee" id="MyEmpByStep"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> <!-- association定义关联对象的封装规则 select:表明当前属性是调用select指定的方法查出的结果 column:指定将哪一列的值传给这个方法 流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性 --> <association property="department" select="com.mybatis.mapper.DepartmentMapper.getDeptById" column="d_id"> </association> </resultMap> <!-- public Employee getEmpByIdStep(Integer id);--> <select id="getEmpByIdStep" resultMap="MyEmpByStep"> select * from tbl_employee where id=#{id} <if test="_parameter!=null"> and 1=1 </if> </select> </mapper>
5、编辑全局配置文件:
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis" /> <property name="username" value="root" /> <property name="password" value="Kitty521!" /> </dataSource> </environment> </environments> <!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 如果 数据库全局文件 和 子配置文件 不在同一个目录 ,就需要 /目录/目录/.../EmployeeMapper_old.xml --> <mappers> <!-- 新方法操作mybatis 需要 的配置文件 --> <mapper resource="EmployeeMapper.xml" /> </mappers> </configuration>
特别强调,上面的配置文件忘记添加了<mapper resource="DepartmentMapper.xml" />
<mappers> <!-- 因为涉及到分步查询,所以每一步,查询语句都要注册好, 一开始下面第一句 sql 映射文件 没有注册,结果就报错了 --> <mapper resource="DepartmentMapper.xml" /> <mapper resource="EmployeeMapperPlus.xml" /> </mappers>
因为没有添加<mapper resource="DepartmentMapper.xml" />
导致报错结果:
org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.mybatis.mapper.DepartmentMapper.getDeptById ### The error may exist in EmployeeMapperPlus.xml ### The error may involve com.mybatis.mapper.EmployeeMapperPlus.getEmpByIdStep ### The error occurred while handling results ### SQL: select * from tbl_employee where id=? and 1=1 ### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.mybatis.mapper.DepartmentMapper.getDeptById at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30) at
所以一定要添加啊,<mapper resource="DepartmentMapper.xml" />
6、单元测试:
package com.mybatis.test; import java.io.IOException; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import com.mybatis.bean.Employee; import com.mybatis.mapper.EmployeeMapperPlus; /** * 1、接口式编程 * 原生: Dao ====> DaoImpl * mybatis: Mapper ====> xxMapper.xml * * 2、SqlSession代表和数据库的一次会话;用完必须关闭; * 3、SqlSession和connection一样她都是非线程安全。每次使用都应该去获取新的对象。(就是不要放在共享成员变量里面,A线程用完释放,B线程再用就为空了) * 4、mapper接口没有实现类,但是mybatis会为这个接口生成一个代理对象。 * (将接口和xml进行绑定) * EmployeeMapper empMapper = sqlSession.getMapper(EmployeeMapper.class); * 5、两个重要的配置文件: * mybatis的全局配置文件:包含数据库连接池信息,事务管理器信息等...系统运行环境信息 * sql映射文件:保存了每一个sql语句的映射信息: * 将sql抽取出来。 * */ public class MybatisTest { /********************************************************************/ public SqlSessionFactory getSqlSessionFactory() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); return new SqlSessionFactoryBuilder().build(inputStream); } @Test public void test_new() throws IOException { // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class); Employee employee = mapper.getEmpByIdStep(1); System.out.println(mapper.getClass()); System.out.println(employee); System.out.println(employee.getDepartment()); } finally { openSession.close(); } } }
7、延迟加载
<!-- 可以使用延迟加载(懒加载);(按需加载) Employee==>Dept: 我们每次查询Employee对象的时候,都将一起查询出来。 部门信息在我们使用的时候再去查询; 分段查询的基础之上加上两个配置: -->
这两个配置,需要写在mybatis全局配置中:
<!-- 2、settings包含很多重要的设置项 setting:用来设置每一个设置项 name:设置项名 value:设置项取值 --> <settings> <!-- 配置驼峰命名法 <setting name="mapUnderscoreToCamelCase" value="true"/> --> <!-- 配置oracle 字段内容 null类型 兼容 <setting name="jdbcTypeForNull" value="NULL"/> --> <!--下面这两个是用来开启延迟加载用的,显示的指定每个我们需要更改的配置的值,即使他是默认的。防止版本更新带来的问题 --> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings>
8、补充说明
分步查询中:子句查询时(无论是association 还是 collection 标签),传入多个参数问题,延迟加载设置:
### 举例: ### fetchType="lazy" 代表子句执行时,用的是延迟加载。 ### - lazy:延迟 ### - eager:立即 ### 子查询 多个入参问题 ### column="{deptId=id}" 代表 sql字段的 id ,传入给 子句查询中的 deptId 入参 ### 将多列的值封装成map;column="{key1=column1,key2=column2}" 来传给子查询的入参 <association property="department" select="com.mybatis.mapper.DepartmentMapper.getDeptById" column="{id=d_id}" fetchType="lazy"> </association>