1. 程式人生 > >Java進階學習第三十三天(MyBatis)

Java進階學習第三十三天(MyBatis)

一、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物件,讓垃圾回收站儘早回收

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.g