MyBatis框架快速入門
技術標籤:java
MyBatis框架快速入門
入門案例
建立一個關於Mybatis專案
首先建立一個空專案,然後新建一個moudle,選擇quickstart,接下來把模組放到空專案之下。即可
實現mybatis查詢資料庫的功能
實現步驟:
- 新建studnet表
- 加入maven的mybatis座標,mysql驅動的座標
- 建立實體類,Student–儲存表中的一行資料的
- 建立持久層的dao介面,定義操作資料庫的方法
- 建立一個mybatis使用的配置檔案,叫做sql對映檔案:寫sql語句的。一般一個表一個sql對映檔案。這個檔案是xml檔案
- 建立mybatis的主配置檔案:一個專案就一個主配置檔案。主配置檔案提供了資料庫的連線資訊和sql對映檔案的位置資訊
- 建立使用mybatis類,通過mybatis訪問資料庫。
建立mysql資料庫和表
資料庫建立表student
CREATE TABLE `student` (
`id` int NOT NULL,
`name` varchar(80) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
`age` int DEFAULT NULL,
PRIMARY KEY (`id`)
);
在pom.xml中新增相關依賴(加入maven的mybatis座標,mysql驅動的座標)
<!-- mybatis的依賴-->
< dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<!--mysql驅動-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId >
<version>8.0.19</version>
</dependency>
可以在左側右鍵pom.xml選擇Maven-Reimport,可以在右側maven專案下的Dependencies下檢視依賴項
建立實體類
studnet實體類(domain包下)
package comipingfan.domain;
//推薦和表明一樣。
public class Student {
private Integer id;
private String name;
private String email;
private Integer age;
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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", age='" + age + '\'' +
'}';
}
}
建立dao層下的介面
dao介面(dao包下)
package comipingfan.dao;
import comipingfan.domain.Student;
import java.util.List;
//介面,操作Student表
public interface StudentDao {
//查詢Student表的所有的資料
public List<Student> selectStudents();
//插入方法
public int insertStudent(Student stu);
}
建立mybatis使用的配置檔案,在介面所在的目錄下
StudentDao.xml(dao包下,sql對映檔案)
<?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="comipingfan.dao.StudentDao">
<select id="selectStudents" resultType="comipingfan.domain.Student">
select id,name,email,age from student order by id
</select>
<insert id="insertStudnet">
insert into student values(#{id},#{name},#{email},#{age})
</insert>
</mapper>
對sql檔案的解析:
sql對映檔案:寫sql語句的,mybatis會執行這些sql
1.指定約束檔案:
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
mybatis-3-mapper.dtd是約束檔案的名稱,副檔名是dtd的。
2.約束檔案的作用:限制,檢查在當前檔案中出現的標籤,屬性必須符合要求
3.mapper 是當前問價你的根標籤,必須的。
namespace:叫做名稱空間,可以是自定義的字串
要求你使用dao介面的全限定名稱
4.在當前檔案中,可以使用特定的標籤,表示資料庫的特定操作。
<select>:表示執行查詢
<update>:表示更新資料庫的操作
建立mybatis的主配置檔案
在resource下建立mybatis.xml(mybatis的主配置檔案)
<?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>
<settings>
<!--設定mybatis輸出日誌-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--環境配置: 資料庫的連線資訊
default:必須和某個environment的id值一樣。
告訴mybatis使用哪個資料庫的連線資訊。也就是訪問哪個資料庫
-->
<environments default="mydev">
<environment id="mydev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/springdb?useSSL=false&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="3306"/>
</dataSource>
</environment>
</environments>
<!-- sql mapper(sql對映檔案)的位置-->
<mappers>
<mapper resource="comipingfan/dao/StudentDao.xml"/>
</mappers>
</configuration>
至此,關於mybatis的配置完成。學過maven的就可以知道點選maven下的compile就能夠對該專案進行編譯。都在target目錄下。此時你可能會發現在你的dao包下只有介面檔案(StudnetDao.class)並沒有(xxx.xml檔案)這是因為預設情況下不會處理xml檔案,需要用過外掛進行編譯。
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
會掃描到properties、xml檔案。
測試
public static void main(String[] args) throws IOException {
//訪問mybatis讀取Student資料
//1.定義mybatis主配置檔案的名稱,從類路徑的根開始(target/clasess)
String config="mybatis.xml";
//2.讀取這個config表示的檔案
InputStream in= Resources.getResourceAsStream(config);
//3.建立了SqlSessionFactoryBuilder物件
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
//4.建立SqlSessionFactory物件
SqlSessionFactory factory=builder.build(in);
//5.獲取SqlSession物件,從SqlSessionFactory中獲取SqlSession
SqlSession sqlSession=factory.openSession();
//6.指定執行的sql語句的標識。sql對映檔案中的namespace+"."+標籤的id值
String sqlId="comipingfan.dao.StudentDao"+"."+"selectStudents";
//7.執行sql語句
List<Student>studentList=sqlSession.selectList(sqlId);
//8.輸出結果
studentList.forEach(student -> System.out.println(student));
//9.關閉SqlSession物件
sqlSession.close();
}
總結:關於連線資料庫,初學者可能遇到各種各樣的問題,比如找不到mybatis.xml檔案(這是因為mybatis.xml並沒有被編譯到target/classes下。需要在pom中加入外掛)還需要檢查自己的依賴到底是mysql8還是mysql5。另外mybatis-3.5.2需要mysql5.1x以上的版本
優化mybatis的連線操作
建立MyBatisUtiles工具類
public class MyBatisUtiles {
private static SqlSessionFactory factory=null;
static {
String config="mybatis.xml";
try {
InputStream in= Resources.getResourceAsStream(config);
factory=new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
//獲取SqlSession方法
public static SqlSession getSqlSession(){
SqlSession sqlSession=null;
if(factory!=null){
sqlSession=factory.openSession();//非自動提交事務
}
return sqlSession;
}
}
測試
SqlSession sqlSession= MyBatisUtiles.getSqlSession();
//指定執行的sql語句的標識。sql對映檔案中的namespace+"."+標籤的id值
String sqlId="comipingfan.dao.StudentDao"+"."+"selectStudents";
//執行sql語句
List<Student>studentList=sqlSession.selectList(sqlId);
//輸出結果
studentList.forEach(student -> System.out.println(student));
//關閉SqlSession物件
sqlSession.close();
自定義mybatis配置模板
在Editor下的File and Code Templates,點選+好。即可建立模板。
例如建立maper模板
name=mybatis-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="">
<select id="" resultType="">
</select>
</mapper>
同理,mybatis主配置檔案。
name=mybatis-config
<?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>
<settings>
<!--設定mybatis輸出日誌-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--環境配置: 資料庫的連線資訊
default:必須和某個environment的id值一樣。
告訴mybatis使用哪個資料庫的連線資訊。也就是訪問哪個資料庫
-->
<environments default="mydev8">
<environment id="mydev8">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/springdb?useSSL=false&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="3306"/>
</dataSource>
</environment>
<environment id="mydev5">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3308/springdb"/>
<property name="username" value="root"/>
<property name="password" value="3308"/>
</dataSource>
</environment>
</environments>
<!-- sql mapper(sql對映檔案)的位置-->
<mappers>
<mapper resource="comipingfan/dao/StudentDao.xml"/>
</mappers>
</configuration>
實現Dao介面的方式訪問資料庫
分析StudentDao介面
我們通過mybatis連線資料庫並進行增刪拆改,可以發現和介面中的方法並沒有直接的關係。正常操作應該是呼叫dao介面中的方法來完成操作的。其實在開發中都是service層來進行訪問資料庫的,而service層去實現dao層的介面的。因此接下來通過實現介面的形式訪問資料庫。
dao層
StudentDao.java
package comipingfan.dao;
import comipingfan.domain.Student;
import java.util.List;
//介面,操作Student表
public interface StudentDao {
//查詢Student表的所有的資料
public List<Student> selectStudents();
//插入方法
public int insertStudent(Student stu);
}
StudentDao.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="comipingfan.dao.StudentDao">
<select id="selectStudents" resultType="comipingfan.domain.Student">
select id,name,email,age from student order by id
</select>
<insert id="insertStudnet">
insert into student values(#{id},#{name},#{email},#{age})
</insert>
</mapper>
dao層下的impl包
StudnetDaoImpl.java
public class StudnetDaoImpl implements StudentDao {
@Override
public List<Student> selectStudents() {
SqlSession sqlSession= MyBatisutiles.getSqlSession();
String sqlId="com.pingfan.dao.StudentDao"+"."+"selectStudents";
List<Student> list = sqlSession.selectList(sqlId);
sqlSession.close();
return list;
}
@Override
public int insertStudent(Student stu) {
SqlSession sqlSession= MyBatisutiles.getSqlSession();
String sqlId="com.pingfan.dao.StudentDao"+"."+"insertStudnet";
int res=sqlSession.insert(sqlId,stu);
sqlSession.commit();
sqlSession.close();
return res;
}
}
測試:
@Test
public void testSelectStudents(){
StudentDao dao=new StudnetDaoImpl();
List<Student> students = dao.selectStudents();
for(Student stu:students){
System.out.println(stu);
}
}
利用動態代理實現Dao介面
上述的實現類StudnetDaoImpl主要作用就是拿到sqlSession物件和sqlId(主要是id和全限定名稱的拼接)。然後去執行相應的方法。而動態代理剛好可以幫我們拿到全限定名稱和id。
分析:
使用mybatis的動態代理機制,使用SqlSession.getMapper(dao介面.class)取這個dao介面的物件
getMapper能獲取dao介面對於的實現類物件
然後就能執行相應的方法
dao層(只需要StudnetDao介面和Studnet.xml)
public interface StudentDao {
List<Student> selectStudents();
int insertStudent(Student stu);
}
<?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.item.dao.StudentDao">
<select id="selectStudents" resultType="com.item.domain.Student">
select * from student order by id
</select>
<insert id="insertStudent" >
insert into student values(#{id},#{name},#{email},#{age})
</insert>
</mapper>
測試:(當然獲取SqlSession的工具類和mybatis的主配置檔案上面已給出)
SqlSession sqlSession= MyBatisutiles.getSqlSession();
StudentDao dao=sqlSession.getMapper(StudentDao.class);
//呼叫dao的方法,執行資料庫的操作
List<Student>students=dao.selectStudents();
for (Student stu:students){
System.out.println(stu);
}
SqlSession sqlSession=MyBatisutiles.getSqlSession();
StudentDao dao=sqlSession.getMapper(StudentDao.class);
Student stu=new Student();
stu.setId(1006);
stu.setName("xxx");
stu.setEmail("[email protected]");
stu.setAge(20);
int res = dao.insertStudent(stu);
sqlSession.commit();
System.out.println("res="+res);
深入理解引數
parameterType
介面中方法引數的型別, 型別的完全限定名或別名。這個屬性是可選的,因為 MyBatis 可以推斷出具體傳入語句的引數,預設值為未設定(unset)。介面中方法的引數從 java 程式碼傳入到 mapper 檔案的 sql 語句。
例如:
<delete id="deleteStudent" parameterType="int">
delete from student where id=#{studentId}
</delete>
等同於
<delete id="deleteStudent" parameterType="java.lang.Integer">
delete from student where id=#{studentId}
</delete>
當然不寫也是可以的。會自動推斷。
MyBatis 傳遞引數
一個簡單引數
Dao 介面中方法的引數只有一個簡單型別(java 基本型別和 String),佔位符 #{ 任意字元 },和方 法的引數名無關
介面方法: Student selectById(int id);
mapper 檔案:
<select id="selectById" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where id=#{studentId}
</select>
#{studentId} , studentId 是自定義的變數名稱,和方法引數名無關。
測試:
Student student = studentDao.selectById(1005);
System.out.println("查詢 id 是 1005 的學生:"+student);
多個引數-使用@Param
當 Dao 介面方法多個引數,需要通過名稱使用引數。在方法形參前面加入@Param(“自定義引數名”), mapper 檔案使用#{自定義引數名}。
例如定義
List selectStudent( @Param(“personName”) String name ) { … }
mapper 檔案
select * from student where name = #{ personName}
介面方法:
List selectMultiParam(@Param("personName") String name, @Param("personAge") int age);
mapper 檔案:
<select id="selectMultiParam" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name=#{personName} or age=#{personAge}
</select>
測試
List<Student> stuList = studentDao.selectMultiParam("李力",20);
stuList.forEach( stu -> System.out.println(stu));
多個引數-使用物件
使用 java 物件傳遞引數, java 的屬性值就是 sql 需要的引數值。 每一個屬性就是一個引數。
語法格式: #{ property,javaType=java 中資料型別名,jdbcType=資料型別名稱 } javaType, jdbcType 的型別 MyBatis 可以檢測出來,一般不需要設定。常用格式 #{ property }
綜上:使用常用格式即可。
建立儲存引數值的物件 QueryParam
package com.bjpowernode.vo;
public class QueryParam {
private String queryName;
private int queryAge;
//set ,get 方法
}
介面方法:
List<Student> selectMultiObject(QueryParam queryParam);
mapper 檔案:
<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name=#{queryName} or age
=#{queryAge}
</select>
或
<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student
where name=#{queryName,javaType=string,jdbcType=VARCHAR}
or age =#{queryAge,javaType=int,jdbcType=INTEGER}
</select>
測試:
QueryParam qp = new QueryParam();
qp.setQueryName("李力");
qp.setQueryAge(20);
List<Student> stuList = studentDao.selectMultiObject(qp);
stuList.forEach( stu -> System.out.println(stu));
問題彙總
resource下的mybatis.xml檔案找不到
當你用IDEA右側maven執行clear和compile命令時,如果不加
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
則會找不到mybatis.xml檔案。但是如果你一開始就沒有target目錄,而是通過main函式執行或者run-test,則mybatix.xml會被放到target目錄下。所以建議還是放下(一個是編譯src/main下一個是resource下)。
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>