Java进阶学习第三十三天(MyBatis)

版权声明:使用本品须Jack Gao同意,违者必究 https://blog.csdn.net/Mr_GaoYang/article/details/85099420

一、MyBatis基础

1、回顾jdbc开发
① 优点:简单易学、上手快、非常灵活构建SQL、效率高
② 缺点:代码繁琐,难以写出高质量的代码(例如:资源的释放,SQL注入安全性等)开发者既要写业务逻辑,又要写对象的创建和销毁,必须管底层具体数据库的语法(例如:分页)。
③ 适合于超大批量数据的操作,速度快
④ 开发步骤
◇ 加载数据库驱动
◇ 通过DriverManager获取Statement/PreparedStatement中去,准备向数据库发送SQL语句
◇ 执行完SQL语句之后,返回对象的结果ResultSet=executeQuery(查询)/int i=executeUpdate(增/删/改)
◇ 如果以查询为例,迭代结果集进行处理while(rs.next){String name = rs.getString("name")}
◇ 依次关闭连接对象ResultSet/Statement/Connection,如果上述操作需要作非查询的话,还需要事务支持conn.setAutoConmmit(false);conn.commit()/conn.rollback;

2、回顾hibernate单表开发
① 优点:不用写SQL,完全以面向对象的方式设计和访问,不用管底层具体数据库的语法,(例如:分页)便于理解。
②缺点:处理复杂业务时,灵活度差, 复杂的HQL难写难理解,例如多表查询的HQL语句
③ 适合于中小批量数据的操作,速度慢
④ 开发步骤
◇ 创建Configuration,目的是加载src/hibernate.cfg.xml配置文件,该配置文件又去加载Hero.hbm.xml文件
◇ 通过Configuration创建重量级SessionFactory
◇ 通过SessionFactory创建轻量级Session
◇ 通过Session创建Transaction
◇ 如果做增删改操作的话,一定要事务,如果做查询,事务可选
◇ 操作Session常用的api,例如:save()/update()/saveOrUpdate()/delete()
◇ 事务提交,出错事务回滚
◇ 关闭Session

3、mybatis的特点
① 基于上述二种支持,我们需要在中间找到一个平衡点呢?结合它们的优点,摒弃它们的缺点,这就是myBatis,现今myBatis被广泛的企业所采用。
② MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
③ iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)
④ jdbc/dbutils/springdao,hibernate/springorm,mybaits同属于ORM解决方案之一

4、mybatis快速入门
① 创建一个mybatis-day01这么一个javaweb工程或java工程
② 导入mybatis和mysql/oracle的jar包到/WEB-INF/lib目录下
③ 创建students.sql表(mysql语法)

create table students(
   id  int(5) primary key,
   name varchar(10),
   sal double(8,2)
);

create table students(
   students_id  int(5) primary key,
   students_name varchar(10),
   students_sal double(8,2)
);

④ 创建Student.java

public class Student {
	private Integer id;//编号
	private String name;//姓名
	private Double sal;//薪水
	public Student(){}
	public Student(Integer id, String name, Double sal) {
		this.id = id;
		this.name = name;
		this.sal = sal;
	}
	public Integer getId() {
		System.out.println("getId()");
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		System.out.println("getName()");
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Double getSal() {
		System.out.println("getSal()");
		return sal;
	}
	public void setSal(Double sal) {
		this.sal = sal;
	}
}

⑤ 在entity目录下创建StudentMapper.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">

<!-- namespace属性是名称空间,必须唯一 -->
<mapper namespace="cn.itcast.javaee.mybatis.app04.Student">	
	<!-- resultMap标签:映射实体与表 
	type属性:表示实体全路径名;id属性:为实体与表的映射取一个任意的唯一的名字
	-->
	<resultMap type="student" id="studentMap">
		<!-- id标签:映射主键属性
			result标签:映射非主键属性
			property属性:实体的属性名;column属性:表的字段名	 
		-->							
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sal" column="sal"/>
	</resultMap>

	<!-- 
	insert标签:要书写insert的sql语句
	id属性:为insert这么一个sql语句取一个任意唯一的名字
	parameterType:要执行的dao中的方法的参数,如果是类的话,必须使用全路径类
	-->
	<insert id="add1">
		insert into students(id,name,sal) values(1,'哈哈',7000)
	</insert>

	<insert id="add2" parameterType="student">
	insert into students(id,name,sal) values(#{id},#{name},#{sal})
	</insert>
</mapper>

⑥ 在src目录下创建mybatis.xml配置文件,提倡放在src目录下,文件名任意

<?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="cn.itcast.javaee.mybatis.app04.Student" alias="student"/>
	</typeAliases>

	<!-- 设置一个默认的连接环境信息 -->
	<environments default="mysql_developer">
		<!-- 连接环境信息,取一个任意唯一的名字 -->
		<environment id="mysql_developer">
			<!-- mybatis使用jdbc事务管理方式 -->
			<transactionManager type="jdbc"/>
			<!-- mybatis使用连接池方式来获取连接 -->
			<dataSource type="pooled">
				<!-- 配置与数据库交互的4个必要属性 -->
				<property name="driver" value="${mysql.driver}"/>
				<property name="url" value="${mysql.url}"/>
				<property name="username" value="${mysql.username}"/>
				<property name="password" value="${mysql.password}"/>
			</dataSource>
		</environment>

		<!-- 连接环境信息,取一个任意唯一的名字 -->
		<environment id="oracle_developer">
			<!-- mybatis使用jdbc事务管理方式 -->
			<transactionManager type="jdbc"/>
			<!-- mybatis使用连接池方式来获取连接 -->
			<dataSource type="pooled">
				<!-- 配置与数据库交互的4个必要属性 -->
				<property name="driver" value="${oracle.driver}"/>
				<property name="url" value="${oracle.url}"/>
				<property name="username" value="${oracle.username}"/>
				<property name="password" value="${oracle.password}"/>
			</dataSource>
		</environment>
	</environments>

	<!-- 加载映射文件-->
	<mappers>
		<mapper resource="cn/itcast/javaee/mybatis/app14/StudentMapper.xml"/>
	</mappers>
</configuration>

db.properties

mysql.driver=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://127.0.0.1:3306/mybatis
mysql.username=root
mysql.password=root

oracle.driver=oracle.jdbc.driver.OracleDriver
oracle.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
oracle.username=scott
oracle.password=tiger

⑦ 在util目录下创建MyBatisUtil.java类,并测试与数据库是否能连接

public class MybatisUtil {
	private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
	private static SqlSessionFactory sqlSessionFactory;
	/**
	 * 加载位于src/mybatis.xml配置文件
	 */
	static{
		try {
			Reader reader = Resources.getResourceAsReader("mybatis.xml");
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 禁止外界通过new方法创建 
	 */
	private MybatisUtil(){}
	
	/**
	 * 获取SqlSession
	 */
	public static SqlSession getSqlSession(){
		//从当前线程中获取SqlSession对象
		SqlSession sqlSession = threadLocal.get();
		//如果SqlSession对象为空
		if(sqlSession == null){
			//在SqlSessionFactory非空的情况下,获取SqlSession对象
			sqlSession = sqlSessionFactory.openSession();
			//将SqlSession对象与当前线程绑定在一起
			threadLocal.set(sqlSession);
		}
		//返回SqlSession对象
		return sqlSession;
	}
	
	/**
	 * 关闭SqlSession与当前线程分开
	 */
	public static void closeSqlSession(){
		//从当前线程中获取SqlSession对象
		SqlSession sqlSession = threadLocal.get();
		//如果SqlSession对象非空
		if(sqlSession != null){
			//关闭SqlSession对象
			sqlSession.close();
			//分开当前线程与SqlSession对象的关系,目的是让GC尽早回收
			threadLocal.remove();
		}
	}

	/**
	 * 测试
	 */
	public static void main(String[] args) {
		Connection conn = MybatisUtil.getSqlSession().getConnection();
		System.out.println(conn!=null?"连接成功":"连接失败");
	}
}

⑧ 在dao目录下创建StudentDao.java类并测试

public class StudentDao {
	public void add1() throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			//事务开始(默认)
			//读取StudentMapper.xml映射文件中的SQL语句
			int i = sqlSession.insert("cn.itcast.javaee.mybatis.app04.Student.add1");
			System.out.println("本次操作影响了"+i+"行");
			//事务提交
			sqlSession.commit();
		}catch(Exception e){
			e.printStackTrace();
			//事务回滚
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	
	public void add2(Student student) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			//事务开始(默认)
			//读取StudentMapper.xml映射文件中的SQL语句
			sqlSession.insert(Student.class.getName()+".add2",student);
			//事务提交
			sqlSession.commit();
		}catch(Exception e){
			e.printStackTrace();
			//事务回滚
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	
	public static void main(String[] args) throws Exception{
		StudentDao dao = new StudentDao();
		dao.add1();
		dao.add2(new Student(2,"呵呵",8000D));
	}
}

5、mybatis工作流程
① 通过Reader对象读取src目录下的mybatis.xml配置文件(该文本的位置和名字可任意)
② 通过SqlSessionFactoryBuilder对象创建SqlSessionFactory对象
③ 从当前线程中获取SqlSession对象
④ 事务开始,在mybatis中默认
⑤ 通过SqlSession对象读取StudentMapper.xml映射文件中的操作编号,从而读取sql语句
⑥ 事务提交【必写】
⑦ 关闭SqlSession对象,并且分开当前线程与SqlSession对象,让垃圾回收站尽早回收

扫描二维码关注公众号,回复: 4668624 查看本文章

6、MybatisUtil工具类的作用
① 在静态初始化块中加载mybatis配置文件和StudentMapper.xml文件一次
② 使用ThreadLocal对象让当前线程与SqlSession对象绑定在一起
③ 获取当前线程中的SqlSession对象,如果没有的话,从SqlSessionFactory对象中获取SqlSession对象
④ 获取当前线程中的SqlSession对象,再将其关闭,释放其占用的资源

7、基于MybatisUtil工具类,完成CURD操作
① StudentDao.java

public class StudentDao1 {
	/**
	 * 增加学生
	 */
	public void add(Student student) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			sqlSession.insert(Student.class.getName()+".add",student);
			sqlSession.commit();
		}catch(Exception e){
			e.printStackTrace();
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	/**
	 * 根据ID查询学生 
	 */
	public Student findById(int id) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			Student student = sqlSession.selectOne(Student.class.getName()+".findById",id);
			sqlSession.commit();
			return student;
		}catch(Exception e){
			e.printStackTrace();
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	/**
	 * 查询所有学生 
	 */
	public List<Student> findAll() throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			return sqlSession.selectList(Student.class.getName()+".findAll");
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	/**
	 * 更新学生 
	 */
	public void update(Student student) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			sqlSession.update(Student.class.getName()+".update",student);
			sqlSession.commit();
		}catch(Exception e){
			e.printStackTrace();
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	/**
	 * 删除学生 
	 */
	public void delete(Student student) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			sqlSession.delete(Student.class.getName()+".delete",student);
			sqlSession.commit();
		}catch(Exception e){
			e.printStackTrace();
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	

	public static void main(String[] args) throws Exception{
		StudentDao1 dao = new StudentDao1();
		//dao.add(new Student(1,"哈哈",7000D));
		//dao.add(new Student(2,"呵呵",8000D));
		//dao.add(new Student(3,"班长",9000D));
		//dao.add(new Student(4,"键状高",10000D));
		//Student student = dao.findById(4);
		//List<Student> studentList = dao.findAll();
		//for(Student student : studentList){
		//	System.out.print(student.getId()+":"+student.getName()+":"+student.getSal());
		//	System.out.println();
		//}
		//Student student = dao.findById(3);
		//student.setName("靓班长");
		//dao.update(student);
		
		Student student = dao.findById(3);
		System.out.print(student.getId()+":"+student.getName()+":"+student.getSal());
		
		//dao.delete(student);
	}
}

② StudentMapper.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="cn.itcast.javaee.mybatis.app09.Student">	
	<resultMap type="cn.itcast.javaee.mybatis.app09.Student" id="studentMap">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sal" column="sal"/>
	</resultMap>

	<!-- 增加学生 -->
	<insert id="add" parameterType="cn.itcast.javaee.mybatis.app09.Student">
		insert into students(id,name,sal) values(#{id},#{name},#{sal})
	</insert>

	<!-- 根据ID查询学生
		 如果参数不是一个实体的话,只是一个普通变量,例如:int,double,String
		 这里的#{中间的变量名可以随便写},不过提倡就用方法的形参
	 -->
	<select id="findById" parameterType="int" resultType="cn.itcast.javaee.mybatis.app09.Student">
		select id,name,sal from students where id = #{id}
	</select>
	
	<!-- 查询所有学生 
		 理论上resultType要写List<Student>
		 但这里只需书写List中的类型即可,即只需书写Student的全路径名
	-->
	<select id="findAll" resultType="cn.itcast.javaee.mybatis.app09.Student">
		select id,name,sal from students
	</select>

	<!-- 更新学生 -->
	<update id="update" parameterType="cn.itcast.javaee.mybatis.app09.Student">
		update students set name=#{name},sal=#{sal} where id=#{id}
	</update>

	<!-- 删除学生 --> 
	<delete id="delete" parameterType="cn.itcast.javaee.mybatis.app09.Student">
		delete from students where id = #{id}
	</delete>

	<!-- 
	<insert id="delete" parameterType="cn.itcast.javaee.mybatis.app09.Student">
		delete from students where id = #{id}
	</insert>
	-->	

	<!-- 
		注意:这个insert/update/delete标签只是一个模板,在做操作时,其实是以SQL语句为核心的
		     即在做增/删/时,insert/update/delete标签可通用,
		     但做查询时只能用select标签
		     我们提倡什么操作就用什么标签
	-->	
</mapper>
<?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="studentNamespace">	

	<!-- 当实体属性与表字段名不相同的时候,必须书写以下代码
	     当实体属性与表字段名相同的时候,以下代码可选 
	 -->
	<resultMap type="cn.itcast.javaee.mybatis.app09.Student" id="studentMap">
		<id property="id" column="students_id"/>
		<result property="name" column="students_name"/>
		<result property="sal" column="students_sal"/>
	</resultMap>

	<!-- 增加学生 -->
	<insert id="add" parameterType="cn.itcast.javaee.mybatis.app09.Student">
		insert into students(students_id,students_name,students_sal) 
		values(#{id},#{name},#{sal})
	</insert>

	<!-- 根据ID查询学生 
		 mybatis会将查询出来的表记录和studentMap这个id所对应的映射结果相互匹配
	-->
	<select id="findById" parameterType="int" resultMap="studentMap">
		select students_id,students_name,students_sal
		from students
		where students_id = #{xxxxxxxxxxxxxxxxxx}
	</select>
</mapper>

8、分页查询
① StudentDao.java

public class StudentDao {
	/**
	 * 增加学生
	 */
	public void add(Student student) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			sqlSession.insert(Student.class.getName()+".add",student);
			sqlSession.commit();
		}catch(Exception e){
			e.printStackTrace();
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	/**
	 * 无条件分页
	 * @param start 表示在mysql中从第几条记录的索引号开始显示,索引从0开始
	 * @param size 表示在mysql中最多显示几条记录
	 */
	public List<Student> findAllWithFy(int start,int size) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			
			Map<String,Object> map = new LinkedHashMap<String,Object>();
			map.put("pstart",start);
			map.put("psize",size);
			return sqlSession.selectList(Student.class.getName()+".findAllWithFy",map);
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	/**
	 * 有条件分页
	 */
	public List<Student> findAllByNameWithFy(String name,int start,int size) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			Map<String,Object> map = new LinkedHashMap<String, Object>();
			map.put("pname","%"+name+"%");
			map.put("pstart",start);
			map.put("psize",size);			
			return sqlSession.selectList(Student.class.getName()+".findAllByNameWithFy",map);
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	
	public static void main(String[] args) throws Exception{
		StudentDao dao = new StudentDao();
		//for(int i=1;i<=10;i++){
		//	dao.add(new Student(i,"哈哈",7000D));
		//}
		System.out.println("--------------------第一页");
		List<Student> studentList1 = dao.findAllByNameWithFy("哈",0,3);
		for(Student s : studentList1){
			System.out.println(s.getId()+":"+s.getName()+":"+s.getSal());
		}
		System.out.println("--------------------第二页");
		List<Student> studentList2 = dao.findAllByNameWithFy("哈",3,3);
		for(Student s : studentList2){
			System.out.println(s.getId()+":"+s.getName()+":"+s.getSal());
		}
		System.out.println("--------------------第三页");
		List<Student> studentList3 = dao.findAllByNameWithFy("哈",6,3);
		for(Student s : studentList3){
			System.out.println(s.getId()+":"+s.getName()+":"+s.getSal());
		}
	}
}

② StudentMapper.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="cn.itcast.javaee.mybatis.app10.Student">	

	<resultMap type="cn.itcast.javaee.mybatis.app10.Student" id="studentMap">
		<id property="id" column="students_id"/>
		<result property="name" column="students_name"/>
		<result property="sal" column="students_sal"/>
	</resultMap>
	
	
	<insert id="add" parameterType="cn.itcast.javaee.mybatis.app10.Student">
		insert into students(students_id,students_name,students_sal) 
		values(#{id},#{name},#{sal});
	</insert>
		
	<select id="findAllWithFy" parameterType="map" resultMap="studentMap">
		select students_id,students_name,students_sal 
		from students 
		limit #{pstart},#{psize}
	</select>
	
	<select id="findAllByNameWithFy" parameterType="map" resultMap="studentMap">
		select students_id,students_name,students_sal 
		from students 
		where students_name like #{pname}
		limit #{pstart},#{psize}
	</select>
</mapper>

二、动态SQL操作之增删改查

1、查询
查询条件不确定,需要根据情况产生SQL语法,这种情况叫动态SQL
① StudentDao.java

public class StudentDao {
	/**
	 * 有条件的查询所有学生
	 */
	public List<Student> findAll(Integer id,String name,Double sal) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();	
			Map<String,Object> map = new LinkedHashMap<String,Object>();
			map.put("pid",id);
			map.put("pname",name);
			map.put("psal",sal);
			return sqlSession.selectList("studentNamespace.findAll",map);
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	
	public static void main(String[] args) throws Exception{
		StudentDao dao = new StudentDao();
		List<Student> studentList = dao.findAll(5,"哈哈",7000D);
		for(Student s : studentList){
			System.out.println(s.getId()+":"+s.getName()+":"+s.getSal());
		}
	}
}

② StudentMapper.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="studentNamespace">	
	<resultMap type="cn.itcast.javaee.mybatis.app11.Student" id="studentMap">
		<id property="id" column="students_id"/>
		<result property="name" column="students_name"/>
		<result property="sal" column="students_sal"/>
	</resultMap>

	<select id="findAll" parameterType="map" resultMap="studentMap">
		select * from students
		<where>
			<if test="pid!=null">
				and students_id = #{pid}
			</if>
			<if test="pname!=null">
				and students_name = #{pname}
			</if>
			<if test="psal!=null">
				and students_sal = #{psal}
			</if>
		</where>
	</select>
</mapper>

2、更新
更新条件不确定,需要根据情况产生SQL语法,这种情况叫动态SQL
① StudentDao.java

public class StudentDao {
	/**
	 * 有条件更新学生
	 */
	public void dynaUpdate(Integer id,String name,Double sal) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
				
			Map<String,Object> map = new HashMap<String, Object>();
			map.put("pid",id);
			map.put("pname",name);
			map.put("psal",sal);
			sqlSession.update("studentNamespace.dynaUpdate",map);
			sqlSession.commit();
		}catch(Exception e){
			e.printStackTrace();
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	
	public static void main(String[] args) throws Exception{
		StudentDao dao = new StudentDao();
		//关注SQL的变化
		//dao.dynaUpdate(1,null,9000D);//update students set sal=? where id=?
		//dao.dynaUpdate(1,"笨笨",null);//update students set name=? where id=?
		dao.dynaUpdate(1,"笨笨",10000D);//update students set name=? and sal=? where id=?
	}
}

② StudentMapper.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="studentNamespace">	
	<resultMap type="cn.itcast.javaee.mybatis.app12.Student" id="studentMap">
		<id property="id" column="students_id"/>
		<result property="name" column="students_name"/>
		<result property="sal" column="students_sal"/>
	</resultMap>

	<!-- set标签自动判断哪个是最后一个字段,会自动去掉最后一个,号 -->
	<update id="dynaUpdate" parameterType="map">
		update students 
		<set>
			<if test="pname!=null">
				students_name = #{pname},
			</if>
			<if test="psal!=null">
				students_sal = #{psal},			
			</if>
		</set>
		where students_id = #{pid}
	</update>
</mapper>

3、删除
根据ID删除学生
① StudentDao.java

public class StudentDao {
	/**
	 * 根据ID批量删除学生(数组版本)
	 */
	public void dynaDeleteArray(int... ids) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			sqlSession.delete("studentNamespace.dynaDeleteArray",ids);
			sqlSession.commit();
		}catch(Exception e){
			e.printStackTrace();
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	/**
	 * 根据ID批量删除学生(集合版本)
	 */
	public void dynaDeleteList(List<Integer> ids) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			sqlSession.delete("studentNamespace.dynaDeleteList",ids);
			sqlSession.commit();
		}catch(Exception e){
			e.printStackTrace();
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}

	public static void main(String[] args) throws Exception{
		StudentDao dao = new StudentDao();
		//dao.dynaDeleteArray(new int[]{1,3,5,7,77});
		//dao.dynaDeleteArray(1,3,5,7,77);
		//dao.dynaDeleteArray(2,4,444);
		
		List<Integer> ids = new ArrayList<Integer>();
		ids.add(6);
		ids.add(8);
		ids.add(9);
		dao.dynaDeleteList(ids);
	}
}

② StudentMapper.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="studentNamespace">	
	<resultMap type="cn.itcast.javaee.mybatis.app13.Student" id="studentMap">
		<id property="id" column="students_id"/>
		<result property="name" column="students_name"/>
		<result property="sal" column="students_sal"/>
	</resultMap>

	<delete id="dynaDeleteArray">
		delete from students where students_id in
		<!-- foreach用于迭代数组元素
			 open表示开始符号
			 close表示结束符号
			 separator表示元素间的分隔符
			 item表示迭代的数组,属性值可以任意,但提倡与方法的数组名相同
			 #{ids}表示数组中的每个元素值
		 -->
		<foreach collection="array" open="(" close=")" separator="," item="ids">
			#{ids}
		</foreach>
	</delete>

	<delete id="dynaDeleteList">
		delete from students where students_id in
		<foreach collection="list" open="(" close=")" separator="," item="ids">
			#{ids}
		</foreach>
	</delete>
</mapper>

4、插入
根据条件,插入一个学生
① StudentDao.java

public class StudentDao {
	/**
	 * 插入学生
	 */
	public void dynaInsert(Student student) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			sqlSession.insert("studentNamespace.dynaInsert",student);
			sqlSession.commit();
		}catch(Exception e){
			e.printStackTrace();
			sqlSession.rollback();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}

	public static void main(String[] args) throws Exception{
		StudentDao dao = new StudentDao();
		//dao.dynaInsert(new Student(1,"哈哈",7000D));//insert into 表名(*,*,*) values(?,?,?)
		//dao.dynaInsert(new Student(2,"哈哈",null));//insert into 表名(*,*) values(?,?)
		//dao.dynaInsert(new Student(3,null,7000D));//insert into 表名(*,*) values(?,?)
		dao.dynaInsert(new Student(4,null,null));//insert into 表名(*) values(?)
	}
}

② StudentMapper.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="studentNamespace">	
	<resultMap type="cn.itcast.javaee.mybatis.app14.Student" id="studentMap">
		<id property="id" column="students_id"/>
		<result property="name" column="students_name"/>
		<result property="sal" column="students_sal"/>
	</resultMap>

	<!-- sql片段对应字段名,id属性值任意 -->
	<sql id="key">
		<!-- 去掉最后一个, -->
		<trim suffixOverrides=",">
			<if test="id!=null">
				students_id,
			</if>
			<if test="name!=null">
				students_name,
			</if>
			<if test="sal!=null">
				students_sal,
			</if>
		</trim>
	</sql>

	<!-- sql片段对应?,id属性值任意 -->
	<sql id="value">
		<!-- 去掉最后一个, -->
		<trim suffixOverrides=",">
			<if test="id!=null">
				#{id},
			</if>
			<if test="name!=null">
				#{name},
			</if>
			<if test="sal!=null">
				#{sal},
			</if>
		</trim>
	</sql>
	
	<!-- <include refid="key"/>和<include refid="value"/>表示引用上面定义的sql片段 -->
	<insert id="dynaInsert" parameterType="cn.itcast.javaee.mybatis.app14.Student">
		insert into students(<include refid="key"/>) values(<include refid="value"/>)
	</insert>
</mapper>

三、多表查询

1、回顾SQL99中的连接查询

drop table if exists orders;
drop table if exists customers;
drop table if exists emps;
 
create table if not exists customers(
  id int(5) primary key auto_increment,
  name varchar(10) not null,
  age int(2) not null 
);
insert into customers(name,age) values('诸葛亮',33);
insert into customers(name,age) values('孙权',44);
insert into customers(name,age) values('曹操',55);
insert into customers(name,age) values('司马懿',66);

create table if not exists orders(
  id int(5) primary key auto_increment,
  isbn varchar(10) not null,
  price integer not null,
  customers_id int(5),
  constraint customers_id_FK foreign key(customers_id) references customers(id)  
);
insert into orders(isbn,price,customers_id) values('isbn100',100,1);
insert into orders(isbn,price,customers_id) values('isbn200',200,1);
insert into orders(isbn,price,customers_id) values('isbn100',100,1);
insert into orders(isbn,price,customers_id) values('isbn200',200,2);
insert into orders(isbn,price,customers_id) values('isbn100',100,2);
insert into orders(isbn,price,customers_id) values('isbn100',100,3);

create table if not exists emps(
  empno int(5) primary key,
  ename varchar(10),
  mgr int(5)
);
insert into emps(empno,ename,mgr) values(1,'AA',5);
insert into emps(empno,ename,mgr) values(2,'BB',5);
insert into emps(empno,ename,mgr) values(3,'CC',6);
insert into emps(empno,ename,mgr) values(4,'DD',6);
insert into emps(empno,ename,mgr) values(5,'EE',7);
insert into emps(empno,ename,mgr) values(6,'FF',7);
insert into emps(empno,ename,mgr) values(7,'GG',9);
insert into emps(empno,ename,mgr) values(8,'HH',9);
insert into emps(empno,ename,mgr) values(9,'II',NULL);

select * from customers;
select * from orders;
select * from emps;

① 内连接(等值连接):查询客户姓名、订单编号、订单价格

    ---------------------------------------------------
    select c.name,o.isbn,o.price
    from customers c inner join orders o
    where c.id = o.customers_id;
    ---------------------------------------------------
    select c.name,o.isbn,o.price
    from customers c join orders o
    where c.id = o.customers_id; 
    ---------------------------------------------------
    select c.name,o.isbn,o.price
    from customers c,orders o
    where c.id = o.customers_id;
    ---------------------------------------------------
    select c.name,o.isbn,o.price
    from customers c join orders o
    on c.id = o.customers_id;
    ---------------------------------------------------

注意:内连接(等值连接)只能查询出多张表中连接字段相同的记录
② 外连接:按客户分组,查询每个客户的姓名和订单数

    ---------------------------------------------------
    左外连接:
    select c.name,count(o.isbn)
    from  customers c left outer join orders o
    on c.id = o.customers_id
    group by c.name; 
    ---------------------------------------------------
    右外连接:
    select c.name,count(o.isbn)
    from  orders o right outer join customers c   
    on c.id = o.customers_id
    group by c.name; 
    ---------------------------------------------------

注意:外连接既能查询出多张表中连接字段相同的记录,又能根据一方将另一方不符合相同记录强行查询出来
③ 自连接:求出AA的老板是EE

    ---------------------------------------------------
    内自连接:
    select users.ename,boss.ename
    from emps users inner join emps boss 
    on users.mgr = boss.empno;
    ---------------------------------------------------
    外自连接:
    select users.ename,boss.ename
    from emps users left outer join emps boss 
    on users.mgr = boss.empno;
    ---------------------------------------------------

注意:自连接是将一张表,通过别名的方式看作多张表后,再进行连接,这时的连接即可以采用内连接,又可以采用外连接

2、mybatis一对一映射【一名学生对应一张身份证】
① Students.java和Card.java

public class Student {
	private Integer id;
	private String name;
	private Card card;//关联属性
	public Student(){}
	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 Card getCard() {
		return card;
	}
	public void setCard(Card card) {
		this.card = card;
	}
}
public class Card {
	private Integer id;
	private String num;
	public Card(){}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getNum() {
		return num;
	}
	public void setNum(String num) {
		this.num = num;
	}
}

② StudentMapper.xml和CardMapper.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="studentNamespace">
	<resultMap type="cn.itcast.javaee.mybatis.one2one.Student" id="studentMap">
		<id property="id" column="sid"/>
		<result property="name" column="sname"/>
		<!-- 引入CardMapper.xml文件中的映射信息 
			 property表示Student类的关联属性
			 resultMap表示引入CardMapper.xml文件的映射类型
		-->
		<association property="card" resultMap="cardNamespace.cardMap"/>
	</resultMap>	

	<!-- 查询1号学生的信息 -->
	<select id="findById" parameterType="int" resultMap="studentMap">
		select s.sid,s.sname,c.cid,c.cnum
		from students s inner join cards c
		on s.scid = c.cid 		
		and s.sid = #{id}
	</select>
	
	
	<!-- 查询哈哈学生的信息 -->
	<select id="findByName" parameterType="string" resultMap="studentMap">
		select s.sname,c.cnum
		from students s inner join cards c
		on s.scid = c.cid 		
		and s.sname = #{name}
	</select>
</mapper>
<?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="cardNamespace">
	<resultMap type="cn.itcast.javaee.mybatis.one2one.Card" id="cardMap">
		<id property="id" column="cid"/>
		<result property="num" column="cnum"/>
	</resultMap>	
</mapper>

③ StudentCardDao.java

public class StudentCardDao {
	/**
	 * 查询1号学生的信息
	 * @param id 表示学生的编号
	 */
	public Student findById(int id) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			return sqlSession.selectOne("studentNamespace.findById",id);
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	/**
	 * 查询"哈哈"学生的信息
	 * @param name 表示学生的姓名
	 */
	public Student findByName(String name) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			return sqlSession.selectOne("studentNamespace.findByName",name);
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}

	public static void main(String[] args) throws Exception{
		StudentCardDao dao = new StudentCardDao();
		Student s = dao.findById(1);
		System.out.println(s.getId()+":"+s.getName()+":"+s.getCard().getId()+":"+s.getCard().getNum());
		
		System.out.println("-------------------------------");
		s = dao.findByName("哈哈");
		System.out.println(s.getName()+"的身份证号码为:" + s.getCard().getNum());
	}
}

3、mybatis一对多映射【一个班级对应一名学生】
① Grade.java和Student.java

public class Grade {
	private Integer id;
	private String name;
	private List<Student> studentList = new ArrayList<Student>();//关联属性
	public Grade(){}
	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 List<Student> getStudentList() {
		return studentList;
	}
	public void setStudentList(List<Student> studentList) {
		this.studentList = studentList;
	}
}
public class Student {
	private Integer id;
	private String name;
	private Grade grade;//关联属性
	public Student(){}
	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 Grade getGrade() {
		return grade;
	}
	public void setGrade(Grade grade) {
		this.grade = grade;
	}
}

② GradeMapper.xml和StudentMapper.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="gradeNamespace">
	<resultMap type="cn.itcast.javaee.mybatis.one2many.Grade" id="gradeMap">
		<id property="id" column="gid"/>
		<result property="name" column="gname"/>
	</resultMap>	

	<!-- 查询哈哈是哪个学科的 -->
	<select id="findByName" parameterType="string" resultMap="gradeMap">
		select g.gname
		from students s inner join grades g
		on s.sgid = g.gid
		and s.sname = #{xxxxx}
	</select>
</mapper>
<?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="studentNamespace">
	<resultMap type="cn.itcast.javaee.mybatis.one2many.Student" id="studentMap">
		<id property="id" column="sid"/>
		<result property="name" column="sname"/>
	</resultMap>	

	<!-- 查询java学科有哪些学生信息 -->
	<select id="findAllByName" parameterType="string" resultMap="studentMap">
		select s.sid,s.sname
		from students s inner join grades g
		on s.sgid = g.gid
		and g.gname = #{namexxxxxxxxxxxxxxxx}
	</select>
</mapper>

③ GradeStudentDao.java

public class GradeStudentDao {
	/**
	 * 查询java学科有哪些学生信息
	 * @param name 表示学科名
	 */
	public List<Student> findAllByName(String name) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			return sqlSession.selectList("studentNamespace.findAllByName",name);
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	
	/**
	 * 查询哈哈是哪个学科的
	 * @param name 表示学生姓名
	 */
	public Grade findByName(String name) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			return sqlSession.selectOne("gradeNamespace.findByName",name);
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}

	public static void main(String[] args) throws Exception{
		GradeStudentDao dao = new GradeStudentDao();
		List<Student> studentList = dao.findAllByName("java");
		System.out.println("java学科有"+studentList.size()+"个学生,它们信息如下:");
		for(Student s : studentList){
			System.out.println(s.getId()+":"+s.getName());
		}
		System.out.println("-----------------------------------------------------------");
		Grade grade = dao.findByName("哈哈");
		System.out.println("哈哈是"+grade.getName()+"学科的");
		System.out.println("-----------------------------------------------------------");
		grade = dao.findByName("呵呵");
		System.out.println("呵呵是"+grade.getName()+"学科的");
	}
}

4、mybatis多对多映射【多名学生对应多门课程】

create table students(
	sid int(5) primary key,
	sname varchar(10)
);
create table courses(
	cid int(5) primary key,
	cname varchar(10)
);
create table middles(
	msid int(5),
	mcid int(5),
	primary key(msid,mcid)
);

① Student.java和Course.java

public class Student {
	private Integer id;
	private String name;
	private List<Course> courseList = new ArrayList<Course>();//关联属性
	public Student(){}
	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 List<Course> getCourseList() {
		return courseList;
	}
	public void setCourseList(List<Course> courseList) {
		this.courseList = courseList;
	}
}
public class Course {
	private Integer id;
	private String name;
	private List<Student> studentList = new ArrayList<Student>();//关联属性
	public Course(){}
	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 List<Student> getStudentList() {
		return studentList;
	}
	public void setStudentList(List<Student> studentList) {
		this.studentList = studentList;
	}
}

② StudentMapper.xml和CourseMapper.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="studentNamespace">
	<resultMap type="cn.itcast.javaee.mybatis.many2many.Student" id="studentMap">
		<id property="id" column="sid"/>
		<result property="name" column="sname"/>
	</resultMap>	

	<select id="findAllByCourseName" parameterType="string" resultMap="studentMap">
		select s.sname
		from students s inner join middles m
		on s.sid = m.msid 
		inner join courses c
		on m.mcid = c.cid
		and c.cname = #{name}
	</select>
</mapper>
<?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="courseNamespace">
	<resultMap type="cn.itcast.javaee.mybatis.many2many.Course" id="courseMap">
		<id property="id" column="cid"/>
		<result property="name" column="cname"/>
	</resultMap>	

	<!-- 查询哈哈选学了哪些课程 -->
	<select id="findAllByName" parameterType="string" resultMap="courseMap">
		select c.cid,c.cname
		from students s inner join middles m
		on s.sid = m.msid
		inner join courses c
		on m.mcid = c.cid
		and s.sname = #{name}
	</select>
</mapper>

③ StudentCourseDao.java

public class StudentCourseDao {
	/**
	 * 查询哈哈选学了哪些课程
	 * @param name 表示学生的姓名
	 */
	public List<Course> findAllByName(String name) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			return sqlSession.selectList("courseNamespace.findAllByName",name);
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
	/**
	 * 查询java课程有哪些学生选修
	 * @param name 表示学生的课程
	 */
	public List<Student> findAllByCourseName(String name) throws Exception{
		SqlSession sqlSession = null;
		try{
			sqlSession = MybatisUtil.getSqlSession();
			return sqlSession.selectList("studentNamespace.findAllByCourseName",name);
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}finally{
			MybatisUtil.closeSqlSession();
		}
	}
		
	public static void main(String[] args) throws Exception{
		StudentCourseDao dao = new StudentCourseDao();
		List<Course> courseList = dao.findAllByName("哈哈");
		System.out.print("哈哈选学了" + courseList.size()+"个课程,分别是:");
		for(Course c : courseList){
			System.out.print(c.getName()+" ");
		}
		System.out.println("\n-----------------------------------------------------");
		List<Student> studentList = dao.findAllByCourseName("android");
		System.out.println("选修了android课程的学生有"+studentList.size()+"个,分别是:");
		for(Student s : studentList){
			System.out.print(s.getName()+" ");
		}
	}
}

四、员工管理系统(springmvc+spring+mybatis+oracle)

1、创建一个spring-mybaits-oracle这么一个javaweb或java工程

2、导入spring、mybatis、c3p0、oracle(或者mysql)、mybatis提供的与spring整合的插件包
① mysql的jar:mysql-connector-java-5.1.7-bin.jar
② oracle的jar:ojdbc5.jar
③ c3p0的jar:c3p0-0.9.1.2.jar
④ mybatis的jar:

asm-3.3.1.jar     
cglib-2.2.2.jar    
commons-logging-1.1.1.jar     
mybatis-3.1.1.jar

⑤ mybatis与spring整合的jar:mybatis-spring-1.1.1.jar
⑥ spring的ioc模块的jar:

org.springframework.asm-3.0.5.RELEASE.jar
org.springframework.beans-3.0.5.RELEASE.jar
org.springframework.context-3.0.5.RELEASE.jar
org.springframework.core-3.0.5.RELEASE.jar
org.springframework.expression-3.0.5.RELEASE.jar
commons-logging.jar

⑦ spring的aop模块的jar:

aopalliance.jar
aspectjweaver.jar
cglib-2.2.2.jar
org.springframework.aop-3.0.5.RELEASE.jar

⑧ spring的transaction模块的jar:

org.springframework.jdbc-3.0.5.RELEASE.jar
org.springframework.orm-3.0.5.RELEASE.jar
org.springframework.transaction-3.0.5.RELEASE.jar

3、创建emps.sql表(使用oracle语法)

create table emps(
	eid number(5) primary key,
	ename varchar2(20),
	esal number(8,2),
	esex varchar2(2)
);

4、创建Emp.java类

public class Emp {
	private Integer id;
	private String name;
	private Double sal;
	private String sex;
	public Emp(){}
	public Emp(Integer id, String name, Double sal, String sex) {
		this.id = id;
		this.name = name;
		this.sal = sal;
		this.sex = sex;
	}
	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 Double getSal() {
		return sal;
	}
	public void setSal(Double sal) {
		this.sal = sal;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
}

5、创建工具类MybatisUtil.java(和spring整合后就不需要使用了)

public class MybatisUtil {
	private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
	private static SqlSessionFactory sqlSessionFactory;
	/**
	 * 加载位于src/mybatis.xml配置文件
	 */
	static{
		try {
			Reader reader = Resources.getResourceAsReader("mybatis.xml");
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	/**
	 * 禁止外界通过new方法创建 
	 */
	private MybatisUtil(){}
	/**
	 * 获取SqlSession
	 */
	public static SqlSession getSqlSession(){
		//从当前线程中获取SqlSession对象
		SqlSession sqlSession = threadLocal.get();
		//如果SqlSession对象为空
		if(sqlSession == null){
			//在SqlSessionFactory非空的情况下,获取SqlSession对象
			sqlSession = sqlSessionFactory.openSession();
			//将SqlSession对象与当前线程绑定在一起
			threadLocal.set(sqlSession);
		}
		//返回SqlSession对象
		return sqlSession;
	}
	/**
	 * 关闭SqlSession与当前线程分开
	 */
	public static void closeSqlSession(){
		//从当前线程中获取SqlSession对象
		SqlSession sqlSession = threadLocal.get();
		//如果SqlSession对象非空
		if(sqlSession != null){
			//关闭SqlSession对象
			sqlSession.close();
			//分开当前线程与SqlSession对象的关系,目的是让GC尽早回收
			threadLocal.remove();
		}
	}

	/**
	 * 测试
	 */
	public static void main(String[] args) {
		Connection conn = MybatisUtil.getSqlSession().getConnection();
		System.out.println(conn!=null?"连接成功":"连接失败");
	}
}

6、创建EmpMapper.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="empNamespace">
	<resultMap type="cn.itcast.javaee.mybatis.entity.Emp" id="empMap">
		<id property="id" column="eid"/>
		<result property="name" column="ename"/>
		<result property="sal" column="esal"/>
		<result property="sex" column="esex"/>
	</resultMap>	
	
	<!-- 增加员工 -->
	<insert id="add" parameterType="cn.itcast.javaee.mybatis.entity.Emp">
		insert into emps(eid,ename,esal,esex) values(#{id},#{name},#{sal},#{sex})
	</insert>
</mapper>

7、在src目录下创建mybatis.xml配置文件

<?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="oracle_developer">
		<environment id="mysql_developer">
			<transactionManager type="jdbc"/>	
			<dataSource type="pooled">
				<property name="driver" value="com.mysql.jdbc.Driver"/>
				<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis"/>
				<property name="username" value="root"/>
				<property name="password" value="root"/>
			</dataSource>
		</environment>
		
		<environment id="oracle_developer">
			<transactionManager type="jdbc"/>	
			<dataSource type="pooled">
				<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
				<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
				<property name="username" value="scott"/>
				<property name="password" value="tiger"/>
			</dataSource>
		</environment>
	</environments>
 	-->

	<mappers>
		<mapper resource="cn/itcast/javaee/mybatis/entity/EmpMapper.xml"/>
	</mappers>
</configuration>

8、创建EmpDao.java类

public class EmpDao {
	private SqlSessionFactory sqlSessionFactory;
	//springioc容器自动注入
	public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
		this.sqlSessionFactory = sqlSessionFactory;
	}
	/**
	 * 增加员工
	 */
	public void add(Emp emp) throws Exception{
		SqlSession sqlSession = sqlSessionFactory.openSession();
		sqlSession.insert("empNamespace.add",emp);
		sqlSession.close();
	}
}

9、创建TestEmpDao.java测试类

public class TestEmpDao {
	//单独测试mybatis(使用MybatisUtil.java工具类)
	@Test
	public void test1() throws Exception{
		EmpDao empDao = new EmpDao();
		empDao.add(new Emp(1,"哈哈",7000D,"男"));
	}
	
	//测试spring整合mybatis
	@Test
	public void test2() throws Exception{
		ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring.xml"});
		EmpDao empDao = (EmpDao) ac.getBean("empDaoID");
		empDao.add(new Emp(2,"明明",8000D,"男"));
	}
}

10、在src目录下创建spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans 
      xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:context="http://www.springframework.org/schema/context"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xmlns:tx="http://www.springframework.org/schema/tx"
	  xmlns:mvc="http://www.springframework.org/schema/mvc"
		
      xsi:schemaLocation="
	
	  http://www.springframework.org/schema/beans 
	  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	  
	  http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-3.0.xsd
 	  
	  http://www.springframework.org/schema/aop 
	  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
	  
	  http://www.springframework.org/schema/tx
      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    
      http://www.springframework.org/schema/mvc
      http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        
      ">

      <!-- 配置C3P0连接池,目的:管理数据库连接 -->
      <bean id="comboPooledDataSourceID" class="com.mchange.v2.c3p0.ComboPooledDataSource">
      		<property name="driverClass" value="oracle.jdbc.driver.OracleDriver"/>
      		<property name="jdbcUrl" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
      		<property name="user" value="scott"/>
      		<property name="password" value="tiger"/>
      </bean>
      
      <!-- 配置SqlSessionFactoryBean,目的:加载mybaits配置文件和映射文件,即替代原Mybatis工具类的作用 -->
      <bean id="sqlSessionFactoryBeanID" class="org.mybatis.spring.SqlSessionFactoryBean">
      		<property name="configLocation" value="classpath:mybatis.xml"/>
      		<property name="dataSource" ref="comboPooledDataSourceID"/>
      </bean>

      <!-- 配置Mybatis的事务管理器,即因为Mybatis底层用的是JDBC事务管事器,所以在这里依然配置JDBC事务管理器 -->
      <bean id="dataSourceTransactionManagerID" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      		<property name="dataSource" ref="comboPooledDataSourceID"/>
      </bean>

      <!-- 配置事务通知,即让哪些方法需要事务支持 -->
      <tx:advice id="tx" transaction-manager="dataSourceTransactionManagerID">
      		<tx:attributes>
      			<tx:method name="*" propagation="REQUIRED"/>
      		</tx:attributes>
      </tx:advice>
      
      <!-- 配置事务切面,即让哪些包下的类需要事务 -->
      <aop:config>
      		<aop:pointcut id="pointcut" expression="execution(* cn.itcast.javaee.mybatis.dao.*.*(..))"/>
     		<aop:advisor advice-ref="tx" pointcut-ref="pointcut"/>
      </aop:config>
      
      <!-- 注册EmpDao -->
      <bean id="empDaoID" class="cn.itcast.javaee.mybatis.dao.EmpDao">
      		<property name="sqlSessionFactory" ref="sqlSessionFactoryBeanID"/>
      </bean>
      
      <!-- 注册EmpService -->
      <bean id="empServiceID" class="cn.itcast.javaee.mybatis.service.EmpService">
      		<property name="empDao" ref="empDaoID"/>
      </bean>

      <!-- 注册EmpAction -->
      <context:component-scan base-package="cn.itcast.javaee.mybatis.action"/>

      <!-- 通知springioc容器这些注解的作用 -->
      <context:annotation-config/>
      
      <!-- 视图解析器 -->
      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      		<property name="prefix" value="/jsp/"/>
      		<property name="suffix" value=".jsp"/>
      </bean>
</beans>         

11、register.jsp

<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>员工注册</title>
  </head>
  <body>
	<form action="${pageContext.request.contextPath}/emp/register.action" method="POST">
		<table border="2" align="center">
			<tr>
				<th>编号</th>
				<td><input type="text" name="id"></td>
			</tr>
			<tr>
				<th>姓名</th>
				<td><input type="text" name="name"></td>
			</tr>
			<tr>
				<th>薪水</th>
				<td><input type="text" name="sal"></td>
			</tr>
			<tr>
				<th>性别</th>
				<td>
					<input type="radio" name="sex" value="男"/>男
					<input type="radio" name="sex" value="女" checked/>女
				</td>
			</tr>
			<tr>
				<td colspan="2" align="center">
					<input type="submit" value="注册"/>
				</td>
			</tr>
		</table>
	</form>		
  </body>
</html>

12、success.jsp

<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>员工注册</title>
  </head>
  <body>
	注册成功<br/>
  </body>
</html>

13、web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	
	<!-- 核心springmvc核心控制器 -->
	<servlet>
		<servlet-name>DispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring.xml</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>DispatcherServlet</servlet-name>
		<url-pattern>*.action</url-pattern>
	</servlet-mapping>
	
	<!-- POST编码过滤器 -->
	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

14、业务层实现类EmpService.java

public class EmpService {
	private EmpDao empDao;
	public void setEmpDao(EmpDao empDao) {
		this.empDao = empDao;
	}
	/**
	 * 注册员工
	 */
	public void register(Emp emp) throws Exception{
		empDao.add(emp);
	}
}

15、单例控制器EmpAction.java

@Controller
@RequestMapping(value="/emp")
public class EmpAction {
	private EmpService empService;
	@Resource(name="empServiceID")
	public void setEmpService(EmpService empService) {
		this.empService = empService;
	}
	/**
	 * 注册员工
	 */
	@RequestMapping(value="/register")
	public String registerMethod(Emp emp) throws Exception{
		//调用业务层
		empService.register(emp);
		return "success";
	}
}

五、jdbc访问oracle存储过程和存储函数

1、准备工作
① c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<default-config>
		<property name="driverClass">oracle.jdbc.driver.OracleDriver</property>
		<property name="jdbcUrl">jdbc:oracle:thin:@127.0.0.1:1521:orcl</property>
		<property name="user">scott</property>
		<property name="password">tiger</property>
		<property name="acquireIncrement">2</property>
		<property name="initialPoolSize">5</property>
		<property name="minPoolSize">1</property>
		<property name="maxPoolSize">5</property>
	</default-config>
</c3p0-config>

② JdbcUtil.java

public class JdbcUtil {
	private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
	public static Connection getConnection() throws Exception{
		return dataSource.getConnection();
	}
}

2、写一个计算个人所得税的应用

--定义过程
create or replace procedure get_rax(salary in number,rax out number)
as
    --需要交税的钱
    bal number;
begin
    bal := salary - 3500;
    if bal<=1500 then
       rax := bal * 0.03 - 0;
    elsif bal<=4500 then
       rax := bal * 0.1 - 105;
    elsif bal<=9000 then
       rax := bal * 0.2 - 555;
    elsif bal<=35000 then
       rax := bal * 0.25 - 1005;
    elsif bal<=55000 then
       rax := bal * 0.3 - 2755;
    elsif bal<=80000 then
       rax := bal * 0.35 - 5505;
    else
       rax := bal * 0.45 - 13505;
    end if;
end;
/

--调用过程
declare
   --交税
   rax number; 
   salary number := &salary;
begin
   get_rax(salary,rax); 
   dbms_output.put_line(salary||'元工资需要交'||rax||'元税');
end;
/

演示java-jdbc调用oracle过程

public class CallOracleProc {
	public static void main(String[] args) throws Exception{
		String sql = "{call get_rax(?,?)}";
		Connection conn = JdbcUtil.getConnection();
		CallableStatement cstmt = conn.prepareCall(sql);
		//为第一个?号设置值,从1开始
		cstmt.setInt(1,7000);
		//为第二个?注册输出类型
		cstmt.registerOutParameter(2,Types.INTEGER);
		//执行调用过程
		cstmt.execute();
		//接收过程的返回值,即第二个?号
		int rax = cstmt.getInt(2);
		//显示
		System.out.println("7000元需要上交"+rax+"元税收");
		cstmt.close();
		conn.close();
	}
}

3、查询7788号员工的的姓名、职位、月薪

--定义函数
create or replace function findEmpNameAndJobAndSal(pempno in number,pjob out varchar2,psal out number) 
return varchar2
as
    pename emp.ename%type;
begin
    select ename,job,sal into pename,pjob,psal from emp where empno = pempno;
    return pename;
end;
/

--调用函数
declare
    pename emp.ename%type;
    pjob   emp.job%type;
    psal   emp.sal%type;
begin
    pename := findEmpNameAndJobAndSal(7788,pjob,psal);
    dbms_output.put_line('7788'||'--'||pename||'--'||pjob||'--'||psal);
end;
/

演示java-jdbc调用oracle函数

public class CallOracleFunc {
	public static void main(String[] args) throws Exception{
		String sql = "{ ? = call findEmpNameAndJobAndSal(?,?,?) }";
		Connection conn = JdbcUtil.getConnection();
		CallableStatement cstmt = conn.prepareCall(sql);
		//为第一个?注册输出类型
		cstmt.registerOutParameter(1,Types.VARCHAR);
		//为第二个?注入值
		cstmt.setInt(2,7788);
		//为第三个?注册输出类型
		cstmt.registerOutParameter(3,Types.VARCHAR);
		//为第四个?注册输出类型
		cstmt.registerOutParameter(4,Types.INTEGER);
		//执行函数调用
		cstmt.execute();
		//分别获取1,3,4占位符的值
		String ename = cstmt.getString(1);
		String job = cstmt.getString(3);
		int sal = cstmt.getInt(4);
		//显示
		System.out.println("7788--"+ename+"--"+job+"--"+sal);
		cstmt.close();
		conn.close();
	}
}

猜你喜欢

转载自blog.csdn.net/Mr_GaoYang/article/details/85099420