mybatis学完也有一段时间了,今天就对它做一个小小的总结吧,不对,与其所是总结,不如说是对前人的经验的一次复述吧,真的是延续了以往的风格
(1)它是用来干什么的:
我们知道,在JAVA应用程序结构的发展,由早期的单层结构逐步的发展到现在的多层次结构,具体的说,应该有4层:表述层,业务逻辑层,持久化层,数据库层.而mybatis就是运用在持久层,用于实现数据的持久化操作,那么有人可能要问了,对于数据的持久化hibernate,和jdbc已经可以实现,为什么还需要Mybatis呢,那么就不得不提到MyBatis的一些特点了,我们知道jdbc用于对数据库操作,基本上可以满足程序员的需求,但是由于jdbc的知识是复杂的,并且还会产生很多复杂且冗余的代码,所以出现了hibernate 这样的对jdbc轻量级封装的orm框架,,并且能够以面向对象的思想去操作数据库,但是hibernate对于一些复杂的需要用存储过程的操作,它的orm就显得比较吃力.这是Mybatis选择了他们的优点,对象关系映射,动态的sql,对于存储过程的运用简单方便.总的来说相对于hibernate 全自动的orm框架,它是一种半自动的orm的实现.
也就是说:它是业务逻辑层和数据库层之间的桥梁,业务逻辑层传入数据,由他操作数据库,返回结果.也就是我们MVC设计模式中的MODEL层
(2)它是如何实现的:
简单的说可以分为(待会实际操作的时候详细解释如何实现)
1 .读取并解析配置文件创建Sqlsessionfactory,
2.有Sqlsessionfactory得到sqlsession
3.使用sqlsession对数据库操作
4.提交事务
5.关闭sqlsession对象
(3)亲自体验一下:
准备工作:
1.数据库:sqlserver2008
表:学生表(sid,bid,sname)
班级表(bid,bname)
课程表(cid,cname)
学生课程表(sid,cid)
2. 工具软件:myeclipse
3.mybatis所需要的jar导入
4.数据库连接配置文件的编写:
mybatis中的核心配置文件是用于解析后生成sqlsessionfactory
它的内容包括 数据库驱动类,数据库,用户名,密码, 以及指定具体映射文件
<?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>
<!-- 加载数据库连接配置属性文件 -->
<properties resource="db.properties"/>
<typeAliases>
<typeAlias type="com.cn.t1.Student" alias="student"/>
</typeAliases>
<environments default="development">
<environment id="development">
<!--事务处理方式 -->
<transactionManager type="JDBC" />
<!-- POOLED是指从连接池(缓存)中获取连接对象,没有则创建新的并放入连接池 -->
<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>
<mappers>
<mapper resource="com/cn/t1/studentMapper.xml"/>
<mapper resource="com/cn/t3/stu.xml"/>
<mapper resource="com/cn/t4/sc.xml"/>
<mapper resource="com/cn/entity/studentMapper.xml"/>
</mappers>
从上边的类容,我们可以看出mybatis同样的对JDBC进行了封装
5.下面我们cdus,以及存储过程的调用,五个方面来认识mybatis这个持久层框架:
首先搭建项目的大概模块
接下来,我们编写用于得到解析数据库连接配置文件的sqlsessionfactory,dbhelp类
此类用于给外部提供借口用于得到sqlsessionfactory,将其放在com.cn.dao下
package com.cn.dao;
import java.io.IOException;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class dbhelp {
private final static SqlSessionFactory sqlsessionfactory;
static{
String resource="myconfig.xml";
Reader reader=null;
try {
reader=Resources.getResourceAsReader(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlsessionfactory=new SqlSessionFactoryBuilder().build(reader);
}
public static SqlSessionFactory getSqlSessionFactory(){
return sqlsessionfactory;
}
}
接下来编写用于具体数据库操作的映射文件student.xml
1.增加数据
编写一个类测试一下
结果:
对应的XML:
<insert id="insert" parameterType="com.cn.entity.Student">
insert into stu(bId,sName) values(#{bId},#{sName})
</insert>
代码部分
@Test
public void insertStudent(){
Student s=new Student(1,"丰");
SqlSessionFactory ssf=dbhelp.getSqlSessionFactory();
sqlsession=ssf.openSession();
sqlsession.insert("com.cn.entity.studentMapper.insert",s);
sqlsession.commit();
}
2.删除数据(包括对单表的删除,以及对关联表的删除,对关联表涉及的多表删除可以用最简单的方法删除多次删除,还可以通过调用存储过程,也可以通过使用触发器)
在这里我们把单表的删除和多表删除一起演示一遍(最简单的方式)
(1)最简单方式
XML部分:
<delete id="deleteonebanji" parameterType="Int">
delete from banji where bId=#{bId}
</delete>
<delete id="deleteonestu" parameterType="Int">
delete from stu where bId=#{bId}
</delete>
代码部分:
@Test
public void insertStudent(){
SqlSessionFactory ssf=dbhelp.getSqlSessionFactory();
sqlsession=ssf.openSession();
sqlsession.delete("com.cn.entity.studentMapper.deleteonestu",3);
sqlsession.delete("com.cn.entity.studentMapper.deleteonebanji",3);
sqlsession.commit();
}
(2)运用 存储过程来实现:
首先在数据库中创建相应的存储过程:
create procedure pro_delete
@p_bId int
as
delete from stu where bId=@p_bId
delete from banji where bId=@p_bId
go
xml部分:
<delete id="deletepro" parameterType="int" statementType="CALLABLE">
{call pro_delete(#{bId})}
</delete>
代码部分:
@Test
public void insertStudent(){
SqlSessionFactory ssf=dbhelp.getSqlSessionFactory();
sqlsession=ssf.openSession();
sqlsession.delete("com.cn.entity.studentMapper.deletepro",4);
sqlsession.commit();
}
(3)运用触发器实现:
在数据库中创建触发器:
create trigger tridelte
on banji
for delete
as
delete stu
from stu b,deleted d
where b.bId=d.bId
xml部分:
<delete id="deleteonebanji" parameterType="Int">
delete from banji where bId=#{bId}
</delete>
代码部分:
@Test
public void deleteStudent(){
SqlSessionFactory ssf=dbhelp.getSqlSessionFactory();
sqlsession=ssf.openSession();
sqlsession.delete("com.cn.entity.studentMapper.deleteonebanji",8);
sqlsession.commit();
}
3.修改数据(以前有一个朋友告诉我,不要把表的主键设置当做有实际意义的字段,比如说学生的ID当做一个表主键。我当时一直没明白这样有什么区别,今天算是明白了一点,一个字段设置成有实际意义,那么不可避免的存在被修改的可能性,一旦它是别人的外键,而且要被修改,修改起来就很麻烦了 。所以避免这样的问题的发生,我们还是把一个表的主键设置成没有实际意义的一个字段,它只用作这条信息的唯一标示)
XML部分:
<update id="update" parameterType="com.cn.entity.Student">
update stu set sName=#{sName} where sId=#{sId}
</update>
<select id="select" parameterType="int" resultType="com.cn.entity.Student">
select * from stu where sId=#{sId}
</select>
代码部分:
@Test
public void updateStudent(){
SqlSessionFactory ssf=dbhelp.getSqlSessionFactory();
sqlsession=ssf.openSession();
Student s=sqlsession.selectOne("com.cn.entity.studentMapper.select",12);
s.setsName("丰你真棒");
sqlsession.update("com.cn.entity.studentMapper.update",s);
sqlsession.commit();
sqlsession.close();
}
4.查询数据(表之间的关联关系在此我们只考虑一对多,多对一,以及多对多)
首先将需要用到的表转化为相应的javabean
(1)一对多
XML部分:
<select id="selectbanstu" parameterType="Int" resultMap="ban">
select * from banji where bId=#{bId}
</select>
<resultMap id="ban" type="com.cn.entity.banji">
<id column="bId" property="bId"/>
<result column="bName" property="bName"/>
<collection column="bId" property="stu" select="selectStu"/>
</resultMap>
<select id="selectStu" parameterType="int" resultType="com.cn.entity.Student">
select * from stu where bId=#{bId}
</select>
代码部分:
@Test
public void selectOneToMany(){
SqlSessionFactory ssf=dbhelp.getSqlSessionFactory();
sqlsession=ssf.openSession();
banji b=sqlsession.selectOne("com.cn.entity.studentMapper.selectbanstu",9);
System.out.println(b);
sqlsession.close();
}
(2)多对一
XM;L部分:
<select id="selectStua" parameterType="int" resultMap="stua">
select * from stu s,banji b where s.bId=b.bId and s.sId=#{sId}
</select>
<resultMap id="stua" type="com.cn.entity.Student" >
<id column="sId" property="sId"/>
<result column="bId" property="bId"/>
<result column="sName" property="sName"/>
<association column="bId" property="bj" select="selectbanji"/>
</resultMap>
<select id="selectbanji" parameterType="int" resultType="com.cn.entity.banji">
select * from banji where bId=#{bId}
</select>
代码部分:
@Test
public void selectManyToOne(){
SqlSessionFactory ssf=dbhelp.getSqlSessionFactory();
sqlsession=ssf.openSession();
Student s=sqlsession.selectOne("com.cn.entity.studentMapper.selectStua",19);
System.out.println(s);
sqlsession.close();
}
(3)多对多
XML部分:
<select id="selectmangtomany" parameterType="int" resultMap="stu_c">
select * from stu_c sc,course c,stu s where sc.cId=c.cId and sc.sId=s.sId and sc.sId=#{sId}
</select>
<resultMap type="com.cn.entity.Stu_c" id="stu_c">
<result column="sId" property="sId"/>
<result column="cId" property="cId"/>
<association column="sId" property="stu" select="selectStuf"/>
<association column="cId" property="course" select="selectCoursef"/>
</resultMap>
<select id="selectStuf" parameterType="int" resultType="com.cn.entity.Student">
select * from stu where sId=#{sId}
</select>
<select id="selectCoursef" parameterType="int" resultType="com.cn.entity.Course">
select * from course where cId=#{cId}
</select>
代码部分:
@Test
public void selectManyToOne(){
SqlSessionFactory ssf=dbhelp.getSqlSessionFactory();
sqlsession=ssf.openSession();
List s=sqlsession.selectList("com.cn.entity.studentMapper.selectmangtomany",5);
System.out.println(s);
sqlsession.close();
}
关于mybatis的xml配置文件的编写:刚开始我觉得有点不好记,有点麻烦,但是到后来发现其实它的配置文件的编写还是很简单的。<select><delete><insert><update>对应数据库的增删改查,我们只需要记住输入参数类型,以及返回类型。这里需要注意的是返回类型,有可能是一个复杂的类型所以我们需要用<resultmap>来表示<result>用来描述这个返回结果使javabean和数据库能够对应,对于javabean中实体类属性,用<association>.对于javabean中集合属性用<colleacion>.