一、學習內(nèi)容
- SSM(Spring、SpringMVC、MyBatis)
- Apache Shiro
- SpringBoot
二、數(shù)據(jù)庫事務(wù)
-
事務(wù):若將 N 個數(shù)據(jù)庫操作(CRUD)放到同一個事務(wù)中,則這 N 個數(shù)據(jù)庫操作最終要么全都生效,要么全都不生效
-
?? 開啟事務(wù)【START TRANSACTION】
-
?? 回滾事務(wù):若事務(wù)中的某個數(shù)據(jù)庫操作失敗,其他所有數(shù)據(jù)庫操作都需要回滾(恢復到開啟事務(wù)之前的狀態(tài))【ROLLBACK】
-
?? 提交事務(wù):如果事務(wù)中的所有數(shù)據(jù)庫操作都成功被執(zhí)行,就提交事務(wù)(讓這些操作正式生效)【COMMIT】
三、JDBC 的事務(wù)管理
?? JDBC 中用 Connection 對象來管理事務(wù)
?? connection.setAutoCommit(false)
:開啟事務(wù)(自己管理事務(wù))
?? connection.rollback()
:回滾事務(wù) (若執(zhí)行某條語句的過程中出現(xiàn)異常,之前執(zhí)行過的語句恢復到最初狀態(tài))
?? connection.commit()
:
提交事務(wù) (若所有語句都被正常執(zhí)行,沒有出現(xiàn)異常,會正常提交事務(wù),讓所有語句的修改都生效)
四、事務(wù)的四大特性
① 原子性(Atomicity)
?? 事務(wù)作為一個整體被執(zhí)行,包含在其中的對數(shù)據(jù)庫的操作要么全部被執(zhí)行,要么都不執(zhí)行
② 一致性(Consistency)
?? 事務(wù)應(yīng)確保數(shù)據(jù)庫的狀態(tài)從一個一致狀態(tài)轉(zhuǎn)變?yōu)榱硪粋€一致狀態(tài)。一致狀態(tài)的含義是:數(shù)據(jù)庫中的數(shù)據(jù)應(yīng)滿足完整性約束
③ 隔離性(Isolation)
?? 多個事務(wù)并發(fā)執(zhí)行時,一個事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行
④ 持久性(Durability)
?? 已被提交的事務(wù)對數(shù)據(jù)庫的修改應(yīng)該永久保存在數(shù)據(jù)庫中
五、MyBatis
- MyBatis 是一款優(yōu)秀的持久層(Dao層)的框架
中文官網(wǎng):https://mybatis.org/mybatis-3/zh/index.html
六、MyBatis 核心配置文件和基本使用
(1) ?? 添加依賴(MyBatis 依賴喝 MySQL 數(shù)據(jù)庫連接驅(qū)動包)
<dependencies>
<!-- 引入 JDBC, Java 連接 MySQL 的驅(qū)動包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<!-- MyBatis 依賴 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
</dependencies>
(2) ?? 創(chuàng)建 MyBatis 的核心配置文件(文件名:mybatis-config.xml
)
XML 配置文件中包含了對 MyBatis 系統(tǒng)的核心設(shè)置,包括獲取數(shù)據(jù)庫連接實例的數(shù)據(jù)源(DataSource)以及決定事務(wù)作用域和控制方式的事務(wù)管理器(TransactionManager)
官方核心配置文件:https://mybatis.org/mybatis-3/zh/getting-started.html
<?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>
<!-- 環(huán)境 -->
<!-- default:使用哪個環(huán)境下的數(shù)據(jù)庫配置 -->
<environments default="development">
<!-- 開發(fā)環(huán)境(開發(fā)調(diào)試階段)-->
<environment id="development">
<!-- 采用 JDBC 的事務(wù)管理方法 -->
<transactionManager type="JDBC"/>
<!-- POOLED:采取 MyBatis 的連接池管理數(shù)據(jù)庫連接 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/study_mb"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
<!-- 生產(chǎn)環(huán)境(發(fā)布階段)-->
<environment id="production">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test_mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
</configuration>
?? transactionManager 的 type 為 JDBC【采用 JDBC 方式來管理事務(wù)】
?? dataSource 的 type 為 POOLED【采用連接池的方式管理數(shù)據(jù)庫連接】
CREATE TABLE `student` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(22) NOT NULL,
`money` bigint(20) NOT NULL,
`create_time` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4
public class Student {
private Long id;
private String name;
private Long money;
private String createTime;
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getMoney() {
return money;
}
public void setMoney(Long money) {
this.money = money;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
", createTime='" + createTime + '\'' +
'}';
}
}
七、查詢 student 表
(1) 實體映射文件 mapper
-
實體映射文件
① 用于做表和實體類之間的映射
② 在 mapper 文件夾下創(chuàng)建 -
把映射文件的路徑配置到核心配置文件(mybatis-config.xml)中
① 在核心配置文件中可通過<mappers></mappers>
標簽配置多個實體映射文件路徑
② 在<mappers></mappers>
標簽中可配置多個<mapper/>
標簽(每個<mapper />
標簽對應(yīng)一個實體映射文件)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="student">
<!-- id="list":后面可通過 list 對應(yīng)該條 SQL 語句并執(zhí)行該條 SQL 語句 -->
<!-- resultType: 該條 SQL 語句的結(jié)果對應(yīng)的 Java Bean -->
<!-- 會自動將結(jié)果集映射為 List<Student> -->
<select id="list" resultType="com.pojo.po.Student">
SELECT * FROM student
</select>
</mapper>
(2) 讀取核心配置文件, 拿到 SqlSession
public class TestStudent {
@Test
public void testSelect() throws Exception {
// 讀取 MyBatis 的核心配置文件
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
// 創(chuàng)建工廠構(gòu)建器
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 創(chuàng)建工廠
SqlSessionFactory factory = builder.build(reader);
// 創(chuàng)建 SqlSession
SqlSession sqlSession = factory.openSession();
// 通過 sqlSession 執(zhí)行 SQL 語句
// 參數(shù)是 <mapper> 標簽中的 namespace 和 <select> 標簽的 id
List<Student> studentList = sqlSession.selectList("student.list");
for (Student student : studentList) {
System.out.println("student = " + student);
}
// 關(guān)閉 session
sqlSession.close();
}
}
八、字段和屬性名映射
(1) mapUnderscoreToCamelCase
是否開啟駝峰命名自動映射,即從經(jīng)典數(shù)據(jù)庫列名 A_COLUMN 映射到經(jīng)典 Java 屬性名 aColumn
若不配置,數(shù)據(jù)庫表中以下劃線方式命名的字段查詢出的結(jié)果是 null
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>
?? 假如不設(shè)置駝峰下劃線自動映射,也可在實體映射文件中通過 <resultMap> 進行 Java Bean 和表字段的映射
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="student">
<!-- id="list":后面可通過 list 對應(yīng)該條 SQL 語句并執(zhí)行該條 SQL 語句 -->
<!-- resultType: 該條 SQL 語句的結(jié)果對應(yīng)的 Java Bean -->
<!-- 會自動將結(jié)果集映射為 List<Student> -->
<!-- <select id="list" resultType="com.pojo.po.Student">-->
<!-- SELECT * FROM student-->
<!-- </select>-->
<resultMap id="resultMapStudent" type="com.pojo.po.Student">
<!-- 屬性名和字段名完全一樣可不進行設(shè)置 -->
<id property="id" column="id"/>
<!-- <result property="id" column="id"/>-->
<!-- <result property="name" column="name"/>-->
<!-- <result property="money" column="money"/>-->
<result property="createTime" column="create_time"/>
</resultMap>
<select id="list" resultMap="resultMapStudent">
SELECT * FROM student
</select>
</mapper>
(2) 完整的 settings 標簽配置
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="safeResultHandlerEnabled" value="true"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
<setting name="defaultScriptingLanguage" value="org.apache.ibatis.scripting.xmltags.XMLLanguageDriver"/>
<setting name="defaultEnumTypeHandler" value="org.apache.ibatis.type.EnumTypeHandler"/>
<setting name="callSettersOnNulls" value="false"/>
<setting name="returnInstanceForEmptyRow" value="false"/>
<setting name="logPrefix" value="exampleLogPreFix_"/>
<setting name="logImpl" value="SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING"/>
<setting name="proxyFactory" value="CGLIB | JAVASSIST"/>
<setting name="vfsImpl" value="org.mybatis.example.YourselfVfsImpl"/>
<setting name="useActualParamName" value="true"/>
<setting name="configurationFactory" value="org.mybatis.example.ConfigurationFactory"/>
</settings>
九、SqlSessionFactory 細節(jié)
?? SqlSessionFactory 一旦被創(chuàng)建就應(yīng)該在應(yīng)用的運行期間一直存在,沒有任何理由丟棄它或重新創(chuàng)建另一個實例。 使用 SqlSessionFactory 的最佳實踐是在應(yīng)用運行期間不要重復創(chuàng)建多次,多次重建 SqlSessionFactory 被視為一種代碼“壞習慣”。因此 SqlSessionFactory 的最佳作用域是應(yīng)用作用域。 有很多方法可以做到,最簡單的就是使用單例模式或者靜態(tài)單例模式。
/**
* @author Larry Meadors
*/
public class SqlSessionManager implements SqlSessionFactory, SqlSession {
private final SqlSessionFactory sqlSessionFactory;
// 構(gòu)造方法私有化
private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {
}
public static SqlSessionManager newInstance(Reader reader) {
return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, null, null));
}
public static SqlSessionManager newInstance(Reader reader, String environment) {
return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, environment, null));
}
public static SqlSessionManager newInstance(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionManager(sqlSessionFactory);
}
}
public class MyBatisUtil {
// 保留一份即可
private static SqlSessionFactory sqlSessionFactory;
static {
try (Reader reader = Resources.getResourceAsReader("mybatis-config.xml")) {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 返回一個 SqlSession
*
* @param autoCommit 是否自動提交事務(wù)
*/
public static SqlSession openSession(boolean autoCommit) {
return sqlSessionFactory.openSession(autoCommit);
}
}
靜態(tài)代碼塊只會在類加載時被執(zhí)行一次,與對象無關(guān)。靜態(tài)代碼塊使用 static 修飾,與對象無關(guān)
十、參數(shù)傳遞
(1) 參數(shù)占位符
${}
:直接文本替換#{}
:預編譯傳值,可防止 SQL 注入
(2) 代碼測試
?? 傳遞單個參數(shù)
/**
* 傳遞單個參數(shù)
*/
@Test
public void testParam0() {
try (SqlSession sqlSession = MyBatisUtil.openSession(true)) {
Student studentById = sqlSession.selectOne("student.getById", 3);
System.out.println("testParam0 studentById = " + studentById);
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="student">
<select id="getById" resultType="com.pojo.po.Student">
<!-- #{}: 參數(shù)占位符 -->
SELECT * FROM student WHERE id = #{id}
</select>
</mapper>
?? 多個參數(shù)的傳遞
public class TestStudent {
/**
* 傳遞多個參數(shù)
*/
@Test
public void testParam1() {
try (SqlSession sqlSession = MyBatisUtil.openSession(true)) {
Map<String, String> paramMap = new HashMap<>();
paramMap.put("id", "3");
paramMap.put("money", "7009900");
List<Student> studentList = sqlSession.selectList("student.listByIdAndMoney", paramMap);
for (Student student : studentList) {
System.out.println("testParam1 student = " + student);
}
}
}
@Test
public void testParam2() {
try (SqlSession sqlSession = MyBatisUtil.openSession(true)) {
Student studentParams = new Student();
studentParams.setId(3L);
studentParams.setMoney(7009900L);
List<Student> studentList = sqlSession.selectList("student.listByIdAndMoney", studentParams);
for (Student student : studentList) {
System.out.println("testParam2 student = " + student);
}
}
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="student">
<select id="listByIdAndMoney" resultType="com.pojo.po.Student">
<!-- <【表示小于符號】 -->
SELECT * FROM student WHERE id < #{id} OR money >= #{money}
</select>
</mapper>
模糊查詢
public class TestStudent {
@Test
public void testParam3() {
try (SqlSession sqlSession = MyBatisUtil.openSession(true)) {
List<Student> studentList = sqlSession.selectList("student.getByName", "%張%");
for (Student student : studentList) {
System.out.println("testParam3 student = " + student);
}
}
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="student">
<select id="getByName" resultType="com.pojo.po.Student">
SELECT * FROM student WHERE name LIKE #{name}
</select>
</mapper>
假如中文模糊查詢沒有結(jié)果,需要配置數(shù)據(jù)庫的字符編碼
十一、日志打印
?? (1) 在核心配置文件中配置打印日志
<?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>
<!-- 打印日志信息 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
</configuration>
?? (2) 第三方日志打印庫
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>test</scope>
</dependency>
使用該第三方庫的話需要取消核心配置文件中的配置
十二、多表查詢
(1) 準備工作
--- 公司表
CREATE TABLE `company` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`intro` varchar(1000) DEFAULT NULL,
`create_time` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4
--- 工作經(jīng)驗表
CREATE TABLE `experience` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job` varchar(20) NOT NULL,
`intro` varchar(1000) DEFAULT NULL,
`company_id` int(11) NOT NULL,
`create_time` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
KEY `company_id` (`company_id`),
CONSTRAINT `experience_ibfk_1` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4
public class Company {
private Long id;
private String name;
private String intro;
private String createTime;
@Override
public String toString() {
return "Company{" +
"id=" + id +
", name='" + name + '\'' +
", intro='" + intro + '\'' +
'}';
}
}
public class Experience {
private Long id;
private String job;
private String intro;
private Company company;
private String createTime;
@Override
public String toString() {
return "Experience{" +
"id=" + id +
", job='" + job + '\'' +
", intro='" + intro + '\'' +
", company=" + company +
", createTime='" + createTime + '\'' +
'}';
}
}
(2) 多表查詢
查詢 experience 表,同時查詢出對應(yīng)的 company 信息
寫法1:
文章來源:http://www.zghlxwxcb.cn/news/detail-474484.html
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="experience">
<resultMap id="rmExp" type="com.pojo.po.Experience">
<!-- c_id 會和 Experience 的 company 屬性的 id 屬性進行映射 -->
<!-- c_name 會和 Experience 的 company 屬性的 name 屬性進行映射 -->
<result property="company.id" column="c_id"/>
<result property="company.name" column="c_name"/>
</resultMap>
<select id="list" resultMap="rmExp">
SELECT
e.*,
c.id c_id,
c.NAME c_name
FROM
experience e
JOIN company c ON c.id = e.company_id
</select>
</mapper>
寫法2
文章來源地址http://www.zghlxwxcb.cn/news/detail-474484.html
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="experience">
<select id="list" resultType="com.pojo.po.Experience">
SELECT
e.*,
c.id `company.id`,
c.NAME `company.name`,
c.intro `company.intro`
FROM
experience e
JOIN company c ON c.id = e.company_id
</select>
</mapper>
到了這里,關(guān)于【MyBatis】1、MyBatis 核心配置文件、多表查詢、實體映射文件 ......的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!