【MyBatis】(一)MyBatis基礎知識點(概念,Mybatis框架的優缺點,簡單的Mybatis框架使用Demo,基本的增刪改查操作案例)
一、概念
簡單的說:一款封裝了資料庫JDBC操作的ORM框架技術.(Apache(ibatis) --> Google(Mybatis))
MyBatis 是一款優秀的持久層框架,它支援定製化 SQL、儲存過程以及高階對映。MyBatis 避免了幾乎所有的 JDBC 程式碼和手動設定引數以及獲取結果集。MyBatis 可以使用簡單的 XML 或註解來配置和對映原生資訊,將介面和 Java 的 POJOs(Plain Old Java Objects,普通的 Java物件)對映成資料庫中的記錄。
ORM:Object Relation Mapping物件關係對映
ORM設計思想:將資料庫中的一張表與java實體類關聯起來,表中每一行記錄對映成實體類物件,可以通過對映關係將實體類中資料儲存到資料庫中,也可以將資料庫中一行記錄對映成一個java實體類物件。ORM是一種設計思想,Hibernate和Mybatis都是實現了這種思想的框架。其中ORM對映分為四級:第一級別為手動連線的SQLutils.第二級別為半自動化的MyBatis框架.第四級便是永續性框架Hibernate,這個在之前的部落格有詳解.這裡我們來詳細學習一下MyBatis框架操作實體類資料庫.
二、MyBatis框架的優缺點
優點:
1.基於SQL語句的框架,可以實現對SQL語句的調優。
2.將SQL語句單獨編寫在xml配置檔案中,方便統一管理和維護,降低程式之間的耦合度。
3.提供xml標籤,支援動態SQL語句編寫。
4.提供xml對映標籤,支援表與表之間的關聯查詢。
缺點:
1.需要自己編寫SQL語句,對開發人員的能力有要求。
2.資料庫移植能力較差。
3.不支援表與表之間級聯增刪改。
三、MyBatis的使用步驟
1.建立資料庫
#建立資料庫 create database mybatis default character set utf8; #使用資料庫 use mybatis; #建立表 create table user( id int primary key auto_increment, username varchar(20), password varchar(20), age int, gender char(1)); #插入資料 INSERT INTO user (username,password,age,gender) values ("張三","123",20,'男'),("李四","123",21,'男'),("王五","123",23,'男'),("趙六","123",24,'男');
2.建立專案,匯入核心Jar包
mybatis-3.4.5.jar 是mybatis核心API
mysql.jar 是資料庫操作Jar
3.編寫Mybatis主配置檔案:SqlMapConfig.xml
主要編寫資料庫連線引數資訊和其他配置.
<configuration>
<!-- 引用Properties配置檔案的 -->
<properties resource="jdbc.properties">
</properties>
<!-- 全域性系統設定:使用log4j框架列印Sql語句 -->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING" />
<!-- 開啟二級快取..延遲載入之類的. -->
</settings>
<!-- 給實體類型別起別名,方便在sql對映檔案中使用 -->
<typeAliases>
<typeAlias type="com.hekaikai666.bean.User" alias="user" />
<typeAlias type="com.hekaikai666.bean.Emp" alias="emp" />
</typeAliases>
<!-- 資源 -->
<environments default="environment">
<environment id="environment">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url"
value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<!-- 關聯SQL對映檔案 -->
<mappers>
<mapper resource="com/hekaikai666/dao/i/UserMapper.xml" />
</mappers>
</configuration>
4.根據表編寫實體類.建議:實體類中屬性名和表中欄位名保持一致.(如果不一致請參考User1)
package com.hekaikai666.bean;
import java.io.Serializable;
/**
*
* @author hekaikai666
* @time 2018年9月17日上午11:24:57
**/
public class User implements Serializable {
private int id;
private String username;
private String password;
private int age;
private String gender;
// 此處省略空參構造方法,不包含id的全參構造方法,全參構造方法,get set方法和toString方法
}
package com.hekaikai666.bean;
import java.io.Serializable;
/**
*
* @author hekaikai666
* @time 2018年9月17日下午4:49:40
**/
public class User1 implements Serializable {
private int u_id;
private String u_username;
private String u_password;
private int u_age;
private String u_gender;
// 此處省略 空參構造方法,不包含id的全參構造方法,全參構造方法,以及get set方法和toString方法
}
5.編寫SQL對映檔案,主要編寫SQL語句,讓主配置檔案關聯載入對映檔案
<!-- SQL對映檔案:多個SQL對映檔案之間,namespace不能相同 -->
<mapper namespace="user">
<!-- 作用:提取多個SQL定義中相同的SQL片段 -->
<sql id="selectAll">SELECT * FROM user</sql>
<!-- 根據id查詢一個User物件
id:代表當前這個SQL定義 #{id}:代表佔位符,大括號中的id和屬性名一致
parameterType:傳給佔位符的引數型別
resultType:SQL語句執行完成後的返回結果
include:對相同Sql語句片段的提取 -->
<!-- 執行查詢物件的兩種方式哦 -->
<select id="findUserById" parameterType="int" resultType="user">SELECT
* FROM user WHERE id=#{id}</select>
<select id="findUserById" parameterType="int" resultType="user">
<include refid="selectAll" />
WHERE id=#{id}
</select>
<!-- 查詢所有User資料 返回list集合時,resultType寫集合元素型別,mybatis會自動將其封裝為集合 -->
<!-- <select id="findAll" resultType="user">SELECT * FROM user</select> -->
<select id="findAll" resultType="user">
<include refid="selectAll" />
</select>
<!-- 插入一條資料 -->
<insert id="saveUser" parameterType="user">INSERT INTO user
(username,password,age,gender) VALUES
(#{username},#{password},#{age},#{gender})
</insert>
<!-- 刪除一條資料 -->
<delete id="deleteUserById" parameterType="int">DELETE FROM user WHERE id=#{id}</delete>
<!-- 根據id修改一行記錄 -->
<update id="updateUser" parameterType="user">UPDATE user SET username=#{username},password=#{password},age=#{age},gender=#{gender} WHERE id=#{id}</update>
<!-- 根據名字進行模糊查詢 -->
<select id="findThem" parameterType="java.lang.String" resultType="user"><include refid="selectAll"/>WHERE username like #{username}</select>
<!-- 根據賬號密碼查詢一個賬戶:user物件傳入 -->
<select id="findOneByUAP" parameterType="user" resultType="user"><include refid="selectAll"/>WHERE username=#{username} and password=#{password}</select>
<!-- 根據賬號密碼查詢一個賬戶:map物件傳入 -->
<select id="findOneByUAP2" parameterType="map" resultType="user"><include refid="selectAll"/>WHERE username=#{username} and password=#{password}</select>
<!-- 根據id只查詢賬號和密碼 -->
<select id="findOneById" parameterType="int" resultType="java.lang.String">SELECT username,password FROM user WHERE id=#{id}</select>
<!-- 查詢所有使用者的賬號和密碼 -->
<select id="findAllUAP" resultType="java.lang.String">SELECT username,password FROM user</select>
<!-- 分頁查詢所有使用者的資訊 -->
<select id="getUserByLimit" parameterType="map" resultType="user">SELECT * FROM user LIMIT #{page},#{pageSize}</select>
<!-- 查詢表中所有資料並封裝成user1型別物件集合 -->
<!-- 方案一:給列起別名,別名的名字和實體類屬性名相同 -->
<select id="findAllUser1" resultType="com.hekaikai666.bean.User1">
SELECT
id u_id,
username u_username,
password u_password,
age u_age,
gender u_gender
FROM user
</select>
<!-- 方案二:藉助resultType標籤做實體類中屬性名和表中欄位之間對映關係 -->
<!-- type:表中每一行記錄封裝成什麼型別物件 id:當前resultMap對映結果id -->
<resultMap type="com.hekaikai666.bean.User1" id="user1Bean">
<!-- 主鍵對映:property:實體類中屬性名稱 column:表中欄位名稱 -->
<id property="u_id" column="id"/>
<!-- 非主鍵對映: -->
<result property="u_username" column="username"/>
<result property="u_password" column="password"/>
<result property="u_age" column="age"/>
<result property="u_gender" column="gender"/>
</resultMap>
<!-- 查詢所有資料封裝成User1物件型別集合 -->
<select id="findUser1" resultMap="user1Bean">SELECT * FROM user</select>
</mapper>
6.通過mybatis中的API獲取到SqlSession物件.
獲取sessionFactory物件可以封裝為util方法,無需重複寫
// 獲取sessionFactory物件
public static SqlSessionFactory getFactory() {
// 獲取SqlSessionFactoryBuilder物件
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 載入mybatis配置檔案
// 通過類載入器物件來載入檔案獲取一個流
String resource = "SqlMapConfig.xml";
InputStream is = TestUser.class.getClassLoader().getResourceAsStream(resource);
// 使用session工廠物件載入檔案(每個應用程式能夠對應一個SqlSessionFactory)
// 可以用於構建你SqlSession物件和充當二級快取
SqlSessionFactory factory = builder.build(is);
return factory;
}
User物件和User1物件的十三種基本增刪改查操作. * 查詢單個User物件 * 查詢所有User物件並風格到List集合中 * 給輸入庫中新增一個User物件 * 根據id刪除一個User物件 * 根據id修改一個物件 * 根據名字進行模糊查詢 * 根據賬號密碼查詢一個賬戶 * 根據id只查詢賬號和密碼 * 查詢所有使用者的賬號和密碼 * 當實體類中屬性名和表中欄位名不一致時查詢 * 根據賬號和密碼查詢一個使用者的 資訊進行登入 如果能查到 成功 如果查不到 失敗 模擬JdbcSQL注入 * mybatis分頁查詢 * 根據名字查詢一個User物件 * 根據賬號和密碼進行查詢 * 傳入資料表名進行查詢
package com.hekaikai666.Test;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Before;
import org.junit.Test;
import com.hekaikai666.bean.User;
import com.hekaikai666.bean.User1;
import com.hekaikai666.util.MyBatisUtil;
import jdk.nashorn.internal.ir.ForNode;
/**
*
* @author hekaikai666
* @time 2018年9月17日上午11:42:16
**/
public class TestUser {
SqlSessionFactory factory;
@Before
public void init() {
factory = MyBatisUtil.getFactory();
}
/**
* 查詢單個User物件
*
* @throws FileNotFoundException
*/
@Test
public void test1() {
// 使用session工廠開啟session
SqlSession session = factory.openSession();
// 通過session物件執行對映檔案中的SQL語句
String statement = "findUserById";
// 第一個引數 Sql定義的id 第二個引數 佔位符的引數值
// 1.查詢SQL語句
User user = session.selectOne(statement, 1);
System.out.println(user);
session.close();
}
/**
* 查詢所有User物件並風格到List集合中
*/
@Test
public void test2() {
SqlSession session = factory.openSession();
// 如果多個對映檔案有相同的sql定義id可以使用namespace.id名來
List<User> users = session.selectList("user.findAll");
for (User user : users) {
System.out.println(user);
}
session.close();
}
/**
* 給輸入庫中新增一個User物件
*/
@Test
public void test3() {
SqlSession session = factory.openSession();
User user = new User("宋豪", "123456", 80, "男");
int rows = session.insert("saveUser", user);
// 提交事務
session.commit();
System.out.println("成功插入資料的行數:" + rows);
// 關閉物件
session.close();
}
/**
* 根據id刪除一個User物件
*/
@Test
public void test4() {
SqlSession session = factory.openSession();
int rows = session.delete("user.deleteUserById", 6);
System.out.println("刪除記錄行數:" + rows);
session.commit();
session.close();
}
/**
* 根據id修改一個物件
*/
@Test
public void test5() {
SqlSession session = factory.openSession();
// 先根據id獲取一個user物件
User user = session.selectOne("findUserById", 3);
user.setUsername("哈哈哈");
user.setPassword("呵呵呵");
user.setAge(18);
user.setGender("女");
int rows = session.update("user.updateUser", user);
System.out.println("修改記錄行數:" + rows);
session.commit();
session.close();
}
/**
* 根據名字進行模糊查詢
*/
@Test
public void test6() {
SqlSession session = factory.openSession();
List<User> users = session.selectList("findThem", "%張%");
for (User user : users) {
System.out.println(user);
}
session.close();
}
/**
* 根據賬號密碼查詢一個賬戶
*/
@Test
public void test7() {
SqlSession session = factory.openSession();
// 傳入一個User物件
User user = new User("張三", "123", 0, "");
List<User> u = session.selectList("findOneByUAP", user);
System.out.println(u);
session.close();
// 傳入一個map集合
Map<String, String> map = new HashMap<String, String>();
map.put("username", "張三");
map.put("password", "123");
User user1 = session.selectOne("findOneByUAP2", map);
System.out.println(user1);
session.close();
}
/**
* 根據id只查詢賬號和密碼
*/
@Test
public void test8() {
SqlSession session = factory.openSession();
List<Map<String, String>> user = session.selectList("findOneById", 1);
for (Map<String, String> map : user) {
System.out.println(map);
}
session.close();
}
/**
* 查詢所有使用者的賬號和密碼
*/
@Test
public void test9() {
SqlSession session = factory.openSession();
List<Map<String, String>> users = session.selectList("findAllUAP");
for (Map<String, String> map : users) {
System.out.println(map);
}
session.close();
}
/*
* 當實體類中屬性名和表中欄位名不一致時查詢
*/
@Test
public void test01() {
SqlSession session = factory.openSession();
List<User1> user1s = session.selectList("findUser1");
for (User1 user1 : user1s) {
System.out.println(user1);
}
}
/**
* 根據賬號和密碼查詢一個使用者的 資訊進行登入 如果能查到 成功 如果查不到 失敗 模擬JdbcSQL注入
*
* @throws ClassNotFoundException
* @throws SQLException
*/
@Test
public void testJDBC() throws ClassNotFoundException, SQLException {
String username="宋豪";
String password="1234' or '1=1";
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8",
"root", "123456");
String sql = "SELECT * FROM user WHERE username='"+username+"' and password='"+password+"';";
Statement stmt = con.createStatement();
PreparedStatement pstmt = con.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
// ResultSet rs = stmt.executeQuery(sql);
if (rs.next()) {
System.out.println("登陸成功");
} else {
System.out.println("登陸失敗");
}
}
/**
* mybatis分頁查詢
*/
@Test
public void test10() {
SqlSession session = factory.openSession();
HashMap<String, Object> maps = new LinkedHashMap<String,Object>();
maps.put("page", 2);
maps.put("pageSize", 3);
List<User> lists = session.selectList("user.getUserByLimit", maps);
for (User user : lists) {
System.out.println(user);
}
}
/**
* 根據名字查詢一個User物件
*/
@Test
public void test11() {
SqlSession session = factory.openSession();
User user = session.selectOne("u.findUserByName","'張三'");
System.out.println(user);
session.close();
}
/**
* 根據賬號和密碼進行查詢
*/
@Test
public void test12() {
SqlSession session = factory.openSession();
HashMap<String, Object> map = new HashMap<String,Object>();
map.put("username", "'張三'");
map.put("password", "'12345' or '1=1'");
User user = session.selectOne("u.findUserByNameAndPsw",map);
System.out.println(user);
session.close();
}
/**
* 傳入資料表名進行查詢
*/
@Test
public void test13() {
SqlSession session = factory.openSession();
String table = "user";
User user = session.selectOne("u.findAll",table);
System.out.println(user);
session.close();
}
}