這里先吐槽下,寫的半天的東西,IE瀏覽器彈出調試窗口導致寫的東西全部沒保存,搞得我還要重新用谷歌寫,思路全沒了,fuck.
前面學習了下spring的DAO層,說起DAO層,那ORM肯定是少不了的,ORM的框架也比較多,做C#的時候用EF,現在Java的話流行SSM,所以就想着學習下Mybatis,參考這EF的幾篇博客,打算MyBatis這塊也系統的學習下,主要涉及單表增刪改查、屬性與列名映射、表之間關系映射、事務與鎖、存儲過程、緩存、Spring與MyBatis結合這幾塊,可能隨着深入的學習還會有慢慢補充。今天主要學習單表的增刪改查。
一、准備
1.引入庫
這里新建了一個maven的project,既然是MyBatis,肯定少不了pom.xml中引入它,同時與數據庫交換,這里用的是mysql,所以也少不了mysql連接庫。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>Cuiyw</groupId> <artifactId>MyBatisDemo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>MyBatisDemo</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.1</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
2.創建Model
既然是ORM,那肯定也得有對象,所以創建model.這里創建了一個簡單的User類。
package Cuiyw.MyBatis.Model; public class User { @Override public String toString() { // TODO Auto-generated method stub return "User [id=" + Id + ", name=" + Name + ", age=" + Age + "]"; } public int getId() { return Id; } public void setId(int id) { Id = id; } public String getName() { return Name; } public void setName(String name) { Name = name; } public int getAge() { return Age; } public void setAge(int age) { Age = age; } private int Id; private String Name; private int Age; }
3.創建數據庫表
ORM要做持久化,那少不了數據庫,這里創建了MyBatis數據庫,並增加了user表。
CREATE DATABASE `mybatis` /*!40100 DEFAULT CHARACTER SET utf8 */; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `NAME` varchar(20) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
二、MyBatis使用
前面算是把准備工作做完了,那下面就是開始MyBatis的使用了,這里主要是單表的增刪改查。處理增刪改查的時候首先要解決的是怎么把User類與數據庫中的user表對應起來,對象關系映射那肯定得有個映射才對。於是乎UserMapper出現了,用它來映射數據庫處理得一些操作。
<?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,namespace的值習慣上設置成包名+sql映射文件名,這樣就能夠保證namespace的值是唯一的 例如namespace="Cuiyw.MyBatis.DBMapping.UserMapper"就是Cuiyw.MyBatis.DBMapping(包名)+UserMapper(UserMapper.xml文件去除后綴) --> <mapper namespace="Cuiyw.MyBatis.DBMapping.UserMapper"> <!-- 在select標簽中編寫查詢的SQL語句, 設置select標簽的id屬性為getUser,id屬性值必須是唯一的,不能夠重復 使用parameterType屬性指明查詢時使用的參數類型,resultType屬性指明查詢返回的結果集類型 resultType="Cuiyw.MyBatis.Model.User"就表示將查詢結果封裝成一個User類的對象返回 User類就是user表所對應的實體類 --> <!-- 根據id查詢得到一個user對象 --> <select id="getUser" parameterType="int" resultType="Cuiyw.MyBatis.Model.User"> select * from user where id=#{id} </select> <select id="getUserList" resultType="Cuiyw.MyBatis.Model.User"> select * from user </select> <insert id="addUser" parameterType="Cuiyw.MyBatis.Model.User"> <selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id"> SELECT LAST_INSERT_ID() </selectKey> insert into user(name,age) values (#{name},#{age}) </insert> <delete id="deleteUserById" parameterType="int"> delete from user where id=#{id} </delete> <update id="updateUser" parameterType="Cuiyw.MyBatis.Model.User"> update user set name=#{name},age=#{age} where id=#{id} </update> </mapper>
上面UserMapper.xml中配置了對user表的增刪改查,有了UserMapper.xml,算是項目中與表user扯上關系了,通過傳入傳出參數也與User類扯上了關系,不過還差一步,就是目前並不知道是映射到哪個數據庫,地址多少,所以還需要一個數據庫配置文件。這里要提下insert,其他幾個都是直接一條sql,而insert與其他不一樣,主要是為了演示新增返回主鍵值。
<?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="development"> <environment id="development"> <transactionManager type="JDBC" /> <!-- 配置數據庫連接信息 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <mappers> <!-- 注冊UserMapper.xml文件, UserMapper.xml位於Cuiyw.MyBatis.DBMapping這個包下,所以resource寫成meCuiyw/MyBatis/DBMapping/UserMapper.xml--> <mapper resource="Cuiyw/MyBatis/DBMapping/UserMapper.xml"/> </mappers> </configuration>
1.新增
先了解下insert的屬性。
parameterType:入參的全限定類名或類型別名
keyColumn:設置數據表自動生成的主鍵名。對特定數據庫(如PostgreSQL),若自動生成的主鍵不是第一個字段則必須設置
keyProperty:默認值unset,用於設置getGeneratedKeys方法或selectKey子元素返回值將賦值到領域模型的哪個屬性中
useGeneratedKeys:取值范圍true|false(默認值),設置是否使用JDBC的getGenereatedKeys方法獲取主鍵並賦值到keyProperty設置的領域模型屬性中。MySQL和SQLServer執auto-generated key field,因此當數據庫設置好自增長主鍵后,可通過JDBC的getGeneratedKeys方法獲取。但像Oralce等不支持auto-generated key field的數據庫就不能用這種方法獲取主鍵了
statementType:取值范圍STATEMENT,PREPARED(默認值),CALLABLE
flushCache:取值范圍true(默認值)|false,設置執行該操作后是否會清空二級緩存和本地緩存
timeout:默認為unset(依賴jdbc驅動器的設置),設置執行該操作的最大時限,超時將拋異常
databaseId:取值范圍oracle|mysql等,表示數據庫廠家,元素內部可通過`<if test="_databaseId = 'oracle'">`來為特定數據庫指定不同的sql語句
這里有兩個知識點,第一個是commit()提交的問題。我剛開始是按照下面寫的.
//mybatis的配置文件 String resource = "DBConfig.xml"; //使用MyBatis提供的Resources類加載mybatis的配置文件(它也加載關聯的映射文件) Reader reader = Resources.getResourceAsReader(resource); //構建sqlSession的工廠 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); //創建能執行映射文件中sql的sqlSession SqlSession session = sessionFactory.openSession(); String statement="Cuiyw.MyBatis.DBMapping.UserMapper.addUser"; User user=new User(); user.setName("Cuiyw"); user.setAge(27); int result=session.insert(statement, user); session.close(); System.out.println(user.getId());
在main中運行上面的代碼,也能打印出返回的主鍵值,但當我打開數據庫表查詢時並沒有找到數據,當時覺得時沒刷新,刷新了好幾變還是沒有,又去百度了下,參考其他博客發現時自己少了session.commit(),增加上之后發現數據庫也有值了。
//mybatis的配置文件 String resource = "DBConfig.xml"; //使用MyBatis提供的Resources類加載mybatis的配置文件(它也加載關聯的映射文件) Reader reader = Resources.getResourceAsReader(resource); //構建sqlSession的工廠 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); //創建能執行映射文件中sql的sqlSession SqlSession session = sessionFactory.openSession(); String statement="Cuiyw.MyBatis.DBMapping.UserMapper.addUser"; User user=new User(); user.setName("Cuiyw"); user.setAge(27); int result=session.insert(statement, user); session.commit(); session.close(); System.out.println(user.getId());
但有搜了幾篇文章,發現有的insert時也沒調用commit(),剛開始懷疑是不是代碼遺漏了,還看了下面的評論,怎么也沒人說,這不科學啊,於是有繼續百度查找原因,終於還是找到了,原來SqlSessionFactory的openSession中有個是帶布爾值參數的方法autoCommit,默認是false,代表不是自定提交,所以當我創建session時傳入true后,也不用再寫commit()方法了。
//mybatis的配置文件 String resource = "DBConfig.xml"; //使用MyBatis提供的Resources類加載mybatis的配置文件(它也加載關聯的映射文件) Reader reader = Resources.getResourceAsReader(resource); //構建sqlSession的工廠 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); //創建能執行映射文件中sql的sqlSession SqlSession session = sessionFactory.openSession(true); String statement="Cuiyw.MyBatis.DBMapping.UserMapper.addUser"; User user=new User(); user.setName("Cuiyw"); user.setAge(27); int result=session.insert(statement, user); //session.commit(); session.close(); System.out.println(user.getId());
第二個是獲取主鍵的問題。這個也是之前做C#的時候遇到過,所以想着看下MyBatis是怎么實現,除了除了上面使用selectKey的方式還可以在insert中直接配置keyProperty和useGeneratedKeys。
selectKey常用屬性如下:
作用:在insert元素和update元素中插入查詢語句。
keyProperty:默認值unset,用於設置getGeneratedKeys方法或selectKey子元素返回值將賦值到領域模型的哪個屬性中
resultType:keyPropety所指向的屬性類全限定類名或類型別名
order屬性:取值范圍BEFORE|AFTER,指定是在insert語句前還是后執行selectKey操作
statementType:取值范圍STATEMENT,PREPARED(默認值),CALLABLE
2.刪改查
其實這幾個是比較類似的,都是SqlSession中調用對應的方法。下面是先增加一個user,然后修改,遍歷和刪除
public static void main( String[] args ) throws IOException { //mybatis的配置文件 String resource = "DBConfig.xml"; //使用MyBatis提供的Resources類加載mybatis的配置文件(它也加載關聯的映射文件) Reader reader = Resources.getResourceAsReader(resource); //構建sqlSession的工廠 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); //創建能執行映射文件中sql的sqlSession SqlSession session = sessionFactory.openSession(true); System.out.println("新增"); String statement="Cuiyw.MyBatis.DBMapping.UserMapper.addUser"; User user=new User(); user.setName("Cuiyw"); user.setAge(27); int result=session.insert(statement, user); //session.commit(); //session.close(); System.out.println(user.getId()); System.out.println("查詢單個"); statement="Cuiyw.MyBatis.DBMapping.UserMapper.getUser"; user=session.selectOne(statement, user.getId()); //session.close(); System.out.println(user.toString()); System.out.println("修改"); statement="Cuiyw.MyBatis.DBMapping.UserMapper.updateUser"; user.setName("Cuiye Update"); result=session.update(statement, user); System.out.println("遍歷所有"); statement="Cuiyw.MyBatis.DBMapping.UserMapper.getUserList"; List<User> users=session.selectList(statement); // session.close(); for(int i=0;i<users.size();i++) { System.out.println(users.get(i)); } session.commit(); System.out.println("刪除"); statement="Cuiyw.MyBatis.DBMapping.UserMapper.deleteUserById"; session.delete(statement,user.getId()); System.out.println("刪除之后遍歷所有"); statement="Cuiyw.MyBatis.DBMapping.UserMapper.getUserList"; users=session.selectList(statement); session.close(); for(int i=0;i<users.size();i++) { System.out.println(users.get(i)); } }

