【(開課吧javaEE)每日一學190802】mybatis基礎概述與第一個程式
mybatis簡介
什麼是mybatis
- MyBatis是一個優秀的持久層框架,它是一個半自動化的ORM框架
- 它對使用JDBC操作資料庫的過程進行封裝,使開發者只需要關注 SQL 本身,而不需要花費精力去處理例如註冊驅動、建立connection、建立statement、手動設定引數、結果集檢索等jdbc繁雜的過程程式碼。
mybatis在哪寫sql語句
- Mybatis通過XML或註解的方式,將要執行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來。
- 並通過java物件和statement中的sql進行對映生成最終執行的sql語句,最後由mybatis框架執行sql並將結果對映成java物件並返回
JDBC程式碼存在問題以及mybatis解決方式
-
建立資料庫連線相關操作,存在硬編碼 解決方案:通過Mybatis全域性配置檔案,對資料庫連線進行配置
-
statement相關操作,存在硬編碼 解決方案:通過Mapper對映檔案,對statement相關處理進行配置。
-
頻繁開啟資料庫連線,會降低資料庫處理效能。 解決方案:通過Mybatis全域性配置檔案,配置連線池
mybatis架構原理
-
mybatis配置檔案
- SqlMapConfig.xml,此檔案作為mybatis的全域性配置檔案,配置了mybatis的執行環境等資訊。
- Mapper.xml,此檔案作為mybatis的sql對映檔案,檔案中配置了操作資料庫的sql語句。此檔案需要在SqlMapConfig.xml中載入。
-
SqlSessionFactory
- 通過mybatis環境等配置資訊構造SqlSessionFactory,即會話工廠。
-
sqlSession
- 通過會話工廠建立sqlSession即會話,程式設計師通過sqlsession會話介面對資料庫進行增刪改查操作。
-
Executor執行器
- mybatis底層自定義了Executor執行器介面來具體操作資料庫,Executor介面有兩個實現,一個是基本執行器(預設)、一個是快取執行器,sqlsession底層是通過executor介面操作資料庫的。
-
Mapped Statement 它也是mybatis一個底層封裝物件,它包裝了mybatis配置資訊及sql對映資訊等。mapper.xml檔案中一個select\insert\update\delete標籤對應一個Mapped Statement物件,select\insert\update\delete標籤的id即是Mapped statement的id。
- Mapped Statement對sql執行輸入引數進行定義,包括HashMap、基本型別、pojo,Executor通過Mapped Statement在執行sql前將輸入的java物件對映至sql中,輸入引數對映就是jdbc程式設計中對preparedStatement設定引數。
- Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本型別、pojo,Executor通過Mapped Statement在執行sql後將輸出結果對映至java物件中,輸出結果對映過程相當於jdbc程式設計中對結果的解析處理過程。
idea中建立maven專案步驟
選擇file之後new project或者new module後來到如下的頁面:
next之後自己輸入專案點group ID,artifacted id,點選next,然後就是配置maven
配置完之後點選finish即可,但是使用idea建立maven專案時是沒有java和resources以及test目錄的,此時需要自己新建,可以參考別人的文章
同樣的如果是需要test資料夾,首先是在src目錄下建立一個普通的資料夾,然後在test目錄下建立java資料夾和resources資料夾並且設定好對應關係即可:
mybatis的第一個小案例
專案整體目錄結構
資料庫
表的建立語句為:
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL COMMENT '使用者名稱稱',
`birthday` date DEFAULT NULL COMMENT '生日',
`sex` char(1) DEFAULT NULL COMMENT '性別',
`address` varchar(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', '測試1', null, '2', null);
INSERT INTO `user` VALUES ('10', '張三', '2014-07-10', '1', '北京市');
INSERT INTO `user` VALUES ('11', '李四', null, '1', null);
INSERT INTO `user` VALUES ('16', '張小明', null, '1', '河南鄭州');
INSERT INTO `user` VALUES ('22', '陳小明', null, '1', '河南鄭州');
INSERT INTO `user` VALUES ('24', '張三丰', null, '1', '河南鄭州');
INSERT INTO `user` VALUES ('25', '陳小明', null, '1', '河南鄭州');
INSERT INTO `user` VALUES ('26', '王五', null, null, null);
mybatis的主配置檔案SqlMapConfig.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>
<!--載入配置檔案-->
<properties resource="db.properties"></properties>
<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>
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
在主配置檔案中對於使用jdbc連線資料庫時使用了佔位符,因此需要寫資料庫配置檔案,同時在mybatis的主配置檔案中載入了mapper檔案,所以也是需要寫sql對映檔案
資料庫配置檔案db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssm
username=root
password=admin
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">
<!--namespace作用是為了分類管理對映檔案中的MapperdStatement物件-->
<mapper namespace="test">
<select id="findUserById" parameterType="int" resultType="test.User">
select * from User where id = #{id}
</select>
</mapper>
POJO
package test;
import java.util.Date;
public class User {
private int id;
private String username;
private Date birthday;
private String sex;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
測試類
package test;
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.io.IOException;
import java.io.InputStream;
public class TestUser {
// 會話工廠
private SqlSessionFactory sqlSessionFactory;
// 該註解可以在@test註解之前執行
@Before
public void createSqlSessionFactory() throws IOException {
// 載入配置檔案
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 使用sqlSessionFactoryBuilder從xml中建立sqlsessionfactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test() {
SqlSession sqlSession = null;
sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("test.findUserById", 1);
System.out.println(user);
sqlSession.close();
}
}
至此查詢的小案例完成。
擴充套件
測試模糊查詢
sql對映檔案
還是上面的檔案,只是擴充套件了
<!--${value}表示輸入引數將${value}替換,直接做字串的拼接,如果是取簡單型別的引數,括號中的引數名必須是value-->
<select id="findUserByUsername" parameterType="java.lang.String" resultType="test.User">
select * from user where username like '%${value}%'
</select>
測試程式碼
@Test
public void testLike() {
SqlSession sqlSession = null;
sqlSession = sqlSessionFactory.openSession();
List<Object> list = sqlSession.selectList("test.findUserByUsername", "張三");
System.out.println(list.size());
sqlSession.close();
}
上面這樣是沒有問題,不過在寫sql對映檔案時說過如果是取簡單型別,這裡只能使用value,比如這裡如果使用hello,會出現下面的報錯:
上面顯示的沒有hello沒有get方法,但是即使我換成username(這是在pojo中有),雖然不報錯但是查詢結果不對。至於mybatis的模糊查詢可以檢視借鑑文章
測試新增
sql對映檔案
insert id="insertUser" parameterType="test.User">
insert into user(username, birthday, sex, address)
values (#{username}, #{birthday}, #{sex}, #{address})
</insert>
測試程式碼
@Test
public void testInsert() {
SqlSession sqlSession = null;
sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setUsername("王五");
user.setAddress("湖北");
user.setSex("1");
user.setBirthday(new Date());
sqlSession.insert("test.insertUser", user);
// 提交事務
sqlSession.commit();
sqlSession.close();
}
測試主鍵返回
sql對映檔案
<insert id="insertUser" parameterType="test.User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select LAST_INSERT_ID()
</selectKey>
insert into user(username, birthday, sex, address)
values (#{username}, #{birthday}, #{sex}, #{address})
</insert>
新增selectKey標籤實現主鍵返回。
- keyProperty:指定返回的主鍵,儲存在pojo中的哪個屬性
- order:selectKey標籤中的sql的執行順序,是相對與insert語句來說。由於mysql的自增原理,執行完insert語句之後才將主鍵生成,所以這裡selectKey的執行順序為after。
- resultType:返回的主鍵對應的JAVA型別
- LAST_INSERT_ID():是mysql的函式,返回auto_increment自增列新