Java SSM篇3——Mybatis
Java SSM篇3——Mybatis
1、JDBC存在的問題
- 數據庫連接創建、釋放頻繁造成系統資源浪費從而影響系統性能
- sql 語句在代碼中硬編碼,造成代碼不易維護,實際應用 sql 變化的可能較大,sql 變動需要改變java 代碼
- 查詢操作時,需要手動將結果集中的數據手動封裝到實體中
2、解決方案
- 數據庫連接池
- 配置文件
- 反射、內省
3、ORM是什么
對象關系映射
- O(對象模型): 實體對象,即我們在程序中根據數據庫表結構建立的一個個實體javaBean
- R(關系型數據庫的數據結構): 關系數據庫領域的Relational(建立的數據庫表)
- M(映射): 從R(數據庫)到O(對象模型)的映射,可通過XML文件映射
3、Mybatis簡介
MyBatis是一個優秀的基于ORM的半自動輕量級持久層框架,它對jdbc的操作數據庫的過程進行封裝, 使開發者只需要關注 SQL 本身,而不需要花費精力去處理例如注冊驅動、創建connection、創建 statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼
mybatis 官方文檔:https://mybatis.org/mybatis-3/
4、mybatis快速入門
4.1、數據庫準備
CREATE TABLE person(id INT PRIMARY KEY,NAME VARCHAR(10),PASSWORD VARCHAR(10) ); INSERT INTO person VALUES (1,"root","123");4.2、創建maven工程,pom.xml導入依賴
<dependencies><!--mybatis--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.5</version></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.20</version></dependency><!--junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version><scope>test</scope></dependency> </dependencies>pom設置資源過濾
<!--maven過濾問題--> <build><resources><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource><resource><directory>src/main/resources</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource></resources> </build>4.3、數據庫配置文件(database.properties)
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://132.232.82.49:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone =Asia/Shanghai username=root password=root4.4、mybatis配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!--引入properties配置文件--><properties resource="database.properties"></properties><!--別名--><typeAliases><package name="club.winkto.bean"></package></typeAliases><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments><!--注冊映射文件--><mappers><package name="club.winkto.mapper"/></mappers> </configuration>4.5、實體類
public class Person {private int id;private String name;private String password; }4.6、Mapper接口
public interface PersonMapper {ArrayList<Person> selectPerson();int insertPerson(Person person);int updatePerson(Person person);int deletePerson(int id); }4.7、映射文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="club.winkto.mapper.PersonService"><select id="selectPerson" resultType="Person">select * from person;</select><insert id="insertPerson" parameterType="Person">insert into person values (#{id},#{name},#{password});</insert><update id="updatePerson" parameterType="Person">update person set name=#{name},password=#{password} where id=#{id};</update><delete id="deletePerson" parameterType="int">delete from person where id=#{id};</delete> </mapper>4.8、mybatis工具類
public class MybatisUtils {private static SqlSessionFactory sqlSessionFactory=null;static{String resource = "mybatis_config.xml";InputStream inputStream = null;try {inputStream = Resources.getResourceAsStream(resource);} catch (IOException e) {e.printStackTrace();}sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}public static SqlSession getSqlSession(){return sqlSessionFactory.openSession();} }4.9、測試類
public class CRUD {@Testpublic void select(){SqlSession sqlSession = MybatisUtils.getSqlSession();PersonService mapper = sqlSession.getMapper(PersonService.class);ArrayList<Person> people = mapper.selectPerson();for (Person person : people) {System.out.println(person);}System.out.println("========================");sqlSession.close();}@Testpublic void insert(){SqlSession sqlSession = MybatisUtils.getSqlSession();PersonService mapper = sqlSession.getMapper(PersonService.class);int i = mapper.insertPerson(new Person(2, "bingbing", "123"));if (i>0){sqlSession.commit();}sqlSession.close();}@Testpublic void update(){SqlSession sqlSession = MybatisUtils.getSqlSession();PersonService mapper = sqlSession.getMapper(PersonService.class);int i = mapper.updatePerson(new Person(2, "bingbing", "blingbling"));if (i>0){sqlSession.commit();}sqlSession.close();}@Testpublic void delete(){SqlSession sqlSession = MybatisUtils.getSqlSession();PersonService mapper = sqlSession.getMapper(PersonService.class);int i = mapper.deletePerson(2);if (i>0){sqlSession.commit();}sqlSession.close();}@Testpublic void doCRUD(){select();insert();select();update();select();delete();select();} }5、Mybatis配置解析
- properties
- settings
- typeAliases
- typeHandlers
- objectFactory
- plugins
- environments
- environment
- transactionManager
- dataSource
- environment
- databaseIdProvider
- mappers
5.1、properties
5.1.1、直接書寫properties內容
<properties><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://132.232.82.49:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone =Asia/Shanghai"/><property name="username" value="root"/><property name="password" value="root"/> </properties>5.1.2、引入properties文件
<properties resource="database.properties"></properties> driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://132.232.82.49:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone =Asia/Shanghai username=root password=root5.1.3、優先級問題
如果一個屬性在多個地方出現,優先級為
- 在方法體中給定的參數值
- 在類路徑或URL資源中讀取的屬性
- 屬性文件中的屬性
5.2、settings
官方屬性頁:https://mybatis.org/mybatis-3/configuration.html#settings
<settings><!--全局啟用或禁用在此配置下在任何映射器中配置的任何緩存--><setting name="cacheEnabled" value="true"/><!--全局啟用或禁用延遲加載,啟用時,將延遲加載所有關系,對于特定關系,可以使用fetchType屬性替換該值--><setting name="lazyLoadingEnabled" value="true"/><!--允許或不允許從單個語句返回多個結果集--><setting name="multipleResultSetsEnabled" value="true"/><!--使用列標簽而不是列名--><setting name="useColumnLabel" value="true"/><!--允許JDBC支持生成的密鑰--><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="mapUnderscoreToCamelCase" value="false"/><setting name="localCacheScope" value="SESSION"/><setting name="jdbcTypeForNull" value="OTHER"/><setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/><!--日志方式--><setting name="logImpl" value="STDOUT_LOGGING"/> </settings>5.3、typeAliases
5.3.1、設置單個
<typeAliases><typeAlias type="com.yan.po.User" alias="user"/> </typeAliases>5.3.2、設置包
<typeAliases><package name="com.ruoye.bean"></package> </typeAliases>5.3.3、Mybatis設置好的類型別名
| _byte | byte |
| _long | long |
| _short | short |
| _int | int |
| _integer | int |
| _double | double |
| _float | float |
| _boolean | boolean |
| string | String |
| byte | Byte |
| long | Long |
| short | Short |
| int | Integer |
| integer | Integer |
| double | Double |
| float | Float |
| boolean | Boolean |
| date | Date |
| decimal | BigDecimal |
| bigdecimal | BigDecimal |
| object | Object |
| map | Map |
| hashmap | HashMap |
| list | List |
| arraylist | ArrayList |
| collection | Collection |
| iterator | Iterator |
5.4、typeHandlers(類型句柄)
可以重寫類型句柄或者是創建你自己的方式來處理不支持或者是非標準的類型,只需要簡單地實現org.mybaits.type包里的TypeHandler,并且映射到一個JAVA類型,然后再選定一個JDBC類型
5.4.1、定義類型
<typeHandlers><typeHandler handler="RuoyeTypeHandler"/> </typeHandlers>5.4.2、實現TypeHandler
import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.TypeHandler;import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException;public class RuoyeTypeHandler<T> implements TypeHandler<T> {public void setParameter(PreparedStatement preparedStatement, int i, T t, JdbcType jdbcType) throws SQLException {preparedStatement.setString(i, (String) t);}public T getResult(ResultSet resultSet, String s) throws SQLException {return null;}public T getResult(ResultSet resultSet, int i) throws SQLException {return null;}public T getResult(CallableStatement callableStatement, int i) throws SQLException {return null;} }5.4.3、使用
<resultMap type="" id="" ><result column="" property="" typeHandler="RuoyeTypeHandler"/> </resultMap>5.5、ObjectFactory
5.5.1、定義
<ObjectFactory type="RuoyeObjectFactory"><property name="" value=""/> </ObjectFactory>5.5.2、繼承DefaultObjectFactory
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;import java.util.List; import java.util.Properties;public class RuoyeObjectFactory extends DefaultObjectFactory {@Overridepublic <T> T create(Class<T> type) {return super.create(type);}@Overridepublic <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {return super.create(type, constructorArgTypes, constructorArgs);}public void setProperties(Properties properties) {} }5.6、plugins
<plugins><plugin interceptor="com.github.pagehelper.PageHelper"><!-- 設置數據庫類型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六種數據庫--> <property name="dialect" value="mysql"/></plugin> </plugins>5.7、environments
雖然你可以配置多重環境,但是你只可以選擇一對一的SqlsessionFactory實例
<environments default="formal"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment><environment id="formal"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment> </environments>5.8、Mappers
5.8.1、單個映射
<mappers><mapper resource="club/winkto/mapper/PersonMapper.xml"/> </mappers> <mappers><!--路徑以.分隔--><mapper class="club.winkto.mapper.PersonMapper"></mapper> </mappers>5.8.2、包映射
<mappers><package name="club.winkto.mapper"/> </mappers>6、注解開發(初步認識)
不再書寫映射文件PersonMapper.xml
public interface PersonMapper {@Select("select * from person")ArrayList<Person> selectPerson();@Insert("insert into person values (#{id},#{name},#{password})")int insertPerson(Person person);@Update("update person set name=#{name},password=#{password} where id=#{id}")int updatePerson(Person person);@Delete("delete from person where id=#{id}")int deletePerson(@Param("id") int id); }注冊class文件,當然你也可以注冊包
<mappers><!--路徑以/分隔--><mapper class="com.lancame.mapper.PersonService"></mapper> </mappers>7、結果集映射(初步認識)
resultType:如果實體的屬性名與表中字段名一致,將查詢結果自動封裝到實體類中
<select id="selectPerson" resultType="Person">select * from person; </select>resutlMap:如果實體的屬性名與表中字段名不一致,可以使用ResutlMap實現手動封裝到實體類中
如果有查詢結果有 字段與屬性是對應的,可以省略手動封裝 <resultMap id="PersonMap" type="Person"><!--id常用于主鍵列--><id column="id" property="id" /><!--result用于其他列--><result column="name" property="name" /><result column="password" property="password" /> </resultMap> <select id="selectPerson" resultMap="PersonMap">select * from person; </select>8、參數傳遞
8.1、封裝map傳遞
<select id="selectPerson1" parameterType="map" resultType="Person">select * from person where name=#{name} and password=#{password}; </select> public interface PersonMapper {ArrayList<Person> selectPerson1(Map map); } @Test public void select1(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);HashMap<String, Object> hashMap = new HashMap<String, Object>();hashMap.put("name","root");hashMap.put("password","123");ArrayList<Person> people = mapper.selectPerson1(hashMap);for (Person person : people) {System.out.println(person);}System.out.println("========================");sqlSession.close(); }8.2、注解傳遞
<select id="selectPerson1" resultType="Person">select * from person where name=#{name} and password=#{password}; </select> public interface PersonMapper {ArrayList<Person> selectPerson1(@Param("name") String name,@Param("password") String password); } @Test public void select1(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);ArrayList<Person> people = mapper.selectPerson1("root","123");for (Person person : people) {System.out.println(person);}System.out.println("========================");sqlSession.close(); }9、模糊查詢
9.1、${} 與 #{}
-
通過 #{} 可以實現preparedStatement向占位符中設置值,自動進行java類型和jdbc類型轉換,# {}可以有效防止sql注入
-
通過 ${} 可以將parameterType 傳入的內容拼接在sql中且不進行jdbc類型轉換,會出現sql注入問題
9.2、模糊查詢操作
<select id="selectPerson2" parameterType="string" resultType="Person">select * from person where name like "%"#{name}"%" </select> public interface PersonMapper {ArrayList<Person> selectPerson2(String name); } @Test public void select2(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);ArrayList<Person> people = mapper.selectPerson2("roo");for (Person person : people) {System.out.println(person);}System.out.println("========================");sqlSession.close(); }9.3、返回主鍵
9.3.1、useGeneratedKeys
只適用于主鍵自增的數據庫,mysql和sqlserver支持,oracle不行
<insert id="insertPerson1" parameterType="Person" useGeneratedKeys="true" keyProperty="id">insert into person (name,password) values (#{name},#{password}); </insert> public interface PersonMapper {int insertPerson1(Person person); } @Test public void insert1(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);Person bingbing = new Person(0, "bingbing", "123");int i = mapper.insertPerson1(bingbing);System.out.println(bingbing.getId());if (i>0){sqlSession.commit();}sqlSession.close(); }9.3.2、selectKey
適用范圍廣,支持所有類型數據庫
<insert id="insertPerson2" parameterType="Person">insert into person (name,password) values (#{name},#{password});<selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">SELECT LAST_INSERT_ID();</selectKey> </insert> public interface PersonMapper {int insertPerson1(Person person); } @Test public void insert2(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);Person bingbing = new Person(0, "bingbing", "123");int i = mapper.insertPerson1(bingbing);System.out.println(bingbing.getId());if (i>0){sqlSession.commit();}sqlSession.close(); }10、動態SQL
當我們要根據不同的條件,來執行不同的sql語句的時候,需要用到動態sql
10.1、where、if
<select id="selectPerson3" resultType="Person">select * from person<where><if test="name!=null">and name=#{name}</if><if test="password!=null">and password=#{password}</if></where> </select> public interface PersonMapper {ArrayList<Person> selectPerson3(@Param("name") String name,@Param("password") String password); } @Test public void select3(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);ArrayList<Person> people = mapper.selectPerson3(null,"123");for (Person person : people) {System.out.println(person);}System.out.println("========================");sqlSession.close(); }10.2、set、if
<update id="updatePerson1" parameterType="Person">update person<set><if test="name!=null">name=#{name},</if><if test="password!=null">password=#{password},</if></set>where id=#{id}; </update> public interface PersonMapper {int updatePerson1(Person person); } @Test public void update1(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);int i = mapper.updatePerson1(new Person(2, "bingbing", "blingbling"));if (i>0){sqlSession.commit();}sqlSession.close(); }10.3、Choose、when、otherwise
參考switch
<select id="selectPerson4" resultType="Person">select * from person<where><choose><when test="name!=null">and name=#{name}</when><otherwise>and password=123</otherwise></choose></where> </select> public interface PersonMapper {ArrayList<Person> selectPerson3(@Param("name") String name,@Param("password") String password); } @Test public void select4(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);ArrayList<Person> people = mapper.selectPerson4(null,"123");for (Person person : people) {System.out.println(person);}System.out.println("========================");sqlSession.close(); }10.4、foreach
<select id="selectPerson5" resultType="Person">select * from person<where>id in<foreach collection="list" open="(" close=")" item="id" separator=",">#{id}</foreach></where> </select> public interface PersonMapper {;ArrayList<Person> selectPerson5(ArrayList<Integer> arrayList); } @Test public void select5(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);ArrayList<Integer> integers = new ArrayList<Integer>(Arrays.asList(1,5,6));ArrayList<Person> people = mapper.selectPerson5(integers);for (Person person : people) {System.out.println(person);}System.out.println("========================");sqlSession.close(); }11、SQL片段
<update id="updatePerson1" parameterType="Person">update person<set><include refid="whereif"></include></set>where id=#{id}; </update> <sql id="whereif"><if test="name!=null">name=#{name},</if><if test="password!=null">password=#{password},</if> </sql> public interface PersonMapper {int updatePerson1(Person person); } @Test public void update1(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);int i = mapper.updatePerson1(new Person(2, "bingbing", "blingbling"));if (i>0){sqlSession.commit();}sqlSession.close(); }12、分頁插件
12.1、依賴導入
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>3.7.5</version> </dependency> <dependency><groupId>com.github.jsqlparser</groupId><artifactId>jsqlparser</artifactId><version>0.9.1</version> </dependency>12.2、mybatis配置分頁
<plugins><!-- 分頁助手的插件 --><plugin interceptor="com.github.pagehelper.PageHelper"><!-- 指定方言 --><property name="dialect" value="mysql"/></plugin> </plugins>12.3、測試
@Test public void select6(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);PageHelper.startPage(1,2);ArrayList<Person> people = mapper.selectPerson();for (Person person : people) {System.out.println(person);}System.out.println("========================");PageInfo<Person> pageInfo = new PageInfo<Person>(people);System.out.println("總條數:"+pageInfo.getTotal());System.out.println("總頁數:"+pageInfo.getPages());System.out.println("當前頁:"+pageInfo.getPageNum());System.out.println("每頁顯示長度:"+pageInfo.getPageSize());System.out.println("是否第一頁:"+pageInfo.isIsFirstPage());System.out.println("是否最后一頁:"+pageInfo.isIsLastPage());sqlSession.close(); }13、多表查詢(根據結果嵌套)
- 一對一:人與身份證號的關系
- 一對多:用戶與訂單的關系,一個用戶可以有多個訂單,但是一個訂單只能有一個用戶
- 多對多:用戶與課程的關系,一個用戶可以選多個課程,一個課程可以被多個用戶選擇
13.1、一對一(多對一)
13.1.1、數據庫準備
CREATE TABLE person(pid INT PRIMARY KEY AUTO_INCREMENT,pname VARCHAR(20),ppassword VARCHAR(20) ) CREATE TABLE idnum(pid INT,idnum VARCHAR(18) ) ALTER TABLE ID ADD CONSTRAINT t2 FOREIGN KEY (pid) REFERENCES person(pid);13.1.2、實體類
public class IDNum {private int pid;private String idnum; } public class Person {private int pid;private String pname;private String ppassword;private IDNum idnum; }13.1.3、接口
public interface PersonMapper {List<Person> selectPersonWithID(); }13.1.4、映射文件
-
一對一使用association標簽關聯
-
property=“user” 封裝實體的屬性名
-
javaType=“user” 封裝實體的屬性類型
13.1.5、測試
@Test public void test(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);List<Person> people = mapper.selectPersonWithID();for (Person person : people) {System.out.println(person);} }13.2、一對多
13.2.1、數據庫準備
CREATE TABLE person(pid INT PRIMARY KEY AUTO_INCREMENT,pname VARCHAR(20),ppassword VARCHAR(20) ) CREATE TABLE orders(pid INT,oid INT PRIMARY KEY AUTO_INCREMENT,otime DATETIME,oremark VARCHAR(100) ) ALTER TABLE orders ADD CONSTRAINT t1 FOREIGN KEY (pid) REFERENCES person(pid);隨便加幾條數據
13.2.2、實體類
public class Person {private int pid;private String pname;private String ppassword;private List<Order> orders; } public class Order {private int pid;private int oid;private Date date;private String oremark; }13.2.3、接口
public interface PersonMapper {List<Person> selectPersonWithOrder(); }13.2.4、映射文件
- 一對多使用collection標簽關聯
- property=“orderList” 封裝到集合的屬性名
- ofType=“order” 封裝集合的泛型類型
13.2.5、測試
@Test public void test1(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);List<Person> people = mapper.selectPersonWithOrder();for (Person person : people) {System.out.println(person);} }13.3、多對多
13.3.1、數據庫準備
CREATE TABLE person(pid INT PRIMARY KEY AUTO_INCREMENT,pname VARCHAR(20),ppassword VARCHAR(20) ) CREATE TABLE course(cid INT PRIMARY KEY AUTO_INCREMENT,cname VARCHAR(20) ); CREATE TABLE person_course(pid INT,cid INT ); ALTER TABLE person_course ADD CONSTRAINT t3 FOREIGN KEY (pid) REFERENCES person(pid); ALTER TABLE person_course ADD CONSTRAINT t4 FOREIGN KEY (cid) REFERENCES course(cid);隨便加幾條數據
13.3.2、實體類
public class Person {private int pid;private String pname;private String ppassword;private List<Order> orders; } public class Course {private int cid;private String cname; }13.3.3、接口
public interface PersonMapper {List<Person> selectPersonWithCourse(); }13.3.4、映射文件
- 一對多使用collection標簽關聯
- property=“orderList” 封裝到集合的屬性名
- ofType=“order” 封裝集合的泛型類型
13.3.5、測試
@Test public void test2(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);List<Person> people = mapper.selectPersonWithCourse();for (Person person : people) {System.out.println(person);} }14、多表查詢(根據查詢嵌套)
14.1、一對一(多對一)
14.1.1、數據庫準備
CREATE TABLE person(pid INT PRIMARY KEY AUTO_INCREMENT,pname VARCHAR(20),ppassword VARCHAR(20) ) CREATE TABLE idnum(pid INT,idnum VARCHAR(18) ) ALTER TABLE ID ADD CONSTRAINT t2 FOREIGN KEY (pid) REFERENCES person(pid);14.1.2、實體類
public class IDNum {private int pid;private String idnum; } public class Person {private int pid;private String pname;private String ppassword;private IDNum idnum; }14.1.3、接口
public interface PersonMapper {List<Person> selectPersonWithID(); }14.1.4、映射文件
-
一對一使用association標簽關聯
-
property=“user” 封裝實體的屬性名
-
javaType=“user” 封裝實體的屬性類型
-
column傳遞的參數
-
select調用的查詢語句
14.1.5、測試
@Test public void test(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);List<Person> people = mapper.selectPersonWithID();for (Person person : people) {System.out.println(person);} }14.2、一對多
14.2.1、數據庫準備
CREATE TABLE person(pid INT PRIMARY KEY AUTO_INCREMENT,pname VARCHAR(20),ppassword VARCHAR(20) ) CREATE TABLE orders(pid INT,oid INT PRIMARY KEY AUTO_INCREMENT,otime DATETIME,oremark VARCHAR(100) ) ALTER TABLE orders ADD CONSTRAINT t1 FOREIGN KEY (pid) REFERENCES person(pid);隨便加幾條數據
14.2.2、實體類
public class Person {private int pid;private String pname;private String ppassword;private List<Order> orders; } public class Order {private int pid;private int oid;private Date date;private String oremark; }14.2.3、接口
public interface PersonMapper {List<Person> selectPersonWithOrder(); }14.2.4、映射文件
- 一對多使用collection標簽關聯
- property=“orderList” 封裝到集合的屬性名
- ofType=“order” 封裝集合的泛型類型
- column傳遞的參數
- select調用的查詢語句
14.2.5、測試
@Test public void test1(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);List<Person> people = mapper.selectPersonWithOrder();for (Person person : people) {System.out.println(person);} }14.3、多對多
14.3.1、數據庫準備
CREATE TABLE person(pid INT PRIMARY KEY AUTO_INCREMENT,pname VARCHAR(20),ppassword VARCHAR(20) ) CREATE TABLE course(cid INT PRIMARY KEY AUTO_INCREMENT,cname VARCHAR(20) ); CREATE TABLE person_course(pid INT,cid INT ); ALTER TABLE person_course ADD CONSTRAINT t3 FOREIGN KEY (pid) REFERENCES person(pid); ALTER TABLE person_course ADD CONSTRAINT t4 FOREIGN KEY (cid) REFERENCES course(cid);隨便加幾條數據
14.3.2、實體類
public class Person {private int pid;private String pname;private String ppassword;private List<Order> orders; } public class Course {private int cid;private String cname; }14.3.3、接口
public interface PersonMapper {List<Person> selectPersonWithCourse(); }14.3.4、映射文件
- 一對多使用collection標簽關聯
- property=“orderList” 封裝到集合的屬性名
- ofType=“order” 封裝集合的泛型類型
- column傳遞的參數
- select調用的查詢語句
14.3.5、測試
@Test public void test2(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);List<Person> people = mapper.selectPersonWithCourse();for (Person person : people) {System.out.println(person);} }15、加載策略
就是在需要用到數據時才進行加載,不需要用到數據時就不加載數據,延遲加載也稱懶加載
延遲加載是基于查詢嵌套來實現的
15.1、優點
先從單表查詢,需要時再從關聯表去關聯查詢,大大提高數據庫性能,因為查詢單表要比關聯查詢多張表 速度要快
15.2、缺點
因為只有當需要用到數據時,才會進行數據庫查詢,這樣在大批量數據查詢時,因為查詢工作也要消耗時 間,所以可能造成用戶等待時間變長,造成用戶體驗下降
15.3、開啟局部延遲加載
在association和collection標簽中都有一個fetchType屬性,通過修改它的值,可以修改局部的加載策略
- fetchType=“lazy” 懶加載策略
- fetchType=“eager” 立即加載策略
15.4、延遲加載觸發策略
在配置了延遲加載策略后,發現即使沒有調用關聯對象的任何方法,但是在你調用當前對象的 equals、clone、hashCode、toString方法時也會觸發關聯對象的查詢,可以在配置文件中使用lazyLoadTriggerMethods配置項覆蓋掉上面四個方法
<settings><setting name="lazyLoadTriggerMethods" value="toString()"/> </settings>15.5、全局延遲加載
局部的加載策略優先級高于全局的加載策略
<settings><setting name="lazyLoadingEnabled" value="true"/> </settings>16、緩存
通過緩存策略來減少數據庫的查詢次數, 從而提高性能
16.1、一級緩存
一級緩存是SqlSession級別的緩存,是默認開啟的
在參數和SQL完全一樣的情況下,使用同一個SqlSession對象調用一個Mapper方法,往往只執行一次SQL,因為使用SelSession第一次查詢后,MyBatis會將其放在緩存中,以后再查詢的時 候,如果沒有聲明需要刷新,并且緩存沒有超時的情況下,SqlSession都會取出當前緩存的數據,而不 會再次發送SQL到數據庫
一級緩存是SqlSession范圍的緩存,執行SqlSession的C(增加)U(更新)D(刪除)操作,或者調 用clearCache()、commit()、close()方法,都會清空緩存
強制清空一級緩存
sqlSession.clearCache();設置每次清空一級緩存
<select flushCache="true"></select>16.2、二級緩存
二級緩存是namspace級別(跨sqlSession)的緩存,是默認不開啟的
二級緩存的開啟需要進行配置,實現二級緩存的時候,MyBatis要求返回的POJO必須是可序列化的。 也就是要求實現Serializable接口,配置方法很簡單,只需要在映射XML文件配置 就可以開啟 二級緩存了
二級緩存是mapper映射級別的緩存,多個SqlSession去操作同一個Mapper映射的sql語句,多個 SqlSession可以共用二級緩存,二級緩存是跨SqlSession的
mybatis的二級緩存因為是namespace級別,所以在進行多表查詢時會產生臟讀問題
16.2.1、mybatis核心配置開啟二級緩存(默認開啟,此步可以省略)
<settings><setting name="cacheEnabled" value="true"/> </settings>16.2.2、在mapper文件中加入
<cache></cache>緩存參數配置
<cache eviction="FIFO"flushInterval="60000"size="512"readOnly="true"/>16.2.3、在select語句上開啟二級緩存
標簽中設置useCache=”true”代表當前這個statement要使用二級緩存
<select useCache="true"></select>16.2.4、修改實體類
繼承Serializable
17、注解(深度認識)
之前在映射文件中通過配置、、來實現復雜關系映射
使用注解開發后,我們可以使用 @Results、@Result,@One、@Many 注解組合完成復雜關系的配置
17.1、根據結果嵌套
我們直接來看根據結果嵌套,看完這個懂了
17.2、根據查詢嵌套
17.2.1、一對一
接口
@Select("select * from person") @Results({@Result(column = "pid",property = "pid",id = true),@Result(column = "pname",property = "pname"),@Result(column = "ppassword",property = "ppassword"),@Result(column = "pid",property = "idnum",javaType = IDNum.class,one = @One(select = "club.winkto.mapper.PersonMapperAnno.selectIDNum",fetchType = FetchType.EAGER)) }) @Select("select * from idnum where pid=#{pid}") IDNum selectIDNum(int pid);測試
@Test public void test3(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapperAnno mapper = sqlSession.getMapper(PersonMapperAnno.class);List<Person> people = mapper.selectPersonWithID();for (Person person : people) {System.out.println(person);} }17.2.2、一對多
接口
@Select("select * from person") @Results({@Result(column = "pid",property = "pid",id = true),@Result(column = "pname",property = "pname"),@Result(column = "ppassword",property = "ppassword"),@Result(column = "pid",property = "orders",javaType = List.class,many = @Many(select = "club.winkto.mapper.PersonMapperAnno.selectOrder",fetchType = FetchType.EAGER)) }) List<Person> selectPersonWithOrder(); @Select("select * from orders where pid=#{pid}") List<Order> selectOrder(int pid);測試
@Test public void test4(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapperAnno mapper = sqlSession.getMapper(PersonMapperAnno.class);List<Person> people = mapper.selectPersonWithOrder();for (Person person : people) {System.out.println(person);} }17.2.3、多對多
接口
@Select("select * from person") @Results({@Result(column = "pid",property = "pid",id = true),@Result(column = "pname",property = "pname"),@Result(column = "ppassword",property = "ppassword"),@Result(column = "pid",property = "courses",javaType = List.class,many = @Many(select = "club.winkto.mapper.PersonMapperAnno.selectCourse",fetchType = FetchType.EAGER)) }) List<Person> selectPersonWithCourse(); @Select("select * from course,person_course where person_course.pid=#{pid} and person_course.cid=course.cid") List<Course> selectCourse(int pid);測試
@Test public void test5(){SqlSession sqlSession = MybatisUtil.getSqlSession();PersonMapperAnno mapper = sqlSession.getMapper(PersonMapperAnno.class);List<Person> people = mapper.selectPersonWithCourse();for (Person person : people) {System.out.println(person);} }17.3、注解開啟二級緩存
在接口上使用@CacheNamespace即可
17.4、注解開啟延遲加載
- fetchType = FetchType.LAZY
- fetchType = FetchType.EAGER
- fetchType = FetchType.DEFAULT(采用全局配置)
總結
以上是生活随笔為你收集整理的Java SSM篇3——Mybatis的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: poweramp最完美设置_2020年感
- 下一篇: Windows之node.js安装