MyBatis是一個支持普通SQL查詢,存儲過程和高級映射的優秀持久層框架。MyBatis消除了幾乎所有的JDBC代碼和參數的手工設置以及對結果集的檢索封裝。MyBatis可以使用簡單的XML或注解用於配置和原始映射,將接口和Java的POJO(Plain Old Java Objects,普通的Java對象)映射成數據庫中的記錄。
無論是用過的hibernate,mybatis,你都可以法相他們有一個共同點:
1. 從配置文件(通常是XML配置文件中)得到 sessionfactory.
2. 由sessionfactory 產生 session
3. 在session 中完成對數據的增刪改查和事務提交等.
4. 在用完之后關閉session 。
5. 在java 對象和 數據庫之間有做mapping 的配置文件,也通常是xml 文件。
1:實體類Student
建立一個簡單的學生類,用來保存學生信息
package com.zhao.entity; import java.io.Serializable; public class Student implements Serializable { private static final long serialVersionUID = 1L; private int stu_id; private String stu_name; private String stu_gender; public Student() { } public Student(String stu_name, String stu_gender) { this.stu_name = stu_name; this.stu_gender = stu_gender; } public Student(int stu_id, String stu_name, String stu_gender) { this.stu_id = stu_id; this.stu_name = stu_name; this.stu_gender = stu_gender; } public int getStu_id() { return stu_id; } public void setStu_id(int stu_id) { this.stu_id = stu_id; } public String getStu_name() { return stu_name; } public void setStu_name(String stu_name) { this.stu_name = stu_name; } public String getStu_gender() { return stu_gender; } public void setStu_gender(String stu_gender) { this.stu_gender = stu_gender; } @Override public String toString() { return "Student [stu_id=" + stu_id + ", stu_name=" + stu_name + ", stu_gender=" + stu_gender + "]"; } }
2:jdbc.properties+Configuration.xml
myBatis的配置文件Configuration.xml和hibernate的配置文件hibernate.cfg.xml差不多。都是用於數據庫連接的,驅動 url 賬號 密碼必不可少。我們可以用jdbc.properties來保存這些信息,前段時間搭建SSH架構的時候也是把數據庫信息寫到一個properties中。
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis username=root password=密碼
1)Configuration.xml 是 mybatis 用來建立 sessionFactory 用的,里面主要包含了數據庫連接相關東西。
2)Configuration里有 java 類所對應的別名,這個別名非常重要。在引用實體類的時候可以用別名來代替,就不用把實體類的全路徑都寫出來了。
3) Configuration.xml 里面 的
<mapper resource="com/zhao/entity/Student.xml" />是包含要映射的類的xml配置文件。
MyBatis的配置文件很好理解,必須做的兩個事就是數據庫的配置 和 要映射的類的配置文件,hibernate叫對象關系映射文件。這二者還是有區別的。
<?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> <!-- 引用jdbc.properties配置文件 --> <properties resource="jdbc.properties" /> <!-- 配置實體類的別名,配置實體類別名的目的是為了在引用實體類時可以使用實體類的別名來代替實體類,達到簡寫的目的 --> <typeAliases> <typeAlias alias="Student" type="com.zhao.entity.Student" /> <!-- 為com.zhao.entity包下的所有實體類配置別名,MyBatis默認的設置別名的方式就是去除類所在的包后的簡單的類名 比如com.zhao.entity.Student這個實體類的別名就會被設置成Student <package name="com.zhao.entity"/> --> </typeAliases> <!-- development : 開發模式; work : 工作模式 --> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <!-- 配置數據庫連接信息 --> <dataSource type="POOLED"> <property name="driver" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> <!-- 要映射的類的xml配置文件 --> <mappers> <mapper resource="com/zhao/entity/Student.xml" /> <mapper class="com.zhao.mapper.StudentMapper" /> </mappers> </configuration>
3:Student.xml
這個文件可能看起來比較復雜,不像hibernate那樣清晰,他們二者是有區別的。
1:hibernate通過對象關系映射文件把實體類的屬性和數據表的列對應起來,是在這個配置文件里完成對應的工作的,所有我們的對象關系映射文件看起來很簡單,就是一些對應關系。只有完成了這個對應關系,我們才可以在代碼中通過對實體類的操作實現數據庫表信息的改變。注意,hibernate對表的操作是在代碼中的。相應的出現了Query SQLQuery這些東西,都是為了方便我們操作數據表。
2:myBatis的映射配置文件中居然把數據表的操作寫的這么清楚。雖然我也看着比較亂吧。沒有了實體類和數據表一一對應的過程了,這是對hibernate的一個簡化。
分析:下面完成了數據表student的增刪改查。
1)<select><insert><update><delete>這幾個標簽很清晰的告訴我們可以在這里寫什么操作。
2)parmeterType就是參數類型,可以通過id刪除數據,idJ就是int型的。resultType顯然就是返回值類型,就是這么簡單粗暴
3)mapper的namespace屬性很重要。我們是用過這個屬性來找這個文件的。這個namespace和下面標簽的id是一起用的,只要這樣我們才能定位到具體的操作
4)還有一個隱藏問題,我的實體類和數據表的屬性都是一一對應的,可是萬一二者不對應怎么辦。比如說 實體類是stu_id 數據表是id.很明顯這會出問題,你看,我們在遍歷的時候會從數據表返回信息 id ,但是我們會得到的是實體類student的對象,這才是orm嘛。可以stu_id和id不匹配,在hibernate中我們是通過對象關系映射文件來處理這個問題的,可如今這個文件被我們用來寫具體的操作了,怎么辦?
1] 通過在查詢的sql語句中定義字段名的別名,讓字段名的別名和實體類的屬性名一致,這樣就可以表的字段名和實體類的屬性名一一對應上了,這種方式是通過在sql語句中定義別名來解決字段名和屬性名的映射關系的。
2] 通過<resultMap>來映射字段名和實體類屬性名的一一對應關系。這種方式是使用MyBatis提供的解決方式來解決字段名和屬性名的映射關系的。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd" > <!-- 為這個mapper指定一個唯一的namespace,namespace的值習慣上設置成包名+sql映射文件名,這樣就能夠保證namespace的值是唯一的 --> <mapper namespace="com.zhao.entity.StudentMapper"> <!-- 在select標簽中編寫查詢的SQL語句, 設置select標簽的id屬性為selectStudentById,id屬性值必須是唯一的,不能夠重復 使用parameterType屬性指明查詢時使用的參數類型,resultType屬性指明查詢返回的結果集類型 --> <select id="selectStudentById" parameterType="int" resultType="Student"> select * from Student where stu_id=#{id} </select> <select id="queryStudent" resultMap="resultQueryStudent"> select * from Student </select> <delete id="deleteStudentById" parameterType="int"> delete from Student where stu_id=#{stu_id} </delete> <!-- 以#{stu_name}的形式引用Student參數 的stu_name屬性,MyBatis將使用反射讀取Student參數 的此屬性。#{stu_name}中stu_name大小寫敏感。seGeneratedKeys設置 為"true"表明要MyBatis獲取由數據庫自動生成的主 鍵;keyProperty="id"指定把獲取到的主鍵值注入 到Student的id屬性 --> <insert id="insertStudent" parameterType="Student" useGeneratedKeys="true" keyProperty="stu_id"> insert into Student(stu_name,stu_gender) values(#{stu_name},#{stu_gender}) </insert> <update id="updateStudentById" parameterType="Student"> update Student set stu_name=#{stu_name},stu_gender=#{stu_gender} where stu_id=#{stu_id} </update> <resultMap type="Student" id="resultQueryStudent"> <id column="stu_id" property="stu_id" /> <result column="stu_name" property="stu_name" /> <result column="stu_gender" property="stu_gender" /> </resultMap> </mapper>
4:測試代碼
這有個很有意思的事情,我們的事務是通過session來提交的。session.commit()。開始我寫這些代碼的時候怎么都沒有改變數據表的信息,也就是數據沒提交,我才想起來是這個問題。hibernate是通過session創建transaction來提交的。這里都讓session自己把事干了。其實在寫MyBatis的配置文件Configuration.xml時我就應該意識到這個問題,如果不是session提交,那我們還寫事務干嘛。
MyBatis里 sqlsession的方法簽名有很多,多看看,就知道下面的代碼怎么寫了。
package com.zhao.entity; import static org.junit.Assert.*; import java.io.FileInputStream; import java.io.InputStream; import java.io.Reader; import org.apache.ibatis.io.Resources; 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 java.util.List; public class StudentTest { /* * MyBatis加載配置文件 * 1:使用類加載器加載mybatis的配置文件(它也加載關聯的映射文件); * 2:使用MyBatis提供的Resources類加載mybatis的配置文件(它也加載關聯的映射文件) */ private SqlSessionFactory factory; @Before public void before(){ try{ /* * 1: * Reader reader =Resources.getResourceAsReader("Configuration.xml"); * factory = new SqlSessionFactoryBuilder().build(reader); */ //2: InputStream inputStream = StudentTest.class.getClassLoader().getResourceAsStream("Configuration.xml"); factory = new SqlSessionFactoryBuilder().build(inputStream); } catch (Exception e) { e.printStackTrace(); } } @Test public void testSelectStudentById() { SqlSession session = factory.openSession(); try { Student student = (Student) session.selectOne("com.zhao.entity.StudentMapper.selectStudentById", 1); System.out.println(student); session.commit(); } finally { session.close(); } } @Test public void testQueryStudent() { SqlSession session = factory.openSession(); try { List<Student> students=session.selectList("queryStudent"); for (Student student : students) { System.out.println(student); } session.commit(); } finally { session.close(); } } @Test public void testDeleteStudentById() { SqlSession session = factory.openSession(); try { int result=session.delete("deleteStudentById",4); System.out.println(result); session.commit(); } finally { session.close(); } } @Test public void testUpdateStudentById() { SqlSession session = factory.openSession(); try { Student student=new Student(3,"zhao", "男"); session.update("updateStudentById", student); session.commit(); } finally { session.close(); } } @Test public void testInsertStudent() { SqlSession session = factory.openSession(); try { Student student=new Student("zhao", "z"); session.insert("insertStudent", student); session.commit(); } finally { session.close(); } } }