Mybatis_第三天笔记

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标签

  1. 通过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… 通过接口绑定方案解决多参数问题

  1. 接口中定义方法带有多参数,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>
发布了22 篇原创文章 · 获赞 6 · 访问量 439

猜你喜欢

转载自blog.csdn.net/ffgyfgj/article/details/105690518
今日推荐