
CREATE TABLE `tbl_employee` ( `id` int(11) NOT NULL AUTO_INCREMENT, `last_name` varchar(255) DEFAULT NULL, `gender` varchar(1) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

建立與之對應的bean文件
package com.atguigu.mybatis.bean; public class Employee { private Integer id; private String lastName; private String email; private String gender; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } @Override public String toString() { return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + "]"; } }
編寫的時候最好保證bean對象的屬性值和表名的字段一一對應,這里 private String lastName;和表字段last_name不對應我們看后面如何處理了這是一個關鍵點
導入所需的jar包

mybatis用到了log4j我們需要在src目錄下建立一個log4j.xml

我們創建一個source folder文件夾,必須是這個類型的文件夾,該類型下的文件夾和src在同一目錄
source folder文件夾是一種特別的文件夾,如果你用面向對象的思想去看待這個source folder,那么他是folder的一個子集,作為子集,肯定是有folder的所有功能,而且還有自己特別的功能,他的特別之處,就是在source folder下面的java文件都會被編譯,編譯后的文件會被放在我們設置的某個文件夾下面(一般我們設置成WEB-INF/classes)

log4m.xml文件夾的內容如下
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> <param name="Encoding" value="UTF-8" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" /> </layout> </appender> <logger name="java.sql"> <level value="debug" /> </logger> <logger name="org.apache.ibatis"> <level value="info" /> </logger> <root> <level value="debug" /> <appender-ref ref="STDOUT" /> </root> </log4j:configuration>
mybatis-config.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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <!-- 將我們寫好的sql映射文件(EmployeeMapper.xml)一定要注冊到全局配置文件(mybatis-config.xml)中 --> <mappers> <mapper resource="EmployeeMapper.xml" /> </mappers> </configuration>
EmployeeMapper.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.atguigu.mybatis.dao.EmployeeMapper"> <!-- namespace:名稱空間;指定為接口的全類名 id:唯一標識 resultType:返回值類型 #{id}:從傳遞過來的參數中取出id值 public Employee getEmpById(Integer id); --> <select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee"> select id,last_name lastName,email,gender from tbl_employee where id = #{id} </select> </mapper>
上面因為bean的屬性和數據庫表名不一樣,如何解決了在編寫mysql的時候可以使用別名的方式來解決select id,last_name lastName,email,gender from tbl_employee where id = #{id} 這里起了一個別名,last_name lastName 第一個是bean中的屬性值,第二個是數據庫的列名
否則會出現問題
EmployeeMapper
package com.atguigu.mybatis.dao;
import com.atguigu.mybatis.bean.Employee;
public interface EmployeeMapper {
public Employee getEmpById(Integer id);
}
MyBatisTest.java
package com.atguigu.mybatis.test; import java.io.IOException; import java.io.InputStream; 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.Test; import com.atguigu.mybatis.bean.Employee; import com.atguigu.mybatis.dao.EmployeeMapper; /** * 1、接口式編程 * 原生: Dao ====> DaoImpl * mybatis: Mapper ====> xxMapper.xml * * 2、SqlSession代表和數據庫的一次會話;用完必須關閉; * 3、SqlSession和connection一樣她都是非線程安全。每次使用都應該去獲取新的對象。 * 4、mapper接口沒有實現類,但是mybatis會為這個接口生成一個代理對象。 * (將接口和xml進行綁定) * EmployeeMapper empMapper = sqlSession.getMapper(EmployeeMapper.class); * 5、兩個重要的配置文件: * mybatis的全局配置文件:包含數據庫連接池信息,事務管理器信息等...系統運行環境信息 * sql映射文件:保存了每一個sql語句的映射信息: * 將sql抽取出來。 * * * @author lfy * */ public class MyBatisTest { public SqlSessionFactory getSqlSessionFactory() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); return new SqlSessionFactoryBuilder().build(inputStream); } /** * 1、根據xml配置文件(全局配置文件)創建一個SqlSessionFactory對象 有數據源一些運行環境信息 * 2、sql映射文件;配置了每一個sql,以及sql的封裝規則等。 * 3、將sql映射文件注冊在全局配置文件中 * 4、寫代碼: * 1)、根據全局配置文件得到SqlSessionFactory; * 2)、使用sqlSession工廠,獲取到sqlSession對象使用他來執行增刪改查 * 一個sqlSession就是代表和數據庫的一次會話,用完關閉 * 3)、使用sql的唯一標志來告訴MyBatis執行哪個sql。sql都是保存在sql映射文件中的。 * * @throws IOException */ @Test public void test() throws IOException { // 2、獲取sqlSession實例,能直接執行已經映射的sql語句 // sql的唯一標識:statement Unique identifier matching the statement to use. // 執行sql要用的參數:parameter A parameter object to pass to the statement. SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try { Employee employee = openSession.selectOne( "com.atguigu.mybatis.dao.EmployeeMapper.getEmpById", 1); System.out.println(employee); } finally { openSession.close(); } } @Test public void test01() throws IOException { // 1、獲取sqlSessionFactory對象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、獲取sqlSession對象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、獲取接口的實現類對象 //會為接口自動的創建一個代理對象,代理對象去執行增刪改查方法 EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Employee employee = mapper.getEmpById(1); System.out.println(mapper.getClass()); System.out.println(employee); } finally { openSession.close(); } } }
4.尚硅谷_MyBatis_接口式編程.avi
注意幾點:
<?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.atguigu.mybatis.dao.EmployeeMapper"> <!-- namespace:名稱空間;指定為接口的全類名 id:唯一標識 resultType:返回值類型 #{id}:從傳遞過來的參數中取出id值 public Employee getEmpById(Integer id); --> <select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee"> select id,last_name lastName,email,gender from tbl_employee where id = #{id} </select> </mapper>
第一點:namespace="com.atguigu.mybatis.dao.EmployeeMapper">對應的是需要訪問的接口的全類名
第二點:<select id="getEmpById"中id的值和接口下的 public Employee getEmpById(Integer id);名字一一對應
在程序中我們就可以采用接口編程了
package com.atguigu.mybatis.test; import java.io.IOException; import java.io.InputStream; 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.Test; import com.atguigu.mybatis.bean.Employee; import com.atguigu.mybatis.dao.EmployeeMapper; /** * 1、接口式編程 * 原生: Dao ====> DaoImpl * mybatis: Mapper ====> xxMapper.xml * * 2、SqlSession代表和數據庫的一次會話;用完必須關閉; * 3、SqlSession和connection一樣她都是非線程安全。每次使用都應該去獲取新的對象。 * 4、mapper接口沒有實現類,但是mybatis會為這個接口生成一個代理對象。 * (將接口和xml進行綁定) * EmployeeMapper empMapper = sqlSession.getMapper(EmployeeMapper.class); * 5、兩個重要的配置文件: * mybatis的全局配置文件:包含數據庫連接池信息,事務管理器信息等...系統運行環境信息 * sql映射文件:保存了每一個sql語句的映射信息: * 將sql抽取出來。 * * * @author lfy * */ public class MyBatisTest { public SqlSessionFactory getSqlSessionFactory() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); return new SqlSessionFactoryBuilder().build(inputStream); } /** * 1、根據xml配置文件(全局配置文件)創建一個SqlSessionFactory對象 有數據源一些運行環境信息 * 2、sql映射文件;配置了每一個sql,以及sql的封裝規則等。 * 3、將sql映射文件注冊在全局配置文件中 * 4、寫代碼: * 1)、根據全局配置文件得到SqlSessionFactory; * 2)、使用sqlSession工廠,獲取到sqlSession對象使用他來執行增刪改查 * 一個sqlSession就是代表和數據庫的一次會話,用完關閉 * 3)、使用sql的唯一標志來告訴MyBatis執行哪個sql。sql都是保存在sql映射文件中的。 * * @throws IOException */ @Test public void test() throws IOException { // 2、獲取sqlSession實例,能直接執行已經映射的sql語句 // sql的唯一標識:statement Unique identifier matching the statement to use. // 執行sql要用的參數:parameter A parameter object to pass to the statement. SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try { Employee employee = openSession.selectOne( "com.atguigu.mybatis.dao.EmployeeMapper.getEmpById", 1); System.out.println(employee); } finally { openSession.close(); } } @Test public void test01() throws IOException { // 1、獲取sqlSessionFactory對象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、獲取sqlSession對象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、獲取接口的實現類對象 //會為接口自動的創建一個代理對象,代理對象去執行增刪改查方法 EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Employee employee = mapper.getEmpById(1); System.out.println(mapper.getClass()); System.out.println(employee); } finally { openSession.close(); } } }
上面不在使用session的方法去增刪改查,而使用getMapper將sql與接口對象進行綁定,獲得接口操作的實現類,這樣就可以使用接口的實現對象進行增刪改查的操作了,接口的實現類是mybatis自己創建出來的,該對象是一個代理對象去實現增刪改查操作。
5.尚硅谷_MyBatis_小結(1).avi
SqlSession代表和數據庫的一次會話;用完必須關閉,每一次增刪改查都是一次會話
SqlSession和connection一樣她都是非線程安全。每次使用都應該去獲取新的對象。所以不能定義成一個類的成員變量,各個方法進行共享,而應該每個方法使用都應用區獲得新的對象
* 5、兩個重要的配置文件:
* mybatis的全局配置文件:包含數據庫連接池信息,事務管理器信息等...系統運行環境信息
* sql映射文件:保存了每一個sql語句的映射信息:
* 將sql抽取出來
6.尚硅谷_MyBatis_全局配置文件_引入dtd約束.avi

我們如何在mybatis的全局配置文件中如何能夠引入源文件了
在上面的mybatis-config.xml中我們引入了mybatis的約束文件"http://mybatis.org/dtd/mybatis-3-config.dtd">
EmployeeMapper.xml中引入了"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
,我們如何因為該約束文件的源碼了,第一找到mybatis的jar包將該jar包解壓
找到下面的兩個文件

在eclipse中做下面操作


key type必須是URI
key就是對於的http://mybatis.org/dtd/mybatis-3-mapper.dtd
location就是解壓對於的文件
引入之后在xml中就能夠實現代碼的自動提示了
7.尚硅谷_MyBatis_全局配置文件_properties_引入外部配置文件.avi

上面中因為conf是一個source folder文件夾,所以配置文件EmployeeMapper.xml和實體類Employee在同樣的包名com.atguigu.mybatis.bean下,並且xml文件以實體類的類命名
dbconfig.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis jdbc.username=root jdbc.password=123456 orcl.driver=oracle.jdbc.OracleDriver orcl.url=jdbc:oracle:thin:@localhost:1521:orcl orcl.username=scott orcl.password=123456
<!--
1、mybatis可以使用properties來引入外部properties配置文件的內容;
resource:引入類路徑下的資源
url:引入網絡路徑或者磁盤路徑下的資源
-->
<properties resource="dbconfig.properties"></properties>
mybatis-config.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> <!-- 1、mybatis可以使用properties來引入外部properties配置文件的內容; resource:引入類路徑下的資源 url:引入網絡路徑或者磁盤路徑下的資源 --> <properties resource="dbconfig.properties"></properties> <!-- 2、settings包含很多重要的設置項 setting:用來設置每一個設置項 name:設置項名 value:設置項取值 --> <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> <!-- 3、typeAliases:別名處理器:可以為我們的java類型起別名 別名不區分大小寫 --> <typeAliases> <!-- 1、typeAlias:為某個java類型起別名 type:指定要起別名的類型全類名;默認別名就是類名小寫;employee alias:指定新的別名 --> <!-- <typeAlias type="com.atguigu.mybatis.bean.Employee" alias="emp"/> --> <!-- 2、package:為某個包下的所有類批量起別名 name:指定包名(為當前包以及下面所有的后代包的每一個類都起一個默認別名(類名小寫),) --> <package name="com.atguigu.mybatis.bean"/> <!-- 3、批量起別名的情況下,使用@Alias注解為某個類型指定新的別名 --> </typeAliases> <!-- 4、environments:環境們,mybatis可以配置多種環境 ,default指定使用某種環境。可以達到快速切換環境。 environment:配置一個具體的環境信息;必須有兩個標簽;id代表當前環境的唯一標識 transactionManager:事務管理器; type:事務管理器的類型;JDBC(JdbcTransactionFactory)|MANAGED(ManagedTransactionFactory) 自定義事務管理器:實現TransactionFactory接口.type指定為全類名 dataSource:數據源; type:數據源類型;UNPOOLED(UnpooledDataSourceFactory) |POOLED(PooledDataSourceFactory) |JNDI(JndiDataSourceFactory) 自定義數據源:實現DataSourceFactory接口,type是全類名 --> <environments default="dev_mysql"> <environment id="dev_mysql"> <transactionManager type="JDBC"></transactionManager> <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> <environment id="dev_oracle"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${orcl.driver}" /> <property name="url" value="${orcl.url}" /> <property name="username" value="${orcl.username}" /> <property name="password" value="${orcl.password}" /> </dataSource> </environment> </environments> <!-- 5、databaseIdProvider:支持多數據庫廠商的; type="DB_VENDOR":VendorDatabaseIdProvider 作用就是得到數據庫廠商的標識(驅動getDatabaseProductName()),mybatis就能根據數據庫廠商標識來執行不同的sql; MySQL,Oracle,SQL Server,xxxx --> <databaseIdProvider type="DB_VENDOR"> <!-- 為不同的數據庫廠商起別名 --> <property name="MySQL" value="mysql"/> <property name="Oracle" value="oracle"/> <property name="SQL Server" value="sqlserver"/> </databaseIdProvider> <!-- 將我們寫好的sql映射文件(EmployeeMapper.xml)一定要注冊到全局配置文件(mybatis-config.xml)中 --> <!-- 6、mappers:將sql映射注冊到全局配置中 --> <mappers> <!-- mapper:注冊一個sql映射 注冊配置文件 resource:引用類路徑下的sql映射文件 mybatis/mapper/EmployeeMapper.xml url:引用網路路徑或者磁盤路徑下的sql映射文件 file:///var/mappers/AuthorMapper.xml 注冊接口 class:引用(注冊)接口, 1、有sql映射文件,映射文件名必須和接口同名,並且放在與接口同一目錄下; 2、沒有sql映射文件,所有的sql都是利用注解寫在接口上; 推薦: 比較重要的,復雜的Dao接口我們來寫sql映射文件 不重要,簡單的Dao接口為了開發快速可以使用注解; --> <!-- <mapper resource="mybatis/mapper/EmployeeMapper.xml"/> --> <!-- <mapper class="com.atguigu.mybatis.dao.EmployeeMapperAnnotation"/> --> <!-- 批量注冊: --> <package name="com.atguigu.mybatis.dao"/> </mappers> </configuration>
注意點:使用properties 標簽導入外面的dbconfig.properties文件
<setting name="mapUnderscoreToCamelCase" value="true"/>設置向映射下划線映射成駝峰命名
作用例如數據庫的字段是last_name,實體類的字段是private String lastName;,在mybatis執行查詢
<select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee">
select * from tbl_employee where id = #{id}
</select>
會把數據庫的last_name的字段轉化成lastName達到一一對應,但是在寫代碼的時候最好數據庫的字段和實體類屬性一一對應。
typeAliases起別名
resultType="com.atguigu.mybatis.bean.Employee"
我們經常使用到com.atguigu.mybatis.bean.Employee,我們可以為它起一個簡單的別名
<!-- 3、typeAliases:別名處理器:可以為我們的java類型起別名
別名不區分大小寫
-->
<typeAliases>
<!-- 1、typeAlias:為某個java類型起別名
type:指定要起別名的類型全類名;默認別名就是類名小寫;employee
alias:指定新的別名
-->
<!-- <typeAlias type="com.atguigu.mybatis.bean.Employee" alias="emp"/> -->
<!-- 2、package:為某個包下的所有類批量起別名
name:指定包名(為當前包以及下面所有的后代包的每一個類都起一個默認別名(類名小寫),)
-->
<package name="com.atguigu.mybatis.bean"/>
<!-- 3、批量起別名的情況下,使用@Alias注解為某個類型指定新的別名 -->
</typeAliases>
package com.atguigu.mybatis.bean; import org.apache.ibatis.type.Alias; @Alias("emp") public class Employee { private Integer id; private String lastName; private String email; private String gender; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } @Override public String toString() { return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + "]"; } }
mybatis為java類型起了下面的別名

_typeHandlers



<!--
4、environments:環境們,mybatis可以配置多種環境 ,default指定使用某種環境。可以達到快速切換環境。
environment:配置一個具體的環境信息;必須有兩個標簽;id代表當前環境的唯一標識
transactionManager:事務管理器;
type:事務管理器的類型;JDBC(JdbcTransactionFactory)|MANAGED(ManagedTransactionFactory)
自定義事務管理器:實現TransactionFactory接口.type指定為全類名
dataSource:數據源;
type:數據源類型;UNPOOLED(UnpooledDataSourceFactory)
|POOLED(PooledDataSourceFactory)
|JNDI(JndiDataSourceFactory)
自定義數據源:實現DataSourceFactory接口,type是全類名
-->
environment標簽必須具有transactionManager和dataSource兩個屬性文件,兩個文件都必須有。
databaseIdProvider_多數據庫支持,可以執行不同數據庫執行不同的sql語句,mybatis依據不同的配置來執行不同的sql語句
在mybatis-config.xml全局配置文件中
<databaseIdProvider type="DB_VENDOR"> <!-- 為不同的數據庫廠商起別名 --> <property name="MySQL" value="mysql"/> <property name="Oracle" value="oracle"/> <property name="SQL Server" value="sqlserver"/> </databaseIdProvider>
在EmployeeMapper.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.atguigu.mybatis.dao.EmployeeMapper"> <!-- namespace:名稱空間;指定為接口的全類名 id:唯一標識 resultType:返回值類型 #{id}:從傳遞過來的參數中取出id值 public Employee getEmpById(Integer id); --> <select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where id = #{id} </select> <select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee" databaseId="mysql"> select * from tbl_employee where id = #{id} </select> <select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee" databaseId="oracle"> select EMPLOYEE_ID id,LAST_NAME lastName,EMAIL email from employees where EMPLOYEE_ID=#{id} </select> </mapper>
通過 databaseId來執行不同的sql語句
_mappers_sql

2、沒有sql映射文件,所有的sql都是利用注解寫在接口上;
EmployeeMapperAnnotation
package com.atguigu.mybatis.dao; import org.apache.ibatis.annotations.Select; import com.atguigu.mybatis.bean.Employee; public interface EmployeeMapperAnnotation { @Select("select * from tbl_employee where id=#{id}") public Employee getEmpById(Integer id); }
然后再全局配置文件夾中進行注解

基於注解的使用
MyBatisTest
package com.atguigu.mybatis.test; import java.io.IOException; import java.io.InputStream; 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.Test; import com.atguigu.mybatis.bean.Employee; import com.atguigu.mybatis.dao.EmployeeMapper; import com.atguigu.mybatis.dao.EmployeeMapperAnnotation; /** * 1、接口式編程 * 原生: Dao ====> DaoImpl * mybatis: Mapper ====> xxMapper.xml * * 2、SqlSession代表和數據庫的一次會話;用完必須關閉; * 3、SqlSession和connection一樣她都是非線程安全。每次使用都應該去獲取新的對象。 * 4、mapper接口沒有實現類,但是mybatis會為這個接口生成一個代理對象。 * (將接口和xml進行綁定) * EmployeeMapper empMapper = sqlSession.getMapper(EmployeeMapper.class); * 5、兩個重要的配置文件: * mybatis的全局配置文件:包含數據庫連接池信息,事務管理器信息等...系統運行環境信息 * sql映射文件:保存了每一個sql語句的映射信息: * 將sql抽取出來。 * * * @author lfy * */ public class MyBatisTest { public SqlSessionFactory getSqlSessionFactory() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); return new SqlSessionFactoryBuilder().build(inputStream); } /** * 1、根據xml配置文件(全局配置文件)創建一個SqlSessionFactory對象 有數據源一些運行環境信息 * 2、sql映射文件;配置了每一個sql,以及sql的封裝規則等。 * 3、將sql映射文件注冊在全局配置文件中 * 4、寫代碼: * 1)、根據全局配置文件得到SqlSessionFactory; * 2)、使用sqlSession工廠,獲取到sqlSession對象使用他來執行增刪改查 * 一個sqlSession就是代表和數據庫的一次會話,用完關閉 * 3)、使用sql的唯一標志來告訴MyBatis執行哪個sql。sql都是保存在sql映射文件中的。 * * @throws IOException */ @Test public void test() throws IOException { // 2、獲取sqlSession實例,能直接執行已經映射的sql語句 // sql的唯一標識:statement Unique identifier matching the statement to use. // 執行sql要用的參數:parameter A parameter object to pass to the statement. SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try { Employee employee = openSession.selectOne( "com.atguigu.mybatis.EmployeeMapper.selectEmp", 1); System.out.println(employee); } finally { openSession.close(); } } @Test public void test01() throws IOException { // 1、獲取sqlSessionFactory對象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、獲取sqlSession對象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、獲取接口的實現類對象 //會為接口自動的創建一個代理對象,代理對象去執行增刪改查方法 EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Employee employee = mapper.getEmpById(1); System.out.println(mapper.getClass()); System.out.println(employee); } finally { openSession.close(); } } @Test public void test02() throws IOException{ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try{ EmployeeMapperAnnotation mapper = openSession.getMapper(EmployeeMapperAnnotation.class); Employee empById = mapper.getEmpById(1); System.out.println(empById); }finally{ openSession.close(); } } }
比較最要的sql我們推薦使用xml方式,不重要的sql我們推薦注解方式
<!-- 批量注冊: -->
<package name="com.atguigu.mybatis.dao"/>
批量注冊的前提是存在xml文件,xml文件必須和bean文件在同一個保包下,並且滿足名字命名規則實體Employee對應的xml文件名是EmployeeMapper.xml這樣才滿足導入配置文件的規則

整個項目的工程代碼如下所示

EmployeeMapper接口
package com.atguigu.mybatis.dao; import java.util.List; import java.util.Map; import org.apache.ibatis.annotations.MapKey; import org.apache.ibatis.annotations.Param; import com.atguigu.mybatis.bean.Employee; public interface EmployeeMapper { //多條記錄封裝一個map:Map<Integer,Employee>:鍵是這條記錄的主鍵,值是記錄封裝后的javaBean //@MapKey:告訴mybatis封裝這個map的時候使用哪個屬性作為map的key @MapKey("lastName") public Map<String, Employee> getEmpByLastNameLikeReturnMap(String lastName); //返回一條記錄的map;key就是列名,值就是對應的值 public Map<String, Object> getEmpByIdReturnMap(Integer id); public List<Employee> getEmpsByLastNameLike(String lastName); public Employee getEmpByMap(Map<String, Object> map); public Employee getEmpByIdAndLastName(@Param("id")Integer id,@Param("lastName")String lastName); public Employee getEmpById(Integer id); public Long addEmp(Employee employee); public boolean updateEmp(Employee employee); public void deleteEmpById(Integer id); }
EmployeeMapper.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.atguigu.mybatis.dao.EmployeeMapper"> <!-- namespace:名稱空間;指定為接口的全類名 id:唯一標識 resultType:返回值類型 #{id}:從傳遞過來的參數中取出id值 public Employee getEmpById(Integer id); --> <!--public Map<Integer, Employee> getEmpByLastNameLikeReturnMap(String lastName); --> <select id="getEmpByLastNameLikeReturnMap" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where last_name like #{lastName} </select> <!--public Map<String, Object> getEmpByIdReturnMap(Integer id); --> <select id="getEmpByIdReturnMap" resultType="map"> select * from tbl_employee where id=#{id} </select> <!-- public List<Employee> getEmpsByLastNameLike(String lastName); --> <!--resultType:如果返回的是一個集合,要寫集合中元素的類型 --> <select id="getEmpsByLastNameLike" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where last_name like #{lastName} </select> <!-- public Employee getEmpByMap(Map<String, Object> map); --> <select id="getEmpByMap" resultType="com.atguigu.mybatis.bean.Employee"> select * from ${tableName} where id=${id} and last_name=#{lastName} </select> <!-- public Employee getEmpByIdAndLastName(Integer id,String lastName);--> <select id="getEmpByIdAndLastName" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where id = #{id} and last_name=#{lastName} </select> <select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where id = #{id} </select> <select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee" databaseId="mysql"> select * from tbl_employee where id = #{id} </select> <select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee" databaseId="oracle"> select EMPLOYEE_ID id,LAST_NAME lastName,EMAIL email from employees where EMPLOYEE_ID=#{id} </select> <!-- public void addEmp(Employee employee); --> <!-- parameterType:參數類型,可以省略, 獲取自增主鍵的值: mysql支持自增主鍵,自增主鍵值的獲取,mybatis也是利用statement.getGenreatedKeys(); useGeneratedKeys="true";使用自增主鍵獲取主鍵值策略 keyProperty;指定對應的主鍵屬性,也就是mybatis獲取到主鍵值以后,將這個值封裝給javaBean的哪個屬性 --> <insert id="addEmp" parameterType="com.atguigu.mybatis.bean.Employee" useGeneratedKeys="true" keyProperty="id" databaseId="mysql"> insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender}) </insert> <!-- 獲取非自增主鍵的值: Oracle不支持自增;Oracle使用序列來模擬自增; 每次插入的數據的主鍵是從序列中拿到的值;如何獲取到這個值; --> <insert id="addEmp" databaseId="oracle"> <!-- keyProperty:查出的主鍵值封裝給javaBean的哪個屬性 order="BEFORE":當前sql在插入sql之前運行 AFTER:當前sql在插入sql之后運行 resultType:查出的數據的返回值類型 BEFORE運行順序: 先運行selectKey查詢id的sql;查出id值封裝給javaBean的id屬性 在運行插入的sql;就可以取出id屬性對應的值 AFTER運行順序: 先運行插入的sql(從序列中取出新值作為id); 再運行selectKey查詢id的sql; --> <selectKey keyProperty="id" order="BEFORE" resultType="Integer"> <!-- 編寫查詢主鍵的sql語句 --> <!-- BEFORE--> select EMPLOYEES_SEQ.nextval from dual <!-- AFTER: select EMPLOYEES_SEQ.currval from dual --> </selectKey> <!-- 插入時的主鍵是從序列中拿到的 --> <!-- BEFORE:--> insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) values(#{id},#{lastName},#{email<!-- ,jdbcType=NULL -->}) <!-- AFTER: insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) values(employees_seq.nextval,#{lastName},#{email}) --> </insert> <!-- public void updateEmp(Employee employee); --> <update id="updateEmp"> update tbl_employee set last_name=#{lastName},email=#{email},gender=#{gender} where id=#{id} </update> <!-- public void deleteEmpById(Integer id); --> <delete id="deleteEmpById"> delete from tbl_employee where id=#{id} </delete> </mapper>
MyBatisTest.java
package com.atguigu.mybatis.test; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; 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.Test; import com.atguigu.mybatis.bean.Department; import com.atguigu.mybatis.bean.Employee; import com.atguigu.mybatis.dao.DepartmentMapper; import com.atguigu.mybatis.dao.EmployeeMapper; import com.atguigu.mybatis.dao.EmployeeMapperAnnotation; import com.atguigu.mybatis.dao.EmployeeMapperPlus; /** * 1、接口式編程 * 原生: Dao ====> DaoImpl * mybatis: Mapper ====> xxMapper.xml * * 2、SqlSession代表和數據庫的一次會話;用完必須關閉; * 3、SqlSession和connection一樣她都是非線程安全。每次使用都應該去獲取新的對象。 * 4、mapper接口沒有實現類,但是mybatis會為這個接口生成一個代理對象。 * (將接口和xml進行綁定) * EmployeeMapper empMapper = sqlSession.getMapper(EmployeeMapper.class); * 5、兩個重要的配置文件: * mybatis的全局配置文件:包含數據庫連接池信息,事務管理器信息等...系統運行環境信息 * sql映射文件:保存了每一個sql語句的映射信息: * 將sql抽取出來。 * * * @author lfy * */ public class MyBatisTest { public SqlSessionFactory getSqlSessionFactory() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); return new SqlSessionFactoryBuilder().build(inputStream); } /** * 1、根據xml配置文件(全局配置文件)創建一個SqlSessionFactory對象 有數據源一些運行環境信息 * 2、sql映射文件;配置了每一個sql,以及sql的封裝規則等。 * 3、將sql映射文件注冊在全局配置文件中 * 4、寫代碼: * 1)、根據全局配置文件得到SqlSessionFactory; * 2)、使用sqlSession工廠,獲取到sqlSession對象使用他來執行增刪改查 * 一個sqlSession就是代表和數據庫的一次會話,用完關閉 * 3)、使用sql的唯一標志來告訴MyBatis執行哪個sql。sql都是保存在sql映射文件中的。 * * @throws IOException */ @Test public void test() throws IOException { // 2、獲取sqlSession實例,能直接執行已經映射的sql語句 // sql的唯一標識:statement Unique identifier matching the statement to use. // 執行sql要用的參數:parameter A parameter object to pass to the statement. SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try { Employee employee = openSession.selectOne( "com.atguigu.mybatis.EmployeeMapper.selectEmp", 1); System.out.println(employee); } finally { openSession.close(); } } @Test public void test01() throws IOException { // 1、獲取sqlSessionFactory對象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、獲取sqlSession對象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、獲取接口的實現類對象 //會為接口自動的創建一個代理對象,代理對象去執行增刪改查方法 EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Employee employee = mapper.getEmpById(1); System.out.println(mapper.getClass()); System.out.println(employee); } finally { openSession.close(); } } @Test public void test02() throws IOException{ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try{ EmployeeMapperAnnotation mapper = openSession.getMapper(EmployeeMapperAnnotation.class); Employee empById = mapper.getEmpById(1); System.out.println(empById); }finally{ openSession.close(); } } /** * 測試增刪改 * 1、mybatis允許增刪改直接定義以下類型返回值 * Integer、Long、Boolean、void * 2、我們需要手動提交數據 * sqlSessionFactory.openSession();===》手動提交 * sqlSessionFactory.openSession(true);===》自動提交 * @throws IOException */ @Test public void test03() throws IOException{ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); //1、獲取到的SqlSession不會自動提交數據 SqlSession openSession = sqlSessionFactory.openSession(); try{ EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); //測試添加 Employee employee = new Employee(null, "jerry4",null, "1"); mapper.addEmp(employee); System.out.println(employee.getId()); //測試修改 //Employee employee = new Employee(1, "Tom", "jerry@atguigu.com", "0"); //boolean updateEmp = mapper.updateEmp(employee); //System.out.println(updateEmp); //測試刪除 //mapper.deleteEmpById(2); //2、手動提交數據 openSession.commit(); }finally{ openSession.close(); } } @Test public void test04() throws IOException{ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); //1、獲取到的SqlSession不會自動提交數據 SqlSession openSession = sqlSessionFactory.openSession(); try{ EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); //Employee employee = mapper.getEmpByIdAndLastName(1, "tom"); Map<String, Object> map = new HashMap<>(); map.put("id", 2); map.put("lastName", "Tom"); map.put("tableName", "tbl_employee"); Employee employee = mapper.getEmpByMap(map); System.out.println(employee); /*List<Employee> like = mapper.getEmpsByLastNameLike("%e%"); for (Employee employee : like) { System.out.println(employee); }*/ /*Map<String, Object> map = mapper.getEmpByIdReturnMap(1); System.out.println(map);*/ /*Map<String, Employee> map = mapper.getEmpByLastNameLikeReturnMap("%r%"); System.out.println(map);*/ }finally{ openSession.close(); } } @Test public void test05() throws IOException{ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try{ EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class); /*Employee empById = mapper.getEmpById(1); System.out.println(empById);*/ /*Employee empAndDept = mapper.getEmpAndDept(1); System.out.println(empAndDept); System.out.println(empAndDept.getDept());*/ Employee employee = mapper.getEmpByIdStep(3); System.out.println(employee); //System.out.println(employee.getDept()); System.out.println(employee.getDept()); }finally{ openSession.close(); } } @Test public void test06() throws IOException{ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try{ DepartmentMapper mapper = openSession.getMapper(DepartmentMapper.class); /*Department department = mapper.getDeptByIdPlus(1); System.out.println(department); System.out.println(department.getEmps());*/ Department deptByIdStep = mapper.getDeptByIdStep(1); System.out.println(deptByIdStep.getDepartmentName()); System.out.println(deptByIdStep.getEmps()); }finally{ openSession.close(); } } }
1、mybatis允許增刪改直接定義以下類型返回值
* Integer、Long、Boolean、void
public boolean updateEmp(Employee employee);
* sqlSessionFactory.openSession();===》手動提交
* sqlSessionFactory.openSession(true);===》自動提交
17.尚硅谷_MyBatis_映射文件_insert_獲取自增主鍵的值.avi
mybatis添加數據成功之后需要獲得自增主鍵的值,需要在EmployeeMapper.xml中進行配置
<!-- public void addEmp(Employee employee); --> <!-- parameterType:參數類型,可以省略, 獲取自增主鍵的值: mysql支持自增主鍵,自增主鍵值的獲取,mybatis也是利用statement.getGenreatedKeys(); useGeneratedKeys="true";使用自增主鍵獲取主鍵值策略 keyProperty;指定對應的主鍵屬性,也就是mybatis獲取到主鍵值以后,將這個值封裝給javaBean的哪個屬性 --> <insert id="addEmp" parameterType="com.atguigu.mybatis.bean.Employee" useGeneratedKeys="true" keyProperty="id" databaseId="mysql"> insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender}) </insert>
@Test public void test03() throws IOException{ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); //1、獲取到的SqlSession不會自動提交數據 SqlSession openSession = sqlSessionFactory.openSession(); try{ EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); //測試添加 Employee employee = new Employee(null, "jerry4",null, "1"); mapper.addEmp(employee); System.out.println(employee.getId()); //測試修改 //Employee employee = new Employee(1, "Tom", "jerry@atguigu.com", "0"); //boolean updateEmp = mapper.updateEmp(employee); //System.out.println(updateEmp); //測試刪除 //mapper.deleteEmpById(2); //2、手動提交數據 openSession.commit(); }finally{ openSession.close(); } }
我們在上面執行添加操作的時候,未添加之前員工的id為null,員工添加到數據庫成功之后,id就已經變成了自增主鍵的值了,需要上面的配置
21.尚硅谷_MyBatis_映射文件_參數處理_POJO&Map&TO.avi
單個參數:mybatis不會做特殊處理,
#{參數名/任意名}:取出參數值。
<delete id="deleteEmpById"> delete from tbl_employee where id=#{id} </delete>
上面代碼等價於
<delete id="deleteEmpById"> delete from tbl_employee where id=#{id535335} </delete>
任意名字都可以
對於多個參數
操作:
方法:public Employee getEmpByIdAndLastName(Integer id,String lastName);
取值:#{id},#{lastName}

這樣會報錯,存在異常


我們可以使用${param1}和${param1}獲得前兩個參數的值,使用param參數獲得值不便於閱讀,我們可以按照下面的方式進行指定

使用@Param參數指定名稱,就可以按照下面的方式使用了

【命名參數】:明確指定封裝參數時map的key;@Param("id")
多個參數會被封裝成 一個map,
key:使用@Param注解指定的值
value:參數值
#{指定的key}取出對應的參數值

第一個參數是可以使用${id}或者#{param1},第二個參數必須使用#param{2}來獲得

因為多個參數是封裝在map對象中,第一個參數只能使用#{param1},#{param2}就是封裝的Employee對象,獲得對應的屬性值就是#{param.lastName}
使用了@Param("e")指定。可以寫為#{e.lastName}

如果傳遞過來的參數本身就是一個map集合,直接使用map的key取值就可以了


傳入List集合只能使用小寫的list,Array只能是小寫的array
24.尚硅谷_MyBatis_映射文件_參數處理_#與$取值區別.avi

第一個參數使用${id}取值,第二個參數使用#{},$直接將值拼接在sql語句的后面會存在sql注入,#預編譯使用的是占位符

但是下面這種情況可以使用$
例如一個表示2016_salary 2017_salary這樣分表的,上面#{}取值只能放在sql的where字段后面。不能使用在表名上面取值,這個時候可以使用${}取值的方式

還有排序操作也不支持#的方式取值,直接將值拼接在sql語句上

25.尚硅谷_MyBatis_映射文件_參數處理_#取值時指定參數相關規則.avi

#{}獲得參數可以安裝上面的方式有更多的操作
jdbcType是要重點強調的,oracle數據庫使用mybatis插入到oracle數據庫不支持插入的字段為null

我們將員工的eamil設置為null,如果插入進oracle數據庫中就會報錯,默認請求下mybatis會將null字段映射為other字段,但是在oracle中不存在other字段,所以就會報錯
但是mysql數據庫支持不存在上面的問題,如何解決了,我們可以使用jdbcTYpe進行解決,在oracle環境下不能讓null字段映射為other字段,還應該是null字段


使用上面的語句就不會報錯了,但是只在當前的sql語句中有效,第二種可以全局進行配置

這樣就會解決上面的問題
26.尚硅谷_MyBatis_映射文件_select_返回List.avi
public List<Employee> getEmpsByLastNameLike(String lastName);
查詢返回一個List集合,如何處理了,resultType要寫list集合中元素的全類名
<!-- public List<Employee> getEmpsByLastNameLike(String lastName); --> <!--resultType:如果返回的是一個集合,要寫集合中元素的類型 --> <select id="getEmpsByLastNameLike" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where last_name like #{lastName} </select>
27.尚硅谷_MyBatis_映射文件_select_記錄封裝map.avi
如果通過id查詢,需要返回一個map對象如何處理了,map對象中key為列名id,key為對應的employee對象
//返回一條記錄的map;map對象中key就是列名,值就是對應的值
public Map<String, Object> getEmpByIdReturnMap(Integer id);
<!--public Map<String, Object> getEmpByIdReturnMap(Integer id); --> <select id="getEmpByIdReturnMap" resultType="map"> select * from tbl_employee where id=#{id} </select>
@Test public void test04() throws IOException{ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); //1、獲取到的SqlSession不會自動提交數據 SqlSession openSession = sqlSessionFactory.openSession(); try{ EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Map<String, Object> map = mapper.getEmpByIdReturnMap(1); System.out.println("map is:"+map); for(String s:map.keySet()){ System.out.println("key : "+s+" value : "+map.get(s)); } }finally{ openSession.close(); } }
運行打印的結果為
map is:{id=1, email=waawdaw, last_name=sdsfd, gender=1}
key : id value : 1
key : email value : waawdaw
key : last_name value : sdsfd
key : gender value : 1
上面是單條記錄的封裝,如果是多條記錄封裝了
/多條記錄封裝一個map:Map<Integer,Employee>:鍵是這條記錄的主鍵,值是記錄封裝后的javaBean //@MapKey:告訴mybatis封裝這個map的時候使用哪個屬性作為map的key @MapKey("lastName") public Map<String, Employee> getEmpByLastNameLikeReturnMap(String lastName);
<!--public Map<Integer, Employee> getEmpByLastNameLikeReturnMap(String lastName); --> <select id="getEmpByLastNameLikeReturnMap" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where last_name like #{lastName} </select>
resultType指的是集合中的元素,現在我們讓map中對應的元素value值是一個employ對象,並且讓其key為主鍵的名字,使用了@MapKey("lastName")告訴mybatis封裝map的時候使用lastName作為map的主鍵
我們來看下代碼
@Test public void test04() throws IOException{ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); //1、獲取到的SqlSession不會自動提交數據 SqlSession openSession = sqlSessionFactory.openSession(); try{ EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Map<String, Employee> map = mapper.getEmpByLastNameLikeReturnMap("%r%"); System.out.println(map); for(String s:map.keySet()){ System.out.println("key : "+s+" value : "+map.get(s)); } }finally{ openSession.close(); } }
數據庫中的值為

返回是一個map對象,map對象的key為上面使用了@Mapkey指定的值。value為最后一條記錄封裝的employee對象,我們來看下打印
{jerry4=Employee [id=7, lastName=jerry4, email=null, gender=1]}
key : jerry4 value : Employee [id=7, lastName=jerry4, email=null, gender=1]
28.尚硅谷_MyBatis_映射文件_select_resultMap_自定義結果映射規則.avi
上面中java bean對象的屬性名稱和表的列名不是一一對應的上面的lastName對應表的last_name上面使用了在sql查詢的時候啟別名的方式來解決,下面也可以采用resultMap的方式來解決
在說明resultmap之前我們先增加一個部門信息。每個員工對應一個部門。在查出員工的時候對象的將員工的部門信息查詢出來,查詢部門的時候將對應員工的信息頁查詢出來
Department
package com.atguigu.mybatis.bean; import java.util.List; public class Department { private Integer id; private String departmentName; private List<Employee> emps; public List<Employee> getEmps() { return emps; } public void setEmps(List<Employee> emps) { this.emps = emps; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getDepartmentName() { return departmentName; } public void setDepartmentName(String departmentName) { this.departmentName = departmentName; } @Override public String toString() { return "Department [id=" + id + ", departmentName=" + departmentName + "]"; } }
在數據庫中創建tbl_dept表
CREATE TABLE `tbl_dept` ( `id` int(11) NOT NULL AUTO_INCREMENT, `dept_name` varchar(222) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

同時需要修改員工表,讓員工表和部門表做管理,給員工表新建一個d_id的字段
CREATE TABLE `tbl_employee` ( `id` int(11) NOT NULL AUTO_INCREMENT, `last_name` varchar(255) DEFAULT NULL, `gender` varchar(1) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, `d_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `ss` (`d_id`), CONSTRAINT `ss` FOREIGN KEY (`d_id`) REFERENCES `tbl_dept` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;


員工類如下
package com.atguigu.mybatis.bean; import org.apache.ibatis.type.Alias; @Alias("emp") public class Employee { private Integer id; private String lastName; private String email; private String gender; private Department dept; public Employee() { super(); } public Employee(Integer id, String lastName, String email, String gender) { super(); this.id = id; this.lastName = lastName; this.email = email; this.gender = gender; } public Department getDept() { return dept; } public void setDept(Department dept) { this.dept = dept; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } @Override public String toString() { return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + ", dept=" + dept + "]"; } }
EmployeeMapperPlus.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.atguigu.mybatis.dao.EmployeeMapperPlus"> <!--自定義某個javaBean的封裝規則 type:自定義規則的Java類型 id:唯一id方便引用 --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MySimpleEmp"> <!--指定主鍵列的封裝規則 id定義主鍵會底層有優化; column:指定哪一列 property:指定對應的javaBean屬性 --> <id column="id" property="id"/> <!-- 定義普通列封裝規則 --> <result column="last_name" property="lastName"/> <!-- 其他不指定的列會自動封裝:我們只要寫resultMap就把全部的映射規則都寫上。 --> <result column="email" property="email"/> <result column="gender" property="gender"/> </resultMap> <!-- resultMap:自定義結果集映射規則; --> <!-- public Employee getEmpById(Integer id); --> <select id="getEmpById" resultMap="MySimpleEmp"> select * from tbl_employee where id=#{id} </select> <!-- 場景一: 查詢Employee的同時查詢員工對應的部門 Employee===Department 一個員工有與之對應的部門信息; id last_name gender d_id did dept_name (private Department dept;) --> <!-- 聯合查詢:級聯屬性封裝結果集 --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="gender" property="gender"/> <result column="did" property="dept.id"/> <result column="dept_name" property="dept.departmentName"/> </resultMap> <!-- 使用association定義關聯的單個對象的封裝規則; --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp2"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="gender" property="gender"/> <!-- association可以指定聯合的javaBean對象 property="dept":指定哪個屬性是聯合的對象 javaType:指定這個屬性對象的類型[不能省略] --> <association property="dept" javaType="com.atguigu.mybatis.bean.Department"> <id column="did" property="id"/> <result column="dept_name" property="departmentName"/> </association> </resultMap> <!-- public Employee getEmpAndDept(Integer id);--> <select id="getEmpAndDept" resultMap="MyDifEmp"> SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id, d.id did,d.dept_name dept_name FROM tbl_employee e,tbl_dept d WHERE e.d_id=d.id AND e.id=#{id} </select> <!-- 使用association進行分步查詢: 1、先按照員工id查詢員工信息 2、根據查詢員工信息中的d_id值去部門表查出部門信息 3、部門設置到員工中; --> <!-- id last_name email gender d_id --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpByStep"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> <!-- association定義關聯對象的封裝規則 select:表明當前屬性是調用select指定的方法查出的結果 column:指定將哪一列的值傳給這個方法 流程:使用select指定的方法(傳入column指定的這列參數的值)查出對象,並封裝給property指定的屬性 --> <association property="dept" select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById" column="d_id"> </association> </resultMap> <!-- public Employee getEmpByIdStep(Integer id);--> <select id="getEmpByIdStep" resultMap="MyEmpByStep"> select * from tbl_employee where id=#{id} <if test="_parameter!=null"> and 1=1 </if> </select> <!-- 可以使用延遲加載(懶加載);(按需加載) Employee==>Dept: 我們每次查詢Employee對象的時候,都將一起查詢出來。 部門信息在我們使用的時候再去查詢; 分段查詢的基礎之上加上兩個配置: --> <!-- ==================association============================ --> <!-- 場景二: 查詢部門的時候將部門對應的所有員工信息也查詢出來:注釋在DepartmentMapper.xml中 --> <!-- public List<Employee> getEmpsByDeptId(Integer deptId); --> <select id="getEmpsByDeptId" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where d_id=#{deptId} </select> <!-- =======================鑒別器============================ --> <!-- <discriminator javaType=""></discriminator> 鑒別器:mybatis可以使用discriminator判斷某列的值,然后根據某列的值改變封裝行為 封裝Employee: 如果查出的是女生:就把部門信息查詢出來,否則不查詢; 如果是男生,把last_name這一列的值賦值給email; --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpDis"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> <!-- column:指定判定的列名 javaType:列值對應的java類型 --> <discriminator javaType="string" column="gender"> <!--女生 resultType:指定封裝的結果類型;不能缺少。/resultMap--> <case value="0" resultType="com.atguigu.mybatis.bean.Employee"> <association property="dept" select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById" column="d_id"> </association> </case> <!--男生 ;如果是男生,把last_name這一列的值賦值給email; --> <case value="1" resultType="com.atguigu.mybatis.bean.Employee"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="last_name" property="email"/> <result column="gender" property="gender"/> </case> </discriminator> </resultMap> </mapper>
注意:resultType和resultMap只能二選一
<!-- resultMap:自定義結果集映射規則; --> <!-- public Employee getEmpById(Integer id); --> <select id="getEmpById" resultMap="MySimpleEmp"> select * from tbl_employee where id=#{id} </select>
我們在封裝下EmployeeMapperPlus.java對象
package com.atguigu.mybatis.dao; import java.util.List; import com.atguigu.mybatis.bean.Employee; public interface EmployeeMapperPlus { public Employee getEmpById(Integer id); public Employee getEmpAndDept(Integer id); public Employee getEmpByIdStep(Integer id); public List<Employee> getEmpsByDeptId(Integer deptId); }
我們來分析下查詢員工的時候同時將員工的部門信息查詢出來 public Employee getEmpAndDept(Integer id);
在EmployeeMapperPlus.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.atguigu.mybatis.dao.EmployeeMapperPlus"> <!--自定義某個javaBean的封裝規則 type:自定義規則的Java類型 id:唯一id方便引用 --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MySimpleEmp"> <!--指定主鍵列的封裝規則 id定義主鍵會底層有優化; column:指定哪一列 property:指定對應的javaBean屬性 --> <id column="id" property="id"/> <!-- 定義普通列封裝規則 --> <result column="last_name" property="lastName"/> <!-- 其他不指定的列會自動封裝:我們只要寫resultMap就把全部的映射規則都寫上。 --> <result column="email" property="email"/> <result column="gender" property="gender"/> </resultMap> <!-- resultMap:自定義結果集映射規則; --> <!-- public Employee getEmpById(Integer id); --> <select id="getEmpById" resultMap="MySimpleEmp"> select * from tbl_employee where id=#{id} </select> <!-- 場景一: 查詢Employee的同時查詢員工對應的部門 Employee===Department 一個員工有與之對應的部門信息; id last_name gender d_id did dept_name (private Department dept;) --> <!-- 聯合查詢:級聯屬性封裝結果集 --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="gender" property="gender"/> <result column="did" property="dept.id"/> <result column="dept_name" property="dept.departmentName"/> </resultMap> <!-- 使用association定義關聯的單個對象的封裝規則; --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp2"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="gender" property="gender"/> <!-- association可以指定聯合的javaBean對象 property="dept":指定哪個屬性是聯合的對象 javaType:指定這個屬性對象的類型[不能省略] --> <association property="dept" javaType="com.atguigu.mybatis.bean.Department"> <id column="did" property="id"/> <result column="dept_name" property="departmentName"/> </association> </resultMap> <!-- public Employee getEmpAndDept(Integer id);--> <select id="getEmpAndDept" resultMap="MyDifEmp"> SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id, d.id did,d.dept_name dept_name FROM tbl_employee e,tbl_dept d WHERE e.d_id=d.id AND e.id=#{id} </select> <!-- 使用association進行分步查詢: 1、先按照員工id查詢員工信息 2、根據查詢員工信息中的d_id值去部門表查出部門信息 3、部門設置到員工中; --> <!-- id last_name email gender d_id --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpByStep"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> <!-- association定義關聯對象的封裝規則 select:表明當前屬性是調用select指定的方法查出的結果 column:指定將哪一列的值傳給這個方法 流程:使用select指定的方法(傳入column指定的這列參數的值)查出對象,並封裝給property指定的屬性 --> <association property="dept" select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById" column="d_id"> </association> </resultMap> <!-- public Employee getEmpByIdStep(Integer id);--> <select id="getEmpByIdStep" resultMap="MyEmpByStep"> select * from tbl_employee where id=#{id} <if test="_parameter!=null"> and 1=1 </if> </select> <!-- 可以使用延遲加載(懶加載);(按需加載) Employee==>Dept: 我們每次查詢Employee對象的時候,都將一起查詢出來。 部門信息在我們使用的時候再去查詢; 分段查詢的基礎之上加上兩個配置: --> <!-- ==================association============================ --> <!-- 場景二: 查詢部門的時候將部門對應的所有員工信息也查詢出來:注釋在DepartmentMapper.xml中 --> <!-- public List<Employee> getEmpsByDeptId(Integer deptId); --> <select id="getEmpsByDeptId" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where d_id=#{deptId} </select> <!-- =======================鑒別器============================ --> <!-- <discriminator javaType=""></discriminator> 鑒別器:mybatis可以使用discriminator判斷某列的值,然后根據某列的值改變封裝行為 封裝Employee: 如果查出的是女生:就把部門信息查詢出來,否則不查詢; 如果是男生,把last_name這一列的值賦值給email; --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpDis"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> <!-- column:指定判定的列名 javaType:列值對應的java類型 --> <discriminator javaType="string" column="gender"> <!--女生 resultType:指定封裝的結果類型;不能缺少。/resultMap--> <case value="0" resultType="com.atguigu.mybatis.bean.Employee"> <association property="dept" select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById" column="d_id"> </association> </case> <!--男生 ;如果是男生,把last_name這一列的值賦值給email; --> <case value="1" resultType="com.atguigu.mybatis.bean.Employee"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="last_name" property="email"/> <result column="gender" property="gender"/> </case> </discriminator> </resultMap> </mapper>
上面中
<!--
聯合查詢:級聯屬性封裝結果集
-->
<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<result column="did" property="dept.id"/>
<result column="dept_name" property="dept.departmentName"/>
</resultMap>
必須和
<!-- public Employee getEmpAndDept(Integer id);-->
<select id="getEmpAndDept" resultMap="MyDifEmp">
SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id,
d.id did,d.dept_name dept_name FROM tbl_employee e,tbl_dept d
WHERE e.d_id=d.id AND e.id=#{id}
</select>
<result column="did"中的別名slql語句一一對應
我們來測試下
@Test public void test05() throws IOException{ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try{ EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class); Employee empAndDept = mapper.getEmpAndDept(1); System.out.println(empAndDept); }finally{ openSession.close(); } }
打印輸出為
DEBUG 04-24 07:12:34,290 ==> Preparing: SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id, d.id did,d.dept_name dept_name FROM tbl_employee e,tbl_dept d WHERE e.d_id=d.id AND e.id=? (BaseJdbcLogger.java:145) DEBUG 04-24 07:12:34,349 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:145) DEBUG 04-24 07:12:34,374 <== Total: 1 (BaseJdbcLogger.java:145) Employee [id=1, lastName=sdsfd, email=null, gender=1, dept=Department [id=2, departmentName=財務部]]
通過級聯操作實現了查詢員工的將該員工的部門信息查詢出來了。
除了級聯操作之后,我們來可以使用下面的assocoiate方式在查詢員工的時候將該員工的部門信息查詢出來
<!-- 使用association定義關聯的單個對象的封裝規則; --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp2"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="gender" property="gender"/> <!-- association可以指定聯合的javaBean對象 property="dept":指定哪個屬性是聯合的對象 javaType:指定這個屬性對象的類型[不能省略] --> <association property="dept" javaType="com.atguigu.mybatis.bean.Department"> <id column="did" property="id"/> <result column="dept_name" property="departmentName"/> </association> </resultMap> <!-- public Employee getEmpAndDept(Integer id);--> <select id="getEmpAndDept" resultMap="MyDifEmp2"> SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id, d.id did,d.dept_name dept_name FROM tbl_employee e,tbl_dept d WHERE e.d_id=d.id AND e.id=#{id} </select>
執行查詢結果同上面一樣
assocoiate方式還可以實現分布查詢,在介紹之前先做下面的操作
給部門表建立一個業務接口;類
DepartmentMapper
package com.atguigu.mybatis.dao; import com.atguigu.mybatis.bean.Department; public interface DepartmentMapper { public Department getDeptById(Integer id); public Department getDeptByIdPlus(Integer id); public Department getDeptByIdStep(Integer id); }
然后編寫對應的xml文件
DepartmentMapper.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.atguigu.mybatis.dao.DepartmentMapper"> <!--public Department getDeptById(Integer id); --> <select id="getDeptById" resultType="com.atguigu.mybatis.bean.Department"> select id,dept_name departmentName from tbl_dept where id=#{id} </select> <!-- public class Department { private Integer id; private String departmentName; private List<Employee> emps; did dept_name || eid last_name email gender --> <!--嵌套結果集的方式,使用collection標簽定義關聯的集合類型的屬性封裝規則 --> <resultMap type="com.atguigu.mybatis.bean.Department" id="MyDept"> <id column="did" property="id"/> <result column="dept_name" property="departmentName"/> <!-- collection定義關聯集合類型的屬性的封裝規則 ofType:指定集合里面元素的類型 --> <collection property="emps" ofType="com.atguigu.mybatis.bean.Employee"> <!-- 定義這個集合中元素的封裝規則 --> <id column="eid" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> </collection> </resultMap> <!-- public Department getDeptByIdPlus(Integer id); --> <select id="getDeptByIdPlus" resultMap="MyDept"> SELECT d.id did,d.dept_name dept_name, e.id eid,e.last_name last_name,e.email email,e.gender gender FROM tbl_dept d LEFT JOIN tbl_employee e ON d.id=e.d_id WHERE d.id=#{id} </select> <!-- collection:分段查詢 --> <resultMap type="com.atguigu.mybatis.bean.Department" id="MyDeptStep"> <id column="id" property="id"/> <id column="dept_name" property="departmentName"/> <collection property="emps" select="com.atguigu.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId" column="{deptId=id}" fetchType="lazy"></collection> </resultMap> <!-- public Department getDeptByIdStep(Integer id); --> <select id="getDeptByIdStep" resultMap="MyDeptStep"> select id,dept_name from tbl_dept where id=#{id} </select> <!-- 擴展:多列的值傳遞過去: 將多列的值封裝map傳遞; column="{key1=column1,key2=column2}" fetchType="lazy":表示使用延遲加載; - lazy:延遲 - eager:立即 --> </mapper>
assocoiate方式還可以實現分布查詢,在查詢員工的同時查詢出對應的部門,如何分布查詢出對應的結果了
第一步:查詢的員工的時候獲得部門的d_id
第二步:使用部門id在部門表中去查詢
我們來看下實現public Employee getEmpByIdStep(Integer id);
在EmployeeMapperPlus.xml
<!-- 使用association進行分步查詢: 1、先按照員工id查詢員工信息 2、根據查詢員工信息中的d_id值去部門表查出部門信息 3、部門設置到員工中; --> <!-- id last_name email gender d_id --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpByStep"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> <!-- association定義關聯對象的封裝規則 select:表明當前屬性是調用select指定的方法查出的結果 column:指定將哪一列的值傳給這個方法 流程:使用select指定的方法(傳入column指定的這列參數的值)查出對象,並封裝給property指定的屬性 --> <association property="dept" select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById" column="d_id"> </association> </resultMap> <!-- public Employee getEmpByIdStep(Integer id);--> <select id="getEmpByIdStep" resultMap="MyEmpByStep"> select * from tbl_employee where id=#{id} <if test="_parameter!=null"> and 1=1 </if> </select>
我來重點分析下
<association property="dept"
select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById"
column="d_id">
</association>
上面中的的dept必須是private Department dept;中的一一對應
select表示我要獲得property="dept"指定對象的值通過那個方法來查詢獲得
com.atguigu.mybatis.dao.DepartmentMapper.getDeptById這個在DepartmentMapper.xml中進行了實現
第三個參數:在執行com.atguigu.mybatis.dao.DepartmentMapper.getDeptById需要傳入一個參數,我們在執行 select * from tbl_employee where id=#{id}會得到d_id的值,我們需要將這個d_id的值賦值給com.atguigu.mybatis.dao.DepartmentMapper.getDeptById,我們就使用
column="d_id"來指定,這個d_id是員工表中的列名d_id
我們來測試下
@Test public void test05() throws IOException{ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try{ EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class); Employee employee = mapper.getEmpByIdStep(3); System.out.println(employee); System.out.println(employee.getDept()); }finally{ openSession.close(); } }
我們來看下打印的結果
DEBUG 04-24 07:38:05,624 ==> Preparing: select * from tbl_employee where id=? and 1=1 (BaseJdbcLogger.java:145) DEBUG 04-24 07:38:05,686 ==> Parameters: 3(Integer) (BaseJdbcLogger.java:145) DEBUG 04-24 07:38:05,756 <== Total: 1 (BaseJdbcLogger.java:145) DEBUG 04-24 07:38:05,757 ==> Preparing: select id,dept_name departmentName from tbl_dept where id=? (BaseJdbcLogger.java:145) DEBUG 04-24 07:38:05,758 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:145) DEBUG 04-24 07:38:05,761 <== Total: 1 (BaseJdbcLogger.java:145) Employee [id=3, lastName=jerry4, email=null, gender=1, dept=Department [id=1, departmentName=研發部]] Department [id=1, departmentName=研發部]
我們可以看出分布查詢上面發出了兩條sql查閱語句
場景二:在查詢部門的時候將該部門下面的所有員工信息查詢出來
DepartmentMapper.java業務接口類
package com.atguigu.mybatis.dao; import com.atguigu.mybatis.bean.Department; public interface DepartmentMapper { public Department getDeptById(Integer id); public Department getDeptByIdPlus(Integer id); public Department getDeptByIdStep(Integer id); }

上面的sql語句要使用左連接。左連接的作用是即使部門下面不存在任何員工也會將該部門的值顯示出來,如果去掉left只會查詢出存在員工的部門,會存在部門丟失
方式一:
DepartmentMapper.xml
<!--嵌套結果集的方式,使用collection標簽定義關聯的集合類型的屬性封裝規則 --> <resultMap type="com.atguigu.mybatis.bean.Department" id="MyDept"> <id column="did" property="id"/> <result column="dept_name" property="departmentName"/> <!-- collection定義關聯集合類型的屬性的封裝規則 ofType:指定集合里面元素的類型 --> <collection property="emps" ofType="com.atguigu.mybatis.bean.Employee"> <!-- 定義這個集合中元素的封裝規則 --> <id column="eid" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> </collection> </resultMap> <!-- public Department getDeptByIdPlus(Integer id); --> <select id="getDeptByIdPlus" resultMap="MyDept"> SELECT d.id did,d.dept_name dept_name, e.id eid,e.last_name last_name,e.email email,e.gender gender FROM tbl_dept d LEFT JOIN tbl_employee e ON d.id=e.d_id WHERE d.id=#{id} </select>
我們來測試下
@Test public void test06() throws IOException{ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try{ DepartmentMapper mapper = openSession.getMapper(DepartmentMapper.class); Department department = mapper.getDeptByIdPlus(1); System.out.println(department); System.out.println(department.getEmps()); }finally{ openSession.close(); } }
運行結果如下
DEBUG 04-24 07:52:12,669 ==> Preparing: SELECT d.id did,d.dept_name dept_name, e.id eid,e.last_name last_name,e.email email,e.gender gender FROM tbl_dept d LEFT JOIN tbl_employee e ON d.id=e.d_id WHERE d.id=? (BaseJdbcLogger.java:145) DEBUG 04-24 07:52:12,734 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:145) DEBUG 04-24 07:52:12,757 <== Total: 1 (BaseJdbcLogger.java:145) Department [id=1, departmentName=研發部] [Employee [id=3, lastName=jerry4, email=null, gender=1, dept=null]]
實現的第二種方式,使用分段查詢public Department getDeptByIdStep(Integer id);
<!-- collection:分段查詢 --> <resultMap type="com.atguigu.mybatis.bean.Department" id="MyDeptStep"> <id column="id" property="id"/> <id column="dept_name" property="departmentName"/> <collection property="emps" select="com.atguigu.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId" column="{deptId=id}" fetchType="lazy"></collection> </resultMap> <!-- public Department getDeptByIdStep(Integer id); --> <select id="getDeptByIdStep" resultMap="MyDeptStep"> select id,dept_name from tbl_dept where id=#{id} </select> <!-- 擴展:多列的值傳遞過去: 將多列的值封裝map傳遞; column="{key1=column1,key2=column2}" fetchType="lazy":表示使用延遲加載; - lazy:延遲 - eager:立即 -->
我們來測試下
@Test public void test06() throws IOException{ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try{ DepartmentMapper mapper = openSession.getMapper(DepartmentMapper.class); Department deptByIdStep = mapper.getDeptByIdStep(1); System.out.println(deptByIdStep.getDepartmentName()); System.out.println(deptByIdStep.getEmps()); }finally{ openSession.close(); } }
DEBUG 04-24 07:59:20,628 ==> Preparing: select id,dept_name from tbl_dept where id=? (BaseJdbcLogger.java:145) DEBUG 04-24 07:59:20,693 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:145) DEBUG 04-24 07:59:20,765 <== Total: 1 (BaseJdbcLogger.java:145) 研發部 DEBUG 04-24 07:59:20,766 ==> Preparing: select * from tbl_employee where d_id=? (BaseJdbcLogger.java:145) DEBUG 04-24 07:59:20,767 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:145) DEBUG 04-24 07:59:20,770 <== Total: 1 (BaseJdbcLogger.java:145) [Employee [id=3, lastName=jerry4, email=null, gender=1, dept=null]]
運行結果發出了兩條sql語句
上面存在一個知識點
<!-- 擴展:多列的值傳遞過去:
將多列的值封裝map傳遞;
column="{key1=column1,key2=column2}"
fetchType="lazy":表示使用延遲加載;
- lazy:延遲
- eager:立即
-->
column="{deptId=id}" 中deptId對應的是select方法中com.atguigu.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId對的#{deptid}一一對應,value值id對應的就是數據庫中部門表中列名id
<!-- public List<Employee> getEmpsByDeptId(Integer deptId); -->
<select id="getEmpsByDeptId" resultType="com.atguigu.mybatis.bean.Employee">
select * from tbl_employee where d_id=#{deptId}
</select>
接下來我們實現下面的規則:如果查詢出來的是女生,我們將該員工的部門查詢出來,如果是男生,將該員工的信息設置為name的值如何實現了
我們可以使用鑒別器來實現
<!-- =======================鑒別器============================ --> <!-- <discriminator javaType=""></discriminator> 鑒別器:mybatis可以使用discriminator判斷某列的值,然后根據某列的值改變封裝行為 封裝Employee: 如果查出的是女生:就把部門信息查詢出來,否則不查詢; 如果是男生,把last_name這一列的值賦值給email; --> <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpDis"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> <!-- column:指定判定的列名 javaType:列值對應的java類型 --> <discriminator javaType="string" column="gender"> <!--女生 resultType:指定封裝的結果類型;不能缺少。/resultMap--> <case value="0" resultType="com.atguigu.mybatis.bean.Employee"> <association property="dept" select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById" column="d_id"> </association> </case> <!--男生 ;如果是男生,把last_name這一列的值賦值給email; --> <case value="1" resultType="com.atguigu.mybatis.bean.Employee"> <id column="id" property="id"/> <result column="last_name" property="lastName"/> <result column="last_name" property="email"/> <result column="gender" property="gender"/> </case> </discriminator> </resultMap>
