8. 通过properties标签实现软编码
a. src下定义配置文件db.properties
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:XE
username=SCOTT
password=TIGER
b. properties标签
mybatis核心配置文件中添加properties标签,指定加载外部的properties文件,注意定义位置
<!-- 加载外部的properties文件 -->
<properties resource="db.properties" />
c.使用方式
获取properties文件中数据时候,要通过${}的方式获取
<environments default="even">
<environment id="even">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
9. typeAliases标签配置别名
a… typeAliases标签
功能
用与给java类型定义别名,放边在配置文件中使用
使用方式
在mybatis核心配置文件中添加typeAliases标签
- 通过typeAlias标签具体指定为某一个类型其别名,别名定义在alias属性中
<!-- typeAliases为类型起别名 -->
<typeAliases>
<!-- 具体为某一个java类其别名 User->u -->
<typeAlias type="com.shsxt.pojo.User" alias="u"/>
<typeAlias type="com.shsxt.pojo.Dept" alias="d"/>
</typeAliases>
2)通过typeAlias标签具体指定为某一个类型指定别名,alias属性可以省略,默认别名为类型,大小写不敏感
<!-- alias属性可以省略,别名默认为类型,大小写不敏感(User|user) -->
<typeAlias type="com.shsxt.pojo.User"/>
3)可以通过package标签为整个包下所有的类定义别名,别名默认为类型,大小写不敏感
<!-- 3)package 为整个包下的所有类定义别名 ,别名默认为类型,大小写不敏感 -->
<package name="com.shsxt.pojo"/>
b.Mybatis内建别名
下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重
复,采取了特殊的命名风格.
10. 入参类型
如果执行的是条件查询,需要在调用方法时候传递参数进来,此时可以在select标签中通过parameterType属性指定
参数的类型,在SQL中,可以通过#{}的方式获取参数
**参数的类型: 基本数据类型(包装类型) JavaBean String Date Map List 数组
SQL映射文件 ** UserMapper.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.shsxt.mappers.UserMapper">
<!-- 入参类型 : 基本数据类型(包装类型) JavaBean String Date Map List 数组 -->
<!-- 没有参数 -->
<select id="queryAll" resultType="user"> SELECT ID,USERNAME,USERPWD FROM TB_USER
</select>
<!-- 基本数据类型(包装类型) -->
<select id="queryById" resultType="User" parameterType="int">
SELECT ID,USERNAME,USERPWD FROM TB_USER WHERE ID = #{id}
<!-- 获取参数的占位符可以 随便指定 -->
</select>
<!-- String -->
<select id="queryByName" resultType="User" parameterType="string">
SELECT ID,USERNAME,USERPWD FROM TB_USER WHERE USERNAME = #{0}
</select>
<!-- JavaBean SQL语句中的占位符要使用参数属性名匹配参数对象中的不同属性值-->
<select id="queryByUser" resultType="User" parameterType="user">
SELECT ID,USERNAME,USERPWD FROM TB_USER WHERE USERNAME = #{username} AND USERPWD = #{userpwd}
</select>
<!-- Map SQL语句中的占位符要根据map中的key值匹配value值-->
<select id="queryByMap" resultType="User" parameterType="map">
SELECT ID,USERNAME,USERPWD FROM TB_USER WHERE id=#{id1} or id =#{id2}
</select>
<!-- 数组 -->
<select id="queryByArray" resultType="User">
SELECT ID,USERNAME,USERPWD FROM TB_USER WHERE id in
<!--foreach: 遍历参数 item: 参数可以自定义,用来循环集合中的值(变量名) -->
<foreach collection="array" item="item" open="(" separator="," close=")"> #{item} </foreach>
</select>
</mapper>
Java测试文件:
public class UserTest {
public static void main(String[] args) throws IOException {
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis.xml");
//2.获取SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//3.获取会话
SqlSession session = factory.openSession();
//4.操作
//1)基本数据类型(包装类)
//selectOne("命名空间.id","入参")
//User user = session.selectOne("com.shsxt.mappers.UserMapper.queryById",180);
//System.out.println(user);
//2)String
//List<User> list = session.selectList("com.shsxt.mappers.UserMapper.queryByName", "胡歌");
//System.out.println(list);
//3)JavaBean
//User u = new User();
//u.setUsername("胡歌");
//u.setUserpwd(5211314);
//List<User> list = session.selectList("com.shsxt.mappers.UserMapper.queryByUser", u);
//System.out.println(list);
//4)Map
//Map<String, Object> param = new HashMap();
//param.put("id1", 180);
//param.put("id2", 100);
//List<User> list = session.selectList("com.shsxt.mappers.UserMapper.queryByMap", param);
//System.out.println(list);
//5)数组
List<User> list = session.selectList("com.shsxt.mappers.UserMapper.queryByArray", new int[] {100,101,102}); System.out.println(list);
//5.关闭
session session.close();
}
}
11. 工具类的封装
package com.shsxt.utils;
import java.io.IOException;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MybatisUtils {
private static SqlSessionFactory factory = null;
static {
try {
factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis.xml"));
} catch (IOException e) {
e.printStackTrace();
}
}
/** 返回一个会话 */
public static SqlSession getSession() {
SqlSession session =null;
if(factory!=null) {
//session = factory.openSession(); //默认手动提交事务
session = factory.openSession(true); //自动提交
}
return session;
}
}
12. 事务(Transaction)
事务是数据库操作的最小单位,有着ACID的特性,应该保证一个事务下的多条SQL语句要么都成功,要么都失败.
Mybatis中配置了事务管理器,type属性设置JDBC,表示Mybatis采用和原生JDBC相同的事务管理机制
在Myabatis执行操作的开始,将自动提交功能关闭了,需要我们在执行DML操作时候,手动提交设置|设置自动提
交
手动提交:
session.commit(); //事务提交
设置自动提交事务:
public static SqlSession getSession() {
SqlSession session =null;
if(factory!=null) {
//session = factory.openSession(); //默认手动提交事务
session = factory.openSession(true); //自动提交
}
return session;
}
13. 增删改操作
SQL映射文件:
<mapper namespace="com.shsxt.mappers.UserMapper2">
<!-- 测试增删改 : 结果返回的都是影响函数int -->
<!-- 新增 -->
<insert id="insertUser" parameterType="user">
insert into tb_user values(seq_user_id.nextval,#{username},#{userpwd})
</insert>
<!-- 修改 -->
<update id="updateUser" parameterType="user">
update tb_user set userpwd = #{userpwd} where id =#{id} </update>
<!-- 删除 -->
<delete id="deleteUser" parameterType="_int">
delete from tb_user where id = #{haha}
</delete>
</mapper>
Java测试类:
/** 测试增删改功能 */
public class UserTest02 {
//删除方法
@Test
public void testDelete() {
SqlSession session = MybatisUtils.getSession();
int rows = session.update("com.shsxt.mappers.UserMapper2.deleteUser", 100);
if(rows>0) {
System.out.println("SECCESS!!!");
}else {
System.out.println("FAILED!!!");
}
//会话关闭
session.close();
}
//修改方法
@Test
public void testUpdate() {
SqlSession session = MybatisUtils.getSession();
User user = new User();
user.setId(100);
user.setUserpwd(9876);
int rows = session.update("com.shsxt.mappers.UserMapper2.updateUser", user);
if(rows>0) {
System.out.println("SECCESS!!!");
}else {
System.out.println("FAILED!!!");
}
//会话关闭
session.close();
}
//插入方法
@Test
public void testInsert() {
SqlSession session = MybatisUtils.getSession();
User user = new User();
user.setUsername("zhangsan");
user.setUserpwd(789);
//插入方法
int rows = session.insert("com.shsxt.mappers.UserMapper2.insertUser", user);
//影响行数判断
if(rows>0) {
System.out.println("SECCESS!!!");
//session.commit(); //事务提交
}else {
System.out.println("FAILED!!!");
//session.rollback();
}
//会话关闭
session.close();
}
}
14. resultType结果类型
常见的结果类型: 基本数据类型(包装类) String Date Javabean List Map List
SQL映射文件:
<?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.shsxt.mappers.EmpMapper">
<!-- 常见的结果类型: 基本数据类型(包装类) String Date Javabean List Map List<Map> -->
<!-- 基本数据类型 : 根据id查询用于薪资 -->
<select id="querySalById" parameterType="int" resultType="_double" >
select sal from emp where empno = #{empno} </select>
<!-- String : 查询与执行名字类似的用户信息 -->
<select id="queryNameByUserNameLike" parameterType="string" resultType="string">
select ename from emp where ename like '%'||#{param}||'%'
</select>
<!-- JavaBean -->
<select id="queryAll" resultType="emp">
select empno,ename,sal,hiredate,deptno from emp
</select>
<!-- Date : 根据id查询入职日期 -->
<select id="queryDateById" parameterType="int" resultType="date">
select hiredate from emp where empno = #{empno}
</select>
<!-- Map : 查询1条数据,把这条数据的<字段名,字段值>放入Map中,如果查询多条数据可以使用List<Map> -->
<select id="queryEmpByIdToMap" resultType="map" parameterType="int">
select empno,ename,sal,hiredate,deptno from emp where empno = #{empno}
</select>
<!-- List<Map> -->
<select id="queryEmpByIdToListMap" resultType="map" parameterType="_double">
select empno,ename,sal,hiredate,deptno from emp where sal = #{0}
</select>
</mapper>
Java测试类:
//测试结果类型
public class EmpTest {
public static void main(String[] args) {
SqlSession session = MybatisUtils.getSession();
//基本数据类型:
//double sal = session.selectOne("com.shsxt.mappers.EmpMapper.querySalById",7369);
//System.out.println(sal);
//String
//List<String> listName = session.selectList("com.shsxt.mappers.EmpMapper.queryNameByUserNameLike", "A"); //System.out.println(listName);
//Date
//Date date = session.selectOne("com.shsxt.mappers.EmpMapper.queryDateById",7369);
//System.out.println("入职日期: "+new SimpleDateFormat().format(date));
//Javabean
//List<Emp> listEmp = session.selectList("com.shsxt.mappers.EmpMapper.queryAll");
//System.out.println(listEmp);
//Map : 查询1条数据,把这条数据的<字段名,字段值>放入Map中,如果查询多条数据可以使用List<Map>
//Map<String,Object> map =session.selectOne("com.shsxt.mappers.EmpMapper.queryEmpByIdToMap",7369); //System.out.println(map);
//List<Map> List<Map<String,Object>> map =session.selectList("com.shsxt.mappers.EmpMapper.queryEmpByIdToListMap",1250.00);
System.out.println(map);
session.close();
}
}
15. 接口绑定方案(***)
Mybatis中,提供了一套接口绑定方案,程序员可以提供一个接口,然后对应的提供一个mapper.xml文件,Mybatis会自
动将接口与xml文件进行绑定,实际上就是Mybatis会根据接口和对应的xml文件创建接口的实现类,换而言之,就是可
以得到接口类型的对象,可以调用方法使用
a. 定义接口
接口要与mapper.xml文件放入同一包下
//测试接口绑定方案基本使用
public interface UserMapper {
//查询所有的用于信息
List<User> queryAll();
}
b.编写对应当前接口的SQL映射文件
注意: 1. xml文件名与接口名保持一致
2. namespace的值必须与接口的权限定路径保持一致
3. id属性必须与接口对应的方法名保持一致
<!-- namespace值一定要与接口的权限定名保持一致(包名+接口名) -->
<mapper namespace="com.shsxt.mappers.UserMapper">
<!-- 查询所有的用户信息 -->
<select id="queryAll" resultType="User">
select * from tb_user
</select>
<!-- 根据id查询用户信息 -->
<select id="queryUserById" parameterType="int" resultType="user">
select * from tb_user where id = #{0}
</select>
</mapper>
c.核心配置文件中扫描接口
1)扫描单个接口,可以使用mapper的class属性值定义
<!-- 用于扫描接口 -->
<mappers>
<mapper class="com.shsxt.mappers.UserMapper"/>
</mappers>
2)当扫描多个接口时,为了简化配置,可以使用package标签,表示扫描对应包下的所有接口
<mappers>
<package name="com.shsxt.mappers"/>
</mappers>
d.引用
在使用时,可以通过SqlSession对象的getMapper(接口.class)方法,得到接口的代理对象,从而可以调用定义好的方法
@Test
public void queryAll() {
SqlSession session = MybatisUtils.getSession();
//getMapper(接口的class对象) 获取参数接口的实现类对象
UserMapper userMapper = session.getMapper(UserMapper.class);
//通过接口的实现类对象,调用接口中的方法
List<User> list = userMapper.queryAll();
System.out.println(list);
session.close();
}
e… 通过接口绑定方案解决多参数问题
- 接口中定义方法带有多参数,SQL中获取方式使用arg0,arg1…|param1,param2…
//根据用户名和密码查询用户
sql中占位符的值必须与为arg0,arg1..|param1,param2..
List<User> queryUserByNamePwd(String username,int userpwd);
<!-- 根据用户名和密码查询用户信息(多参数) -->
<select id="queryUserByNamePwd" resultType="user">
<!-- select * from tb_user where username=#{arg0} and userpwd=#{arg1} -->
select * from tb_user where username=#{param1} and userpwd=#{param2}
</select>
2)接口中定义方法带有多参数,参数中使用@Param注解设定参数名用于SQL语句中使用
//通过@Param来定义sql中占位符的值,可以实现与参数名字相同形式,更直观
List<User> queryUserByNamePwd(@Param("username")
String username,@Param("userpwd") int userpwd);
<!-- 根据用户名和密码查询用户信息(多参数) -->
<select id="queryUserByNamePwd" resultType="user">
select * from tb_user where username=#{username} and userpwd=#{userpwd}
</select>
16. 接口实现CRUD
a.基本CRUD操作
//测试接口绑定方案crud
public interface UserMapper {
//查询所有用于信息
public List<User> queryUserByNamePwd(@Param("name")
String name,@Param("pwd")
int pwd);
//新增用户
public int addUser(String name,int pwd);
//修改用户信息
public int updateUser(User user);
//删除用户
public int deleteUser(int id);
}
<mapper namespace="com.shsxt.mappers.UserMapper">
<select id="queryUserByNamePwd" resultType="User">
select * from tb_user where username=#{name} or userpwd = #{pwd}
</select>
<!-- 新增用户 -->
<insert id="addUser">
INSERT INTO TB_USER VALUES(seq_user_id.nextval,#{param1},#{param2})
</insert>
<!-- 修改用户 -->
<update id="updateUser" parameterType="User">
update tb_user set username=#{username},userpwd=#{userpwd} where id=#{id}
</update>
<!-- 删除用户 -->
<delete id="deleteUser" parameterType="int">
delete from tb_user where id=#{id}
</delete>
</mapper>
/** 接口实现crud */
public class UserTest {
@Test
public void testDelete() {
SqlSession session = MybatisUtils.getSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
int rows = userMapper.deleteUser(202);
if(rows>0) {
System.out.println("成功");
}else {
System.out.println("失败");
}
session.close();
}
@Test
public void testUpdate() {
SqlSession session = MybatisUtils.getSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
int rows = userMapper.updateUser(new User(201,"张三丰",1111));
if(rows>0) {
System.out.println("成功");
}
else { System.out.println("失败");
}
session.close();
}
@Test
public void testInsert() {
SqlSession session = MybatisUtils.getSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
int rows = userMapper.addUser("林更新", 45678);
if(rows>0) {
System.out.println("成功");
}else {
System.out.println("失败");
}
session.close();
}
@Test
public void testSelect() {
SqlSession session = MybatisUtils.getSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
List<User> list = userMapper.queryUserByNamePwd("胡歌", 789);
System.out.println(list); session.close();
}
}
b.批量操作
//测试批量操作
public interface UserMapper2 {
//批量新增用户
public int addUserSome(List<User> user);
//批量删除
public int deleteSomeUser(List<Integer> id);
//批量更新
public int updateSomeUser(List<User> list);
}
<mapper namespace="com.shsxt.mappers.UserMapper2">
<!-- 批量插入 -->
<insert id="addUserSome" parameterType="list">
insert into tb_user(id, username, userpwd)
select seq_user_id.nextval, uname, upwd from ( <foreach collection="list" item="item" separator="union" >
select #{item.username} uname, #{item.userpwd} upwd from dual </foreach> )
</insert>
<!-- 批量删除 -->
<delete id="deleteSomeUser" parameterType="list">
delete from tb_user where id in( <foreach collection="list" item="item" separator=","> #{item} </foreach> )
</delete>
<!-- 批量更新 -->
<update id="updateSomeUser" parameterType="list">
<foreach collection="list" item="item" open="begin" close=";end;" separator=";">
update tb_user set userpwd = #{item.userpwd} where id = #{item.id}
</foreach>
</update>
</mapper>
public class UserTest2 {
@Test
public void testUpdateSome() {
SqlSession session = MybatisUtils.getSession();
UserMapper2 userMapper = session.getMapper(UserMapper2.class);
List<User> list = new ArrayList();
list.add(new User(218,"蓝精灵",88));
list.add(new User(219,"粉精灵",99));
list.add(new User(220,"紫精灵",00));
int rows = userMapper.updateSomeUser(list);
System.out.println(rows); session.close();
}
@Test
public void testDeleteSome() {
SqlSession session = MybatisUtils.getSession();
UserMapper2 userMapper = session.getMapper(UserMapper2.class);
List<Integer> list = new ArrayList();
list.add(208); list.add(209);
int rows = userMapper.deleteSomeUser(list);
if(rows>0) {
System.out.println("成功");
}else {
System.out.println("失败");
}
session.close();
}
@Test
public void testInsertSome() {
SqlSession session = MybatisUtils.getSession();
UserMapper2 userMapper = session.getMapper(UserMapper2.class);
List<User> list = new ArrayList();
list.add(new User(1,"蓝精灵",5));
list.add(new User(2,"粉精灵",6));
list.add(new User(1,"紫精灵",7));
int rows = userMapper.addUserSome(list);
if(rows>0) {
System.out.println("成功");
}else {
System.out.println("失败");
}
session.close();
}
}
17. 动态SQL
根据条件的不同,SQL语句可以随之动态改变,Mybatis中提供了一组用户实现动态SQL的标签
a. if
用于进行条件判断,test属性,用于指定判断条件.在sql语句后强行添加where 1=1 的恒成立条件
public List<User> queryUser(@Param("username") String username,@Param("userpwd") int userpwd);
<!-- if where-->
<select id="queryUser" resultType="User">
select * from t_user where 1=1
<!--if条件判断标签 test编写条件 获取对应参数值进行判断,参数值的获取@param()规定的别名 -->
<if test="username!=null and username!=''"> and uname =#{username}
</if>
<if test="password!=null and password!=''"> and upwd = #{password}
</if>
</where>
</select>
b.where标签
用于管理 where 子句. 有如下功能:
如果没有条件, 不会生成 where 关键字
如果有条件, 会自动添加 where 关键字
如果第一个条件中有 and, 去除之
<select id="queryUser" resultType="User">
select * from t_user
<where>
<if test="username!=null and username!=''"> and uname =#{username}
</if>
<if test="password!=null and password!=''"> and upwd = #{password}
</if>
</where>
</select>
c.choose when otherwise标签
这是一套标签, 功能类似于 switch…case…default
List<User> queryUser2(@Param("username") String username,@Param("password") String password);
<!-- choose when otherwise -->
<select id="queryUser2" resultType="User">
select * from t_user
<where>
<choose>
<!-- switch -->
<when test="username!=null and username!=''">
<!-- case test中存放条件 --> and uname =#{username}
</when>
<when test="password!=null and password!=''"> and upwd = #{password}
</when>
<otherwise>
<!-- default --> and 1=1
</otherwise>
</choose>
</where>
</select>
d.set标签
用于维护 update 语句中的 set 子句. 功能如下:
满足条件时, 会自动添加 set 关键字
会去除 set 子句中多余的逗号
不满足条件时, 不会生成 set 关键字
//根据id修改用户信息
int undateUser(User user);
<!-- 动态修改 -->
<update id="undateUser" parameterType="user"> update t_user <set>id=#{id},
<if test="uname!=null and uname!=''"> uname =#{uname},
</if>
<if test="upwd!=null and upwd!=''"> upwd = #{upwd},
</if>
</set> where id=#{id}
</update>
e.trim标签
当对where或set标签的功能不满意,可以使用trim标签定义,用于在前后添加或删除一些内容
prefix, 在前面添加内容
prefixOverrides, 从前面去除内容
suffix, 向后面添加内容
suffixOverrides, 从后面去除内容
List<User> queryByNameLike(@Param("username") String name);
<select id="queryUser" resultType="User">
select * from t_user
<trim prefix="WHERE" prefixOverrides="AND |OR ">
<if test="username!=null and username!=''"> and uname =#{username}
</if>
<if test="password!=null and password!=''"> and upwd = #{password}
</if>
</trim>
</select>
f.bind标签
用于对数据进行再加工, 用于模糊查询
<!-- 根据用户名模糊查询 -->
<select id="queryByNameLike" resultType="user" parameterType="string">
select * from t_user
<where>
<!-- bind 对数据进行再加工 -->
<bind name="username" value="'%'+username+'%'"/> uname like #{username}
</where>
</select>
g.foreach标签
用于在 SQL 语句中遍历集合参数, 在 in 查询中使用
collection: 待遍历的集合
open: 设置开始符号
item: 迭代变量
separator: 项目分隔符
close: 设置结束符号
<!-- 批量删除数据 -->
<delete id="deleteSomeUser">
delete from t_user where id in
<foreach collection="list" item ="item" separator="," open="(" close=")">
#{item}
</foreach>
</delete>
h. sql include标签
用于提取 SQL 语句, 用于引用 SQL 语句
<sql id="all">
id, uname, upwd
</sql>
<select id="selIn" parameterType="list" resultType="user">
select
<include refid="all"/>
from t_user where id in
<foreach collection="list" open="(" separator="," close=")" item="item">
#{item}
</foreach>
</select>
表与表之间的关系:
一对一 外键约束
一对多
多对一 外键约束
多对多 中间表
类与类之间的关系
继承
多态 组合
聚合
…
一个类作为另一个类的方法的参数
一个类作为另一个类的成员属性
18. 解决列名和属性名不一致问题
如果查询时候,使用resultType属性,表示采用mybaits的自动映射机制(Auto-Mapping),相同的列名和相同的属性名
会自动匹配,但是当表中的字段名与类中的属性名不一致时候,会导致查不到数据,结决方案有2中:
1. 列别名
查询时,可以通过列别名的方式将列名与属性名保持一致,继续使用自动映射,从而解决该问题,但是比较麻烦
<!-- 查询所有学生 -->
<select id="queryAll" resultType="student">
select sid id,sname name,sgender gender,sage age,hiredate,cid from sxt_student
</select>
2. 使用resultMap
resultMap标签用于自定义映射关系,可以有程序员自主指定列明与属性名的映射关系,一旦使用resultMap,表示不再
使用自动映射机制
<!--手动指定属性与列名之间映射关系 id : 标识resultMap的唯一 type : 表示映射的类型 -->
<resultMap type="Student" id="student_resultMap">
<!-- 标识主键唯一 -->
<id column="sid" property="id"/>
<!-- 非主键字段使用result -->
<result column="sname" property="name"/>
<result column="sgender" property="gender"/>
<result column="sage" property="age"/>
</resultMap>
<!-- 根据id查询学生 -->
<select id="queryById" resultMap="student_resultMap">
select * from sxt_student where sid = #{id}
</select>
19. 连表查询
表连接从数据库中查询的数据
在java中,可以返回Map,List
<!--结果类型Map : 根据id查询一个学生的学生信息以及班级信息 -->
<select id="queryStudentClassById" parameterType="int" resultType="map">
select sid, sname, sage, sgender, hiredate, s.cid cid, cname
from sxt_student s
join sxt_class c
on s.cid = c.cid
where sid = #{id}
</select>
<!-- 结果类型:List<Map> 查询学生的学生信息以及班级信息-->
<select id="queryAll" resultType="map"> select sid, sname, sage, sgender, hiredate, s.cid cid, cname
from sxt_student s
join sxt_class c
on s.cid = c.cid
</select>
public List<Map<String,Object>> queryAll();
//根据id查询学生信息以及学生所在的班级信息
public Map<String,Object> queryStudentClassById(int id);
resultMap的关联方式实现多表查询(一对一,多对一)
a)在 StudentMapper.xml 中定义多表连接查询 SQL 语句, 一 次性查到需要的所有数据, 包括对应班级的信息.
b)通过定义映射关系, 并通过 指定对象属性的映射关系. 可以把看成一 个使用. javaType 属性表示当前对象, 可以 写
全限定路径或别名.
Javabean类
//Clazz班级类
public class Student implements Serializable{
private int id;
private String name;
private String gender;
private int age;
private Date hiredate;
private int cid;
private Clazz clazz; //坐在班级对象
private IDCard idcard; //身份证
public Student() {
// TODO Auto-generated constructor stub
}
public Student(int id, String name, String gender, int age, Date hiredate, int cid, Clazz clazz) {
super();
this.id = id;
this.name = name;
this.gender = gender;
this.age = age;
this.hiredate = hiredate;
this.cid = cid;
this.clazz = clazz;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getHiredate() {
return hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
public int getCid() {
return cid;
}
public void setCid(int cid) {
this.cid = cid;
}
public Clazz getClazz() {
return clazz;
}
public void setClazz(Clazz clazz) {
this.clazz = clazz;
}
@Override public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + cid;
result = prime * result + ((clazz == null) ? 0 : clazz.hashCode());
result = prime * result + ((gender == null) ? 0 : gender.hashCode());
result = prime * result + ((hiredate == null) ? 0 : hiredate.hashCode());
result = prime * result + id; result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (cid != other.cid)
return false;
if (clazz == null) {
if (other.clazz != null)
return false;
} else if (!clazz.equals(other.clazz))
return false;
if (gender == null) {
if (other.gender != null)
return false;
} else if (!gender.equals(other.gender))
return false; if (hiredate == null) {
if (other.hiredate != null)
return false;
} else if (!hiredate.equals(other.hiredate))
return false;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override public String toString() {
return "Student [id=" + id + ", name=" + name + ", gender=" + gender + ", age=" + age + ", hiredate=" + hiredate + ", cid=" + cid + ", clazz=" + clazz + "]";
}
}
//Clazz班级类
public class Clazz implements Serializable{
private int cid; private String cname; public Clazz() {
// TODO Auto-generated constructor stub
}
public Clazz(int cid, String cname) {
super();
this.cid = cid;
this.cname = cname;
}
public int getCid() {
return cid; }
public void setCid(int cid) {
this.cid = cid; }
public String getCname() {
return cname; }
public void setCname(String cname) {
this.cname = cname;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1; result = prime * result + cid; result = prime * result + ((cname == null) ? 0 : cname.hashCode());
return result; }
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Clazz other = (Clazz) obj;
if (cid != other.cid)
return false;
if (cname == null) {
if (other.cname != null)
return false;
} else if (!cname.equals(other.cname))
return false;
return true; }
@Override
public String toString() {
return "Clazz [cid=" + cid + ", cname=" + cname + "]";
}
}
Mapper接口
public interface StudentMapper {
public Student queryStudentClassById(int id);
}
Sql映射文件
<resultMap type="Student" id="student_resultMap">
<!-- 标识主键唯一 -->
<id column="sid" property="id"/>
<!-- 非主键字段使用result -->
<result column="sname" property="name"/>
<result column="sgender" property="gender"/>
<result column="sage" property="age"/>
<result column="scid" property="cid"/>
<!--可以指定对象属性的映射关系 -->
<association property="clazz" javaType="Clazz">
<id property="cid" column="ccid"/>
<result property="cname" column="cname"/>
</association>
</resultMap>
<select id="queryStudentClassById" parameterType="int" resultMap="student_resultMap">
select sid, sname, sage, sgender, hiredate, s.cid scid,c.cid ccid,cname
from sxt_student s
join sxt_class c
on s.cid = c.cid
where sid = #{id}
</select>
resultMap 的关联方式实现多表查询(一对 多)
a)在 ClazzMapper.xml 中定义多表连接查询 SQL 语句, 一次 性查到需要的所有数据, 包括对应学生的信息.返回学
生对象
b)通过定义映射关系, 并通过指 定集合属性泛型的映射关系. 可以把看成 一个使用. ofType 属性表示集合的泛型, 可
以写全限定路径或别名.
public class Clazz implements Serializable{
private int cid;
private String cname;
private List<Student> stus; ...
<mapper namespace="com.bjsxt.mapper.ClazzMapper">
<resultMap type="clazz" id="cmap">
<id property="cid" column="ccid" />
<result property="cname" column="cname" />
<!-- 当属性为集合类型时候使用collection关联映射 ofType:集合中数据类型-->
<collection property="stus" javaType="list" ofType="student">
<id property="id" column="sid" />
<result property="name" column="sname" />
<result property="age" column="sage" />
<result property="gender" column="sgender" />
<result property="cid" column="scid" />
</collection>
</resultMap>
<select id="selAll" resultMap="cmap">
select c.cid ccid, c.cname, s.sid, s.sname, s.sage, s.sgender, s.cid scid
from sxt_student s
right join sxt_class c
on s.cid = c.cid
</select>
ResultMap继承问题
当resultMap中的一些配置可能多次在其他定制映射中使用的时候,可以单独提出来,其他resultMap映射关系可以继
承
<resultMap type="Student" id="Fu">
<!-- 标识主键唯一 -->
<id column="sid" property="id"/>
<!-- 非主键字段使用result -->
<result column="sname" property="name"/>
<result column="sgender" property="gender"/>
<result column="sage" property="age"/>
<result column="scid" property="cid"/>
</resultMap>
<!-- extends继承另外一个resultMap的配置 -->
<resultMap type="Student" id="student_resultMap" extends="Fu">
<!--可以指定对象属性的映射关系 -->
<association property="clazz" javaType="Clazz">
<id property="cid" column="ccid"/>
<result property="cname" column="cname"/>
</association>
</resultMap>