目录
(2) [choose when otherwise] 和where
1.多表查询
1.1多对一
例子: 根据学生id查询学生信息与班级信息
(1) 第一种方式 通过链表查询。
1. 创建两张具有逻辑外键或物理外键的数据表
班级表:
学生表:
2. 常见数据表对应的实体类
班级实体类:
public class Cls {
private Integer id;
private String cname;
public Cls() {
}
public Cls(Integer id, String cname) {
this.id = id;
this.cname = cname;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
@Override
public String toString() {
return "Cls{" +
"id=" + id +
", cname='" + cname + '\'' +
'}';
}
}
学生实体类:
public class Stu {
private Integer id;
private String name;
private String classid;
//学生类里面需要创建一个班级类的实体类!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
private Cls cls;
public Stu() {
}
public Stu(Integer id, String name, String classid, Cls cls) {
this.id = id;
this.name = name;
this.classid = classid;
this.cls = cls;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClassid() {
return classid;
}
public void setClassid(String classid) {
this.classid = classid;
}
public Cls getCls() {
return cls;
}
public void setCls(Cls cls) {
this.cls = cls;
}
@Override
public String toString() {
return "Stu{" +
"id=" + id +
", name='" + name + '\'' +
", classid='" + classid + '\'' +
", cls=" + cls +
'}';
}
}
3.创建学生dao层接口并定义方法
public interface StuDao {
Stu selectstuandclassbystuid(int id);
}
4.在映射文件中写对应的dao接口方法中的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.aaa.qy145.ten.cys.dao.StuDao">
<select id="selectstuandclassbystuid" resultMap="getstu">
select * from stu s join class c on s.uclassid=c.id where s.id = #{id}
</select>
<!--
<id>标签:实体类中属性与数据库主键对应 使用的标签
<result>标签: 实体类其他属性与数据库的列名对应 使用的标签
上面只适用于 八大基本类型与String类型的简单属性
若是实体类属性 应使用<association>复杂标签
<association>标签: property:对应学生类中的实体类的变量名(cls)
javaType:对应的是该变量名对应的实体类(Cls)的路径
该标签中书写 javaType对应的实体类(Cls)的属性名与数据表名之间的关系
如果实体类(Cls)属性名与数据表名相同 可不写 但必须要在
<association>标签内书写 autoMapping="true"
-->
<resultMap id="getstu" type="com.aaa.qy145.ten.cys.entity.Stu">
<id property="id" column="id"/>
<result property="name" column="uname"/>
<result property="classid" column="uclassid"/>
<association property="cls" javaType="com.aaa.qy145.ten.cys.entity.Cls" autoMapping="true">
<id property="id" column="id"/>
<result property="cname" column="classname"/>
</association>
</resultMap>
</mapper>
5.在配置文件中注册映射文件并测试
注册:
<mappers>
<mapper resource="Mapper/StuMapper.xml"/>
</mappers>
测试:
@Test
public void test01() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory =new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sqlSessionFactory.openSession();
StuDao stuDao = session.getMapper(StuDao.class);
Stu stu = stuDao.selectstuandclassbystuid(1001);
System.out.println(stu);
}
结果:
(2)第二种方式 通过嵌套查询。----两次查询。
1. 在学生映射文件中写对应的dao接口方法中的sql语句
<!--
该sql语句只根据学生id查找学生数据表中的所有数据
-->
<select id="selectstuandclassidbystuid" resultMap="getstuandclassid">
select * from stu where stu.id=#{id}
</select>
<resultMap id="getstuandclassid" type="com.aaa.qy145.ten.cys.entity.Stu">
<id property="id" column="id"/>
<result property="name" column="uname"/>
<result property="classid" column="uclassid"/>
<!--
column: 对应的是 学生数据表与班级数据表的 外键列名
select: 对应的是 班级映射文件里的 根据班级id查找班级信息 的sql语句的对应路径
-->
<association property="cls" javaType="com.aaa.qy145.ten.cys.entity.Cls"
column="uclassid"
select="com.aaa.qy145.ten.cys.dao.ClsDao.getclassbyclassid">
</association>
2. 在班级映射文件中写根据班级id查找班级信息的sql语句
<mapper namespace="com.aaa.qy145.ten.cys.dao.ClsDao">
<!--
因为班级实体类中属性名与列名不同 采用第二中 别名方法:列名的别名与实体类的属性名相同即可
也可使用resultMap方法 两种方法都可以
-->
<select id="getclassbyclassid" resultType="com.aaa.qy145.ten.cys.entity.Cls">
select id id,classname cname from class where id=#{id}
</select>
</mapper>
3.在配置文件中注册两张表的映射文件 并测试
注册:
<mappers>
<mapper resource="Mapper/StuMapper.xml"/>
<mapper resource="Mapper/ClasMapper.xml"/>
</mappers>
测试:
@Test
public void test01()throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory =new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sqlSessionFactory.openSession();
StuDao stuDao = session.getMapper(StuDao.class);
Stu stu = stuDao.selectstuandclassbystuid(1001);
System.out.println(stu);
}
测试结果:
1.2 一对多
例:根据班级id查找班级信息以及班级内所有学生
1. 使用上例多对一的数据表
2.创建数据表对应的实体类
学生类:
public class Stu {
private Integer id;
private String name;
private String classid;
public Stu() {
}
public Stu(Integer id, String name, String classid) {
this.id = id;
this.name = name;
this.classid = classid;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClassid() {
return classid;
}
public void setClassid(String classid) {
this.classid = classid;
}
@Override
public String toString() {
return "Stu{" +
"id=" + id +
", name='" + name + '\'' +
", classid='" + classid + '\'' +
'}';
}
}
班级类:
public class Cls {
private Integer id;
private String cname;
//班级中有很多学生 所以需要创建一个学生类的集合
private List<Stu> stus;
public Cls() {
}
public Cls(Integer id, String cname, List<Stu> stus) {
this.id = id;
this.cname = cname;
this.stus = stus;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public List<Stu> getStus() {
return stus;
}
public void setStus(List<Stu> stus) {
this.stus = stus;
}
@Override
public String toString() {
return "Cls{" +
"id=" + id +
", cname='" + cname + '\'' +
", stus=" + stus +
'}';
}
}
3.创建班级dao接口
public interface ClsDao {
Cls selectclassandstubyclassid(int id);
}
4.在班级表的映射文件中写dao接口方法的对应sql
<mapper namespace="com.aaa.qy145.ten.cys.dao.ClsDao">
<!--
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
如果两个表中没有相同的列名 可以直接 select * ....
但是由于班级表跟学生表中的主键都为 id
因此需要将其中一个由别名展示 不然查询到的数据会显示不完整
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-->
<select id="selectclassandstubyclassid" resultMap="getclass">
select c.*,s.id sid,s.uname name,s.uclassid classid from class c join stu s on c.id = s.uclassid where c.id=#{id}
</select>
<resultMap id="getclass" type="com.aaa.qy145.ten.cys.entity.Cls">
<id property="id" column="id"/>
<result property="cname" column="classname"/>
<collection property="stus" ofType="com.aaa.qy145.ten.cys.entity.Stu" autoMapping="true">
<id property="id" column="sid"/>
</collection>
</resultMap>
</mapper>
5.测试
@Test
public void test02()throws IOException{
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory =new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sqlSessionFactory.openSession();
ClsDao clsDao = session.getMapper(ClsDao.class);
Cls cls = clsDao.selectclassandstubyclassid(1);
System.out.println(cls);
}
测试结果:
上述为第一种链表查询 第二种嵌套查询与多对一第二种相同 略
2.动态SQL
所谓动态sql 便是sql语句根据条件而发生改变。 一般用到的方法为:
元素 | 作用 | 描述 |
if | 条件判断 | 但条件判断 |
choos(when、otherwise) | 条件选择,相当Java when | 多条件分支判断 |
where、set | 辅助 | 处理sql语句拼接问题 |
foreache | 循环 | 循环 |
首先创建一个数据表 并存入数据
创建对应实体类与dao接口 并创建sql方法
(1)if和where一起用
<!-- #{参数名} 参数名:与map集合中的key对应才可获得传来的参数
如果name为空,那么将只根据sex来查询;如果sex也为空 则查询所有
where:可以帮你添加where关键 并且把第一个and | or去除
-->
<select id="selectbysome" resultMap="my01">
select * from student
<where>
<if test="sname!=null and sname!=''">
and s_name=#{sname}
</if>
<if test="ssex!=null and ssex!=''">
and s_sex=#{ssex}
</if>
</where>
</select>
测试:
@Test
public void test03()throws IOException{
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory =new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sqlSessionFactory.openSession();
StudentDao studentDao = session.getMapper(StudentDao.class);
Map<String,String> map = new HashMap<String, String>();
//从网页中得到参数值 并且封装到map对象中。
map.put("sname","李云");
map.put("ssex","男");
List<Student> list = studentDao.selectbysome(map);
System.out.println(list);
}
(2) [choose when otherwise] 和where
根据 name和 sex 来查询数据 若name有数据则之按照name查询 若name没数据 则按照sex查询 若sex也没数据则查询id为1的学生
<!--
choose +where
when:当条件满足时不会执行下面的when和other 都不满足则执行otherwise
-->
<select id="selectbysexorname" resultMap="my01">
select * from student
<where>
<choose>
<when test="name!=null and name!=''">
and s_name=#{name}
</when>
<when test="sex!=null and sex!=''">
and s_sex=#{sex}
</when>
<otherwise>
s_id=1
</otherwise>
</choose>
</where>
</select>
测试:
@Test
public void test05()throws IOException{
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory =new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sqlSessionFactory.openSession();
StudentDao studentDao = session.getMapper(StudentDao.class);
Map<String,String> map = new HashMap<String, String>();
//从网页中得到参数值 并且封装到map对象中。
map.put("sex","男");
List<Student> list = studentDao.selectbysexorname(map);
System.out.println(list);
}
(3)set标签---修改部分字段
<!--
修改部分列的值。
set 可以帮你添加set关键字 并且去除最后的逗号。
-->
<update id="updateall">
update student
<set>
<if test="name!=null and name!=''">
s_name=#{name},
</if>
<if test="birth!=null and birth!=''">
s_birth=#{birth}
</if>
<if test="sex!=null and sex!=''">
s_sex=#{sex}
</if>
</set>
where s_id = #{id}
</update>
测试:
@Test
public void test04()throws IOException{
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory =new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sqlSessionFactory.openSession();
StudentDao studentDao = session.getMapper(StudentDao.class);
Map<String,String> map = new HashMap<String, String>();
//从网页中得到参数值 并且封装到map对象中。
map.put("id","05");
map.put("name","哈哈");
map.put("sex","男");
int i = studentDao.updateall(map);
System.out.println("受影响的行数:"+i);
session.commit();
}
(4) foreach 批量处理
查询id=01,02,03,04的学生。
<!--
foreach:
collection:要遍历的集合和数组名
item: 每次遍历时赋值的元素变量名
open: 以什么开始
close:以什么结束
separator: 分隔符
List<Student> selectbysomeid(@Param("ids") int[] ids);
#{参数名}: 要与对应方法的@Param("参数名") 相对应
-->
<select id="selectbysomeid" resultMap="my01">
select * from student where s_id in
<foreach collection="ids" item="tid" open="(" close=")" separator=",">
#{tid}
</foreach>
</select>
测试:
@Test
public void test06()throws IOException{
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory =new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sqlSessionFactory.openSession();
StudentDao studentDao = session.getMapper(StudentDao.class);
int[] ids = {1,3,4};
List<Student> list = studentDao.selectbysomeid(ids);
for(Student s:list){
System.out.println(s);
}
}
最后,mybatis框架的基本使用到此结束,感谢浏览 ^_^