MyBatis 詳解(一對一,一對多,多對多)


1、什么是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)。

  MyBatis 是支持普通 SQL查詢,存儲過程和高級映射的優秀持久層框架。MyBatis 消除了幾乎所有的JDBC代碼和參數的手工設置以及結果集的檢索。MyBatis 使用簡單的 XML或注解用於配置和原始映射,將接口和 Java 的POJOs(Plain Ordinary Java Objects,普通的 Java對象)映射成數據庫中的記錄。

PS:本文所有代碼下載鏈接:http://pan.baidu.com/s/1gf8CPQN 密碼:t2x9 

  再給大家推薦一個比較好的mybatis學習網站:www.mybatis.cn

2、MyBatis 入門實例基於xml配置

  ①、創建MySQL數據庫:mybatisDemo和表:person

create database mybatisDemo;
use mybatisDemo;
create table person(pid int primary key AUTO_INCREMENT, pname varchar(50), page int);

  

 

  ②、建立一個Java工程,並導入相應的jar包

   

  相應的 jar 包下載鏈接:http://pan.baidu.com/s/1skZM09Z  密碼:nkt6

  

   ③、在 MyBatisDemo 工程中添加數據庫配置文件 mybatis-configuration.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>
<!-- 可以配置多個運行環境,但是每個 SqlSessionFactory 實例只能選擇一個運行環境   
  一、development:開發模式
   二、work:工作模式-->
 <environments default="development">
 <!--id屬性必須和上面的default一樣  -->
    <environment id="development">
    <!--事務管理器
    	一、JDBC:這個配置直接簡單使用了 JDBC 的提交和回滾設置。它依賴於從數據源得到的連接來管理事務范圍
    	二、MANAGED:這個配置幾乎沒做什么。它從來不提交或回滾一個連接。而它會讓容器來管理事務的整個生命周期
    		比如 spring 或 JEE 應用服務器的上下文,默認情況下,它會關閉連接。然而一些容器並不希望這樣,
    		因此如果你需要從連接中停止它,就可以將 closeConnection 屬性設置為 false,比如:
    		<transactionManager type="MANAGED">
				<property name="closeConnection" value="false"/>
			</transactionManager>
      -->
      <transactionManager type="JDBC"/>
      <!--dataSource 元素使用標准的 JDBC 數據源接口來配置 JDBC 連接對象源  -->
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatisdemo"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
      </dataSource>
    </environment>
  </environments>
</configuration>

  

  ④、定義表所對應的實體類

  

package com.ys.bean;

public class Person {
	private int pid;
	private String pname;
	private int page;
	
	public int getPid() {
		return pid;
	}
	public void setPid(int pid) {
		this.pid = pid;
	}
	public String getPname() {
		return pname;
	}
	public void setPname(String pname) {
		this.pname = pname;
	}
	public int getPage() {
		return page;
	}
	public void setPage(int page) {
		this.page = page;
	}
	@Override
	public String toString() {
		return "Person [pid=" + pid + ", pname=" + pname + ", page=" + page
				+ "]";
	}
}

  

  ⑤、定義操作 person 表的sql映射文件personMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ys.bean.personMapper">
  <!-- 根據 pid 查詢 person 表中的數據
  	   id:唯一標識符,此文件中的id值不能重復
  	   resultType:返回值類型,一條數據庫記錄也就對應實體類的一個對象
  	   parameterType:參數類型,也就是查詢條件的類型
   -->
  <select id="selectPersonById" 
  			resultType="com.ys.bean.Person" parameterType="int">
  	<!-- 這里和普通的sql 查詢語句差不多,對於只有一個查詢條件后面的 #{pid}表示占位符,里面不一定要寫pid,寫啥都可以,但是不要空着;如果有多個查詢條件,則要寫pojo類里面的屬性 -->
    select * from person where pid = #{pid}
  </select>
  
  <!-- 查詢person 表所有數據 -->
  <select id="getAllPerson" resultType="com.ys.bean.Person">
  	select * from person
  </select>
  
  <!-- 根據id更新數據 -->
  <update id="updatePersonById" parameterType="com.ys.bean.Person">
  	update person set pname=#{pname},page=#{page} where pid = #{pid}
  </update>
  
  <!-- 向 person 表插入一條數據 -->
  <insert id="addPerson" parameterType="com.ys.bean.Person">
  	insert into person(pid,pname,page) values(#{pid},#{pname},#{page})
  </insert>
  
  <!-- 根據 pid 刪除數據 -->
  <delete id="deletePersonById" parameterType="Long">
  	delete from person where pid=#{pid}
  </delete>
  
</mapper>

  

  ⑥、向 mybatis-configuration.xml 配置文件中注冊 personMapper.xml 文件

  <mappers>
         <!-- 注冊personMapper.xml文件, 
         personMapper.xml位於com.ys.bean這個包下,所以resource寫成com/ys/bean/personMapper.xml-->
         <mapper resource="com/ys/bean/personMapper.xml"/>
  </mappers>

  如下圖所示:

 

   ⑦、創建測試類

package com.ys.test;

import java.io.InputStream;
import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;

import com.ys.bean.Person;

public class MyBatisTest {
	SqlSession session;
	
	@Before
	public void beforeLoadXML(){
		//加載 mybatis 配置文件
		InputStream inputStream = MyBatisTest.class.
				getClassLoader().getResourceAsStream("mybatis-configuration.xml");
		//構建sqlSession的工廠
		SqlSessionFactory sqlSessionFactory =
				new SqlSessionFactoryBuilder().build(inputStream);
		//根據 sqlSessionFactory 產生 session
		session = sqlSessionFactory.openSession();
	}
	
	//根據 pid 查詢 person 表中的數據
	@Test
	public void testSelectById(){
		//這個字符串有 personMapper.xml 文件中 兩個部分構成
		//<mapper namespace="com.ys.bean.personMapper"> 的 namespace 的值
		//<select id="selectPersonById" > id 值
		String statement = "com.ys.bean.personMapper"+".selectPersonById";
		Person p = session.selectOne(statement, 1);
		System.out.println(p);
		session.close();
	}
	
	//查詢person 表所有數據
	@Test
	public void testGetAllPerson(){
		String statement = "com.ys.bean.personMapper.getAllPerson";
		List<Person> listPerson = session.selectList(statement);
		System.out.println(listPerson);
		session.close();
	}
	
	//根據id更新數據 
	@Test
	public void updateById(){
		String statement = "com.ys.bean.personMapper.updatePersonById";
		Person p = new Person();
		p.setPid(1);
		p.setPname("aaa");
		p.setPage(11);
		session.update(statement, p);
		session.commit();
		session.close();
	}
	
	//向 person 表插入一條數據
	@Test
	public void addPerson(){
		String statement = "com.ys.bean.personMapper.addPerson";
		Person p = new Person();
		//由於我們設置了主鍵的自增長機制,故這里不需要手動設置 pid 的值
		//p.setPid(1);
		p.setPname("add");
		p.setPage(11);
		session.insert(statement, p);
		session.commit();
		session.close();
	}
	
	//根據 pid 刪除person 表中的數據
	@Test
	public void deletePersonById(){
		String statement = "com.ys.bean.personMapper.deletePersonById";
		session.delete(statement, 1);
		session.commit();
		session.close();
		
	}
	

}

  

 

3、MyBatis 入門實例注解配置

   ①、上面的前面四步都是一樣的,但是第五步不一樣,我們不需要創建 personMapper.xml 文件,首先在 src 目錄下創建 personMapper.java 文件

  

   內容如下:

package com.ys.annocation;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import com.ys.bean.Person;

public interface PersonMapper {
	
	@Insert("insert into person(pid,pname,page) values(#{pid},#{pname},#{page})")
	public int add(Person person); 
	
	@Select("select * from person where pid = #{pid}")
	public Person getPerson(int pid);
	
	@Update("update person set pname=#{pname},page=#{page} where pid = #{pid}")
	public int updatePerson(Person preson);
	
	@Delete("delete from person where pid=#{pid}")
	public int deletePerson(int pid);

}

  ②、向 mybatis-configuration.xml 配置文件中注冊 personMapper.xml 文件

 

   ③、編寫測試類

	@Test
	public void testAnnocation(){
		PersonMapper mapper = session.getMapper(PersonMapper.class);
		Person p = new Person();
		p.setPid(7);
		p.setPname("abc");
		p.setPage(11);
		//調用增加方法
		mapper.add(p);
		//調用查詢方法
		Person p1 = mapper.getPerson(3);
		System.out.println(p1);
		//調用更新方法
		p.setPage(100);
		mapper.updatePerson(p);
		//調用刪除方法
		mapper.deletePerson(7);
		session.commit();
		session.close();
	}

 

4、MyBatis 入門實例  一對一  基於xml配置

  這里我們以老師和班級為例,假設一般班級只能擁有有一個老師,一個老師只能帶一個班級。

  ①、創建實體類

  

 

  Teacher.java

package one.to.one;

public class Teacher {
	private int tid;
	private String tname;
	private Classes classes;
	
	public int getTid() {
		return tid;
	}
	public void setTid(int tid) {
		this.tid = tid;
	}
	public String getTname() {
		return tname;
	}
	public void setTname(String tname) {
		this.tname = tname;
	}
	public Classes getClasses() {
		return classes;
	}
	public void setClasses(Classes classes) {
		this.classes = classes;
	}
	@Override
	public String toString() {
		return "Teacher [tid=" + tid + ", tname=" + tname + ", classes=" + classes + "]";
	}
	
	
}

  Classes.java

package one.to.one;

public class Classes {
	private int cid;
	private String cname;
	private Teacher teacher;
	
	public int getCid() {
		return cid;
	}
	public void setCid(int cid) {
		this.cid = cid;
	}
	public String getCname() {
		return cname;
	}
	public void setCname(String cname) {
		this.cname = cname;
	}
	public Teacher getTeacher() {
		return teacher;
	}
	public void setTeacher(Teacher teacher) {
		this.teacher = teacher;
	}
	@Override
	public String toString() {
		return "Classes [cid=" + cid + ", cname=" + cname + ", teacher=" + teacher + "]";
	}
	
}

 

  ②、在數據庫中根據實體類創建相應的數據表

 

  ③、定義操作 Classes 表的sql映射文件classesMapper.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="one.to.one.classesMapper">
	<!-- 
         方式一:嵌套結果:使用嵌套結果映射來處理重復的聯合結果的子集
                 封裝聯表查詢的數據(去除重復的數據)
         select * from classes c, teacher t where c.tid=t.tid and c.tid=#{tid}
     -->
	<select id="getClasses" resultMap="getClassesMap" parameterType="int">
		select * from classes c ,teacher t 
			where c.tid=t.tid and c.tid=#{tid}
	</select>
	<resultMap type="one.to.one.Classes" id="getClassesMap">
		<id column="cid" property="cid"/>
		<result column="cname" property="cname"/>
		<association property="teacher" javaType="one.to.one.Teacher">
			<id column="tid" property="tid"></id>
			<result column="tname" property="tname"/>
		</association>
	</resultMap>
	<!-- 
         方式一:嵌套結果:使用嵌套結果映射來處理重復的聯合結果的子集
                 封裝聯表查詢的數據(去除重復的數據)
         select * from teacher t,classes c where t.cid = c.cid and t.cid=#{cid}
     -->
	<select id="getTeacher" resultMap="getTeacherMap" parameterType="int">
		select * from teacher t,classes c
			where t.cid = c.cid and t.cid=#{cid}
	</select>
	<resultMap type="one.to.one.Teacher" id="getTeacherMap">
		<id column="tid" property="tid"/>
		<result column="tname" property="tname"/>
		<association property="classes" javaType="one.to.one.Classes">
			<id column="cid" property="cid"/>
			<result column="cname" property="cname"/>
		</association>
	</resultMap>
	
	
	<!-- 
         方式二:嵌套查詢:通過執行另外一個SQL映射語句來返回預期的復雜類型
         SELECT * FROM classes WHERE cid=1;
         SELECT * FROM teacher WHERE tid=1   //1 是上一個查詢得到的tid的值
         property:別名(屬性名)    column:列名 -->
          <!-- 把teacher的字段設置進去 -->
	<select id="getClasses2" resultMap="getClassesMap2">
		select * from classes c where c.cid = #{cid}
	</select>
	<resultMap type="one.to.one.Classes" id="getClassesMap2">
		<id column="cid" property="cid"/>
		<result column="cname" property="cname"/>
		<collection property="teacher" column="tid" select="getTeacherCollection">
		</collection>
	</resultMap>
	<select id="getTeacherCollection" resultType="one.to.one.Teacher">
		select tid tid,tname tname from teacher where tid=#{tid}
	</select>
  
</mapper>

  說明:我們這里一對一的關聯操作,有兩種方式:

    1、使用嵌套結果映射來處理重復的聯合結果的子集

    2、通過執行另外一個SQL映射語句來返回預期的復雜類型

    相關屬性解釋:

    

 

  ④、向 mybatis-configuration.xml 配置文件中注冊 classesMapper.xml 文件

  

  ⑤、編寫測試類

package one.to.one;

import java.io.InputStream;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;

import com.ys.test.MyBatisTest;

public class OneToOneTest {
SqlSession session;
	
	@Before
	public void beforeLoadXML(){
		//加載 mybatis 配置文件
		InputStream inputStream = MyBatisTest.class.
				getClassLoader().getResourceAsStream("mybatis-configuration.xml");
		//構建sqlSession的工廠
		SqlSessionFactory sqlSessionFactory =
				new SqlSessionFactoryBuilder().build(inputStream);
		//根據 sqlSessionFactory 產生 session
		session = sqlSessionFactory.openSession();
	}
	
	//一對一嵌套結果方式:根據教師id查詢班級信息
	@Test
	public void testGetClasses(){
		String statement = "one.to.one.classesMapper.getClasses";
		Classes c = session.selectOne(statement, 1);
		System.out.println(c);
	}
	
	//一對一嵌套結果方式:根據班級id查詢教師信息
	@Test
	public void testGetTeacher(){
		String statement = "one.to.one.classesMapper.getTeacher";
		Teacher t = session.selectOne(statement, 1);
		System.out.println(t);
	}
	
	//一對一嵌套查詢方式:根據教師id查詢班級信息
	@Test
	public void testGetClasses2(){
		String statement = "one.to.one.classesMapper.getClasses2";
		Classes c = session.selectOne(statement, 1);
		System.out.println(c);
	}
	
	

}

  

 

4、MyBatis 入門實例  一對多,多對一  基於xml配置

  這里我們以班級和學生為例,一個班級里面對應多個學生,這是一對多;反過來,多個學生對應一個班級,這是多對一

  ①、建立學生和班級的實體類

  Student.java

package one.to.many;

public class Student {
	private int sid;
	private String sname;
	private Classes classes;
	public int getSid() {
		return sid;
	}
	public void setSid(int sid) {
		this.sid = sid;
	}
	public String getSname() {
		return sname;
	}
	public void setSname(String sname) {
		this.sname = sname;
	}
	public Classes getClasses() {
		return classes;
	}
	public void setClasses(Classes classes) {
		this.classes = classes;
	}
	@Override
	public String toString() {
		return "Student [sid=" + sid + ", sname=" + sname + ", classes=" + classes + "]";
	}
	
}

    Classes.java

package one.to.many;

import java.util.Set;

public class Classes {
	private int cid;
	private String cname;
	private Set<Student> students;
	
	public int getCid() {
		return cid;
	}
	public void setCid(int cid) {
		this.cid = cid;
	}
	public String getCname() {
		return cname;
	}
	public void setCname(String cname) {
		this.cname = cname;
	}
	public Set<Student> getStudents() {
		return students;
	}
	public void setStudents(Set<Student> students) {
		this.students = students;
	}
	@Override
	public String toString() {
		return "Classes [cid=" + cid + ", cname=" + cname + ", students=" + students + "]";
	}
}

  

  ②、在數據庫中根據實體類創建相應的數據表

 

  ③、多對一:定義操作 Classes 表的sql映射文件classesMapper.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="one.to.many.classesMapper">
  	<select id="getClasses" resultMap="getClassesMap">
  		select * from classes c,student s where s.cid=c.cid and c.cid=#{cid}
  	</select>
  	<resultMap type="one.to.many.Classes" id="getClassesMap">
  		<id column="cid" property="cid"></id>
  		<result column="cname" property="cname"/>
  		<collection property="students" ofType="one.to.many.Student">
  			<id column="sid" property="sid"/>
  			<result column="sname" property="sname"/>
  		</collection>
  	</resultMap>
  	
</mapper>

  ④、一對多:定義操作 Student 表的sql映射文件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="many.to.one.studentMapper">
  	<select id="getStudents" resultMap="getStudentMap">
  		select * from classes c,student s where s.cid=c.cid and s.sid=#{sid}
  	</select>
  	<resultMap type="one.to.many.Student" id="getStudentMap">
  		<id column="sid" property="sid"></id>
  		<result column="sname" property="sname"/>
  		<association property="classes" javaType="one.to.many.Classes">
  			<id column="cid" property="cid"/>
  			<result column="cname" property="cname"/>
  		</association>
  	</resultMap>
  	
</mapper>

  ⑤、向 mybatis-configuration.xml 配置文件中注冊 classesMapper.xml 、studentMapper.xml文件

  ⑥、編寫測試類

package one.to.many;

import java.io.InputStream;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;

import com.ys.test.MyBatisTest;

public class OneToManyTest {
SqlSession session;
	
	@Before
	public void beforeLoadXML(){
		//加載 mybatis 配置文件
		InputStream inputStream = MyBatisTest.class.
				getClassLoader().getResourceAsStream("mybatis-configuration.xml");
		//構建sqlSession的工廠
		SqlSessionFactory sqlSessionFactory =
				new SqlSessionFactoryBuilder().build(inputStream);
		//根據 sqlSessionFactory 產生 session
		session = sqlSessionFactory.openSession();
	}
	
	//一對多嵌套結果方式:根據班級id查詢班級所有的學生信息
	@Test
	public void testGetClasses(){
		String statement = "one.to.many.classesMapper.getClasses";
		Classes c = session.selectOne(statement, 1);
		System.out.println(c);
		System.out.println(c.getStudents().size());
	}
	
	
	//多對一嵌套結果方式:根據學生id查詢班級信息
	@Test
	public void testGetStudents(){
		String statement = "many.to.one.studentMapper.getStudents";
		Student s = session.selectOne(statement, 1);
		System.out.println(s);
		System.out.println(s.getClasses());
	}
	
	

}

 

5、MyBatis 入門實例  多對多  基於xml配置

  這里我們以 users 表和 groups 表為例,一個 users 可能加入多個 groups,而一個 groups 可能包含多個 users,故構成 多對多 的關聯

  ①、在數據庫中建立相應的表

  users 表

  

  groups 表

  

  兩者之間的關聯表users_groups表

  

  ②、建立對應的實體類

  Users.java

package many.to.many;

import java.util.Set;

public class Users {
	private int uid;
	private String uname;
	private Set<Groups> groups;
	public int getUid() {
		return uid;
	}
	public void setUid(int uid) {
		this.uid = uid;
	}
	public String getUname() {
		return uname;
	}
	public void setUname(String uname) {
		this.uname = uname;
	}
	public Set<Groups> getGroups() {
		return groups;
	}
	public void setGroups(Set<Groups> groups) {
		this.groups = groups;
	}
	@Override
	public String toString() {
		return "User [uid=" + uid + ", uname=" + uname + ", groups=" + groups + "]";
	}
	
}

    Groups.java

package many.to.many;

import java.util.Set;

public class Groups {
	private int gid;
	private String gname;
	private Set<Users> users;
	public int getGid() {
		return gid;
	}
	public void setGid(int gid) {
		this.gid = gid;
	}
	public String getGname() {
		return gname;
	}
	public void setGname(String gname) {
		this.gname = gname;
	}
	public Set<Users> getUsers() {
		return users;
	}
	public void setUsers(Set<Users> users) {
		this.users = users;
	}
	@Override
	public String toString() {
		return "Group [gid=" + gid + ", gname=" + gname + ", users=" + users + "]";
	}
	
}

    Users_Groups.java

package many.to.many;

public class Users_Groups {
	private Users user;
	private Groups group;
	public Users getUser() {
		return user;
	}
	public void setUser(Users user) {
		this.user = user;
	}
	public Groups getGroup() {
		return group;
	}
	public void setGroup(Groups group) {
		this.group = group;
	}

}

  ③、多對多:定義操作 sql映射文件userMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="many.to.many.userMapper">
	<!-- 給一個用戶 id,查看該用戶下的所有用戶組信息 -->
  	<select id="getUsers" resultMap="getGroupMap">
  		select g.gid,g.gname from users_groups ug,groups g 
  			where ug.group_id=g.gid and ug.user_id=#{uid}
  	</select>
  	<resultMap type="many.to.many.Groups" id="getGroupMap">
  		<id column="gid" property="gid"/>
  		<result column="gname" property="gname"/>
  		<collection property="users" ofType="many.to.many.Users">
  			<id column="uid" property="uid"/>
  		<result column="uname" property="uname"/>
  		</collection>
  	</resultMap>
  	
</mapper>

  

  ⑤、向 mybatis-configuration.xml 配置文件中注冊 userMapper.xml文件

  ⑥、編寫測試類

//多對多:根據根據用戶 id 查詢所有的用戶組信息
	@Test
	public void testGetGroups(){
		String statement = "many.to.many.userMapper.getUsers";
		List<Groups> listGroup = session.selectList(statement,1);
		for(Groups g : listGroup){
			System.out.println(g.toString());
		}
	}

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM