MyBatis筆記(一)
阿新 • • 發佈:2021-07-28
一、MyBatis是什麼?
MyBatis是一個優秀的基於java的持久層框架,它內部封裝了JDBC,使開發者只需要關注SQL語句本身,而不需要花費精力去處理載入驅動、建立連線、建立Statement等繁雜的過程。
二、原來的JDBC有哪些缺點?
JDBC程式示例:
public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { //載入資料庫驅動 Class.forName("com.mysql.jdbc.Driver"); //通過驅動管理類獲取資料庫連結 connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root"); //定義 sql 語句 ?表示佔位符 String sql = "select * from user where username = ?"; //獲取預處理 statement preparedStatement = connection.prepareStatement(sql); //設定引數,第一個引數為 sql 語句中引數的序號(從 1 開始),第二個引數為設定的引數值 preparedStatement.setString(1, "王五"); //向資料庫發出 sql 執行查詢,查詢出結果集 resultSet = preparedStatement.executeQuery(); //遍歷查詢結果集 while(resultSet.next()){ System.out.println(resultSet.getString("id")+" "+resultSet.getString("username")); } } catch (Exception e) { e.printStackTrace(); }finally{ //釋放資源 if(resultSet!=null){ try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if(preparedStatement!=null){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(connection!=null){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
JDBC存在的問題:
- 資料庫連結建立、釋放頻繁造成系統資源浪費從而影響系統性能,如果使用資料庫連結池可解決此問題。
- SQL語句在程式碼中硬編碼,造成程式碼不易維護,實際應用SQL變化的可能較大,SQL變動需要改變Java程式碼。
- 使用PreparedStatement向佔有位符號傳引數存在硬編碼,因為SQL語句的where條件不一定,可能多也可能少,修改SQL還要修改程式碼,系統不易維護。
- 對結果集解析存在硬編碼(查詢列名),SQL變化導致解析程式碼變化,系統不易維護,如果能將資料庫記錄封裝成pojo物件解析比較方便。
三、MyBatis環境搭建步驟
- 建立Maven工程
GroupId: com.itheima ArtifactId: mybatis01
- 匯入依賴座標
pom.xml
<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.16</version> </dependency> </dependencies>
- 編寫實體類
com/itheima/domain/User.java
package com.itheima.domain;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
}
- 編寫持久層介面
com/itheima/dao/UserDao.java
package com.itheima.dao;
import com.itheima.domain.QueryVo;
import com.itheima.domain.User;
import java.util.List;
public interface UserDao {
/**
* 查詢所有使用者
* @return
*/
List<User> findAll();
/**
* 根據id查詢使用者
* @param id
* @return
*/
User findById(Integer id);
/**
* 儲存使用者
* @param user
* @return
*/
int saveUser(User user);
/**
* 更新使用者
* @param user
* @return
*/
int updateUser(User user);
/**
* 刪除使用者
* @param id
* @return
*/
int deleteUser(Integer id);
/**
* 根據使用者名稱模糊查詢
* @param username
* @return
*/
List<User> findByName(String username);
/**
* 查詢使用者數量
* @return
*/
Integer findCount();
/**
* 根據QueryVo中的條件查詢使用者
* @param vo
* @return
*/
List<User> findByVo(QueryVo vo);
}
- 編寫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>
<typeAliases>
<package name="com.itheima.domain"/>
</typeAliases>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ee50"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.itheima.dao"/>
</mappers>
</configuration>
- 編寫對映配置檔案
com/itheima/dao/UserDao.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.itheima.dao.UserDao">
<select id="findAll" resultType="User">
select * from user
</select>
<select id="findById" resultType="User" parameterType="int">
select * from user where id = #{id}
</select>
<insert id="saveUser" parameterType="User">
<selectKey keyColumn="id" keyProperty="id" resultType="int">
select last_insert_id();
</selectKey>
insert into user(username, birthday, sex, address)
values(#{username}, #{birthday}, #{sex}, #{address})
</insert>
<update id="updateUser" parameterType="User">
update user set username=#{username}, birthday=#{birthday}, sex=#{sex},
address=#{address} where id=#{id}
</update>
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>
<select id="findByName" parameterType="string" resultType="User">
select * from user where username like #{username}
</select>
<select id="findCount" resultType="int">
select count(*) from user
</select>
<select id="findByVo" resultType="User" parameterType="QueryVo">
select * from user where username like #{user.username}
</select>
</mapper>
- 編寫測試類
com/itheima/test/MyBatisTests.java
package com.itheima.test;
import com.itheima.dao.UserDao;
import com.itheima.domain.QueryVo;
import com.itheima.domain.User;
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.After;
import org.junit.Before;
import org.junit.Test;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class MyBatisTests {
private InputStream in ;
private SqlSessionFactory factory;
private SqlSession session;
private UserDao userDao;
// 一些共有操作
@Before
public void init() throws IOException{
in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(in);
session = factory.openSession();
userDao = session.getMapper(UserDao.class);
}
@After
public void destroy() throws Exception {
session.commit();
session.close();
in.close();
}
@Test
public void testSelectAll() {
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
@Test
public void testSelectById() {
User user = userDao.findById(1);
System.out.println(user);
}
@Test
public void testSaveUser() {
User user = new User();
user.setUsername("xxx");
user.setBirthday(new Date());
user.setSex("男");
user.setAddress("china");
int i = userDao.saveUser(user);
System.out.println(i);
System.out.println(user.getId());
}
@Test
public void testUpdateUser() {
User user = userDao.findById(2);
user.setAddress("JiangSu");
int i = userDao.updateUser(user);
System.out.println(i);
}
@Test
public void testDeleteUser() {
int i = userDao.deleteUser(4);
System.out.println(i);
}
@Test
public void testFindByName() {
List<User> userList = userDao.findByName("%g%");
for (User user : userList) {
System.out.println(user);
}
}
@Test
public void testFindCount() {
int i = userDao.findCount();
System.out.println(i);
}
@Test
public void testFindByVo() {
QueryVo vo = new QueryVo();
User user = new User();
user.setUsername("%w%");
vo.setUser(user);
List<User> userList = userDao.findByVo(vo);
for (User resUser : userList) {
System.out.println(resUser);
}
}
}
四、補充說明
UserDao.java
和UserDao.xml
兩個檔案分別在java包和resources包下,其路徑必須保持一致且名字相同。UserDao.xml
中的mapper的幾個屬性:namespace為對應的持久層介面UserDao.java
的全限定類名,id為UserDao.java
中相應的方法名,用於新增User後自動返回id屬性值。 UserDao.xml
中的resultType和parameterType:若是基本型別和String型別,可以直接寫類名;若是實體類,如User,則需要寫全限定類名。可以在SqlMapConfig.xml
中註冊別名:
<typeAliases>
<package name="com.itheima.domain"/>
</typeAliases>
註冊過後,該報下的實體類都可以用別名,及類名,首字母不區分大小寫。
4. 需要在SqlMapConfig.xml
中配置對映器(mappers),一種比較方便的方法是設定整個包:
<mappers>
<package name="com.itheima.dao"/>
</mappers>
要求mapper介面和mapper對映檔案包路徑一致且名字相同。
5. MyBatis也可以不編寫mapper對映檔案,可以將SQL語句寫在mapper介面中相應方法的上面,例如:
/**
* 查詢所有使用者
* @return
*/
@Select("select * from user")
List<User> findAll();
這種方式少些一個XML檔案,看著比較簡潔。但是一般工程不採用該方式,個人猜想是因為SQL和Java方法之間產生了耦合,修改維護不方便。