1.MyBatis簡述
mybatis是一個(gè)優(yōu)秀的基于 java 的持久層框架,它內(nèi)部封裝了 jdbc拇砰,使開發(fā)者只需要關(guān)注 sql語句本身, 而不需要花費(fèi)精力去處理加載驅(qū)動雏门、創(chuàng)建連接柳畔、創(chuàng)建 statement 等繁雜的過程馍管。**
mybatis通過xml 或注解的方式將要執(zhí)行的各種statement配置起來,并通過java對象和statement 中 sql 的動態(tài)參數(shù)進(jìn)行映射生成最終執(zhí)行的 sql 語句薪韩,最后由 mybatis 框架執(zhí)行 sql 并將結(jié)果映射為 java 對象并 返回确沸。
采用 ORM 思想解決了實(shí)體和數(shù)據(jù)庫映射的問題,對 jdbc進(jìn)行了封裝俘陷,屏蔽了 jdbc api 底層訪問細(xì)節(jié)罗捎,使我 們不用與 jdbc api 打交道,就可以完成對數(shù)據(jù)庫的持久化操作拉盾。
2.MyBatis入門之配置文件實(shí)現(xiàn)
2.1.pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yuan</groupId>
<artifactId>note_mybaties_01</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!-- mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!-- 單元測試-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<!-- 數(shù)據(jù)庫-->
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<!-- 日志-->
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>
</project>
2.2.編寫實(shí)體類
路徑com/yuan/doman/User.java
package com.yuan.doman;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable{
private Integer id;
/**
* 用戶姓名
*/
private String username;
/**
* 用戶生日
*/
private Date birthday;
/**
* 用戶性別
*/
private String sex;
/**
* 用戶地址
*/
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
2.3.編寫持久層接口
路徑:com/yuan/dao/UserDao.java
package com.yuan.dao;
import com.yuan.doman.User;
import java.util.List;
/**
* 桨菜,用戶的持久層接口
*/
public interface UserDao {
List<User> findAll();
}
2.4.編寫映射文件
路徑:resources/yuan/dao/UserDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yuan.dao.UserDao">
<!--findAll方法-->
<select id="findAll" resultType="com.yuan.doman.User">
SELECT * FROM USER
</select>
</mapper>
2.5.編寫配置文件
路徑:resources/SqlMapConfig .xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--環(huán)境配置-->
<!--默認(rèn)環(huán)境-->
<environments default="mysql">
<!--mysql環(huán)境-->
<environment id="mysql">
<!--JDBC事務(wù)-->
<transactionManager type="JDBC"></transactionManager>
<!--POOLED連接池-->
<dataSource type="POOLED">
<!--四大參數(shù)-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///數(shù)據(jù)庫名"/>
<property name="username" value="數(shù)據(jù)庫賬戶"/>
<property name="password" value="數(shù)據(jù)庫密碼"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/yuan/dao/UserDao.xml"/>
</mappers>
</configuration>
2.6.注意事項(xiàng)
第一個(gè):創(chuàng)建UserDao.xml 和 UserDao.java時(shí)名稱是為了和我們之前的知識保持一致。
在Mybatis中它把持久層的操作接口名稱和映射文件也叫做:Mapper
所以:UserDao 和 UserMapper是一樣的
第二個(gè):在idea中創(chuàng)建目錄的時(shí)候盾剩,它和包是不一樣的
包在創(chuàng)建時(shí):com.yuan.dao它是三級結(jié)構(gòu)
目錄在創(chuàng)建時(shí):com.yuan.dao是一級目錄
第三個(gè):mybatis的映射配置文件位置必須和dao接口的包結(jié)構(gòu)相同
第四個(gè):映射配置文件的mapper標(biāo)簽namespace屬性的取值必須是dao接口的全限定類名
第五個(gè):映射配置文件的操作配置(select)雷激,id屬性的取值必須是dao接口的方法名
第六個(gè):當(dāng)我們遵從了第三,四告私,五點(diǎn)之后屎暇,我們在開發(fā)中就無須再寫dao的實(shí)現(xiàn)類。
2.7.測試
package com.yuan.test;
import com.yuan.dao.UserDao;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class UserDaoTest {
InputStream is = null;
SqlSessionFactory factory = null;
SqlSession session = null;
@Before
public void init() throws IOException {
//讀取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//創(chuàng)建會話工廠
factory = new SqlSessionFactoryBuilder().build(is);
//生產(chǎn)SQLSession對象
session = factory.openSession();
}
@After
public void close() throws IOException {
session.commit();
session.close();
is.close();
}
@Test
public void findAllTest(){
UserDao userDao = session.getMapper(UserDao.class);
System.out.println(userDao.findAll());
}
}
3.MyBatis入門之注解實(shí)現(xiàn)
3.1.pom.xml
與2.1相同
3.2.編寫實(shí)體類
與2.2相同
3.3.編寫持久層接口
package com.yuan.dao;
import com.yuan.doman.User;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* 用戶的持久層接口
*/
public interface UserDao {
@Select("SELECT * FROM USER")
List<User> findAll();
}
3.4.編寫配置文件
與2.5大致相同【唯一不同】
<mappers> <mapper class="com.yuan.dao.UserDao"/> </mappers>
3.5.測試
與2.7相同
4.小結(jié)1
開發(fā)時(shí)要不要寫持久層實(shí)現(xiàn)類驻粟?
不寫根悼,怎么簡單怎么來凶异,怎么快怎么來,怎么好維護(hù)怎么來
開發(fā)時(shí)用注解還是用xml文件挤巡?
老項(xiàng)目一般用xml剩彬,最近項(xiàng)目都是注解開發(fā),同一個(gè)Dao接口不能既用注解又用xml
項(xiàng)目中如何獲取路徑
一般使用兩種方法
1.使用類加載器矿卑,它只能讀取類路徑的配置文件
2.使用servletContext的getRealPath()方法
5.基于配置文件的增刪改查
5.1.持久層接口
package com.yuan.dao;
import com.yuan.doman.User;
import java.util.List;
/**
* 用戶的持久層接口
*/
public interface UserDao {
/**
* 全查User
*
* @return
*/
List<User> findAll();
/**
* 查詢UserId
*
* @param uid
*/
User findById(Integer uid);
/**
* 查詢UserName
*
* @param username
*/
List<User> findLikeName(String username);
/**
* 查詢User總數(shù)
*
* @return int
*/
Integer findTotalId();
/**
* 新增User
*
* @param user
*/
void save(User user);
/**
* 修改User
*
* @param user
*/
void update(User user);
/**
* 刪除User
*
* @param uid
*/
void delete(Integer uid);
}
5.2.映射文件
<?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.yuan.dao.UserDao">
<!--查詢?nèi)縐ser-->
<select id="findAll" resultType="com.yuan.doman.User">
SELECT * FROM USER
</select>
<!--查詢單個(gè)User-->
<select id="findById" resultType="com.yuan.doman.User" parameterType="int">
SELECT * FROM USER WHERE ID = #{id}
</select>
<!--Like查詢UserName-->
<select id="findLikeName" resultType="com.yuan.doman.User" parameterType="string">
SELECT * FROM USER WHERE USERNAME LIKE #{uname};
</select>
<!--查詢User總數(shù)-->
<select id="findTotalId" resultType="int">
SELECT count(*) FROM USER
</select>
<!--新增User-->
<insert id="save" parameterType="com.yuan.doman.User">
<!--拿到返回的ID-->
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
SELECT Last_INSERT_ID();
</selectKey>
INSERT INTO USER(username,birthday,sex, address) VALUE (#{username},#{birthday},#{sex},#{address});
</insert>
<!-- 更新User根據(jù)ID-->
<update id="update" parameterType="com.yuan.doman.User">
UPDATE USER SET USERNAME = #{username} WHERE ID = #{id}
</update>
<!--刪除User根據(jù)ID-->
<update id="delete" parameterType="Integer">
delete FROM user WHERE ID = #{uid}
</update>
</mapper>
5.3.測試文件
package com.yuan.test;
import com.yuan.dao.UserDao;
import com.yuan.doman.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
public class UserDaoTest {
InputStream is = null;
SqlSessionFactory factory = null;
SqlSession session = null;
/**
* 在Test
* @throws IOException
*/
@Before
public void init() throws IOException {
//讀取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//創(chuàng)建會話工廠
factory = new SqlSessionFactoryBuilder().build(is);
//生產(chǎn)SQLSession對象
session = factory.openSession();
}
@After
public void close() throws IOException {
session.commit();
session.close();
is.close();
}
@Test
public void findAllTest(){
UserDao userDao = session.getMapper(UserDao.class);
System.out.println(userDao.findAll());
}
@Test
public void testSave() {
UserDao userDao = session.getMapper(UserDao.class);
User user = new User();
user.setUsername("GiaoWin");
user.setBirthday(new Date());
user.setSex("男");
user.setAddress("張家口");
System.out.println("保存前 = " + user);
userDao.save(user);
System.out.println("保存后 = " + user);
}
@Test
public void testUpdate() {
UserDao userDao = session.getMapper(UserDao.class);
User user = new User();
user.setUsername("AKUMA");
user.setId(49);
userDao.update(user);
}
@Test
public void testDelete() {
UserDao userDao = session.getMapper(UserDao.class);
userDao.delete(49);
}
@Test
public void testfindById() {
UserDao userDao = session.getMapper(UserDao.class);
System.out.println(userDao.findById(46));
}
@Test
public void testfindAll() {
UserDao userDao = session.getMapper(UserDao.class);
System.out.println(userDao.findAll());
}
@Test
public void testfindLikeName() {
UserDao userDao = session.getMapper(UserDao.class);
userDao.findLikeName("%王%");
}
@Test
public void testfindTotalUser() {
UserDao userDao = session.getMapper(UserDao.class);
System.out.println("+++++++++++++++++++++++"+userDao.findTotalId()+"++++++++++++++++++++++++");
}
}
6.小結(jié)2
#{}h和${}有什么區(qū)別
前者是占位符?喉恋,后者是字符串拼接,會受到SQL注入攻擊
如何拿到保存時(shí)的ID值:
<!--拿到返回的ID-->
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
SELECT Last_INSERT_ID();
</selectKey>
多個(gè)查詢條件組成一個(gè)對象作為參數(shù)怎么解決母廷?
用一個(gè)包裝類給他們包裝一下轻黑,然后通過NGOL表達(dá)式逐一拿出。
數(shù)據(jù)庫與實(shí)體類中的列名不一致怎么解決琴昆?
1.改正
2.用別名【提升速度】
3.用resultMap【提升開發(fā)速度】
<resultMap id="userMap" type="com.yuan.doman.User">
<!-- 主鍵字段的對應(yīng) -->
<id property="Java中的屬性" column="數(shù)據(jù)庫中的列"/>
<!-- 非主鍵字段的對應(yīng) -->
<result property="Java中的屬性" column="數(shù)據(jù)庫中的列"/>
</resultMap>
<!-- 使用 -->
<select id="findAll" resultMap="userMap">
SELECT * FROM USER
</select>
SqlMapConfig.xml配置文件常用標(biāo)簽
<!—外部配置文件-->
<propertys>
<property source="文件路徑"/>
</propertys>
<!--別名映射-->
<typeAliases>
<!--引入映射包就不用其他的了-->
<package name="com.yuan.doman " />
<typeAlias type="com.yuan.doman.User" alias="user"/>
</typeAliases>
如何查看源碼
用Ctrl+Alt+B跟蹤到底層實(shí)現(xiàn)【IDEA工具】
代理Dao的實(shí)現(xiàn)源碼追蹤
/**
- Copyright 2009-2017 the original author or authors.
*
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
*
- http://www.apache.org/licenses/LICENSE-2.0
*
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
*/
package org.apache.ibatis.binding;
import org.apache.ibatis.annotations.Flush;
import org.apache.ibatis.annotations.MapKey;
import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.ParamNameResolver;
import org.apache.ibatis.reflection.TypeParameterResolver;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
/**
- @author Clinton Begin
- @author Eduardo Macarron
- @author Lasse Voss
*/
public class MapperMethod {
private final SqlCommand command;
private final MethodSignature method;
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
this.command = new SqlCommand(config, mapperInterface, method);
this.method = new MethodSignature(config, mapperInterface, method);
}
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
switch (command.getType()) {
case INSERT: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
case DELETE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
case SELECT:
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
result = executeForMap(sqlSession, args);
} else if (method.returnsCursor()) {
result = executeForCursor(sqlSession, args);
} else {
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + command.getName());
}
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
}
7.MyBatis連接池
使用了同步代碼快保障了每一個(gè)線程拿到的是不同的連接氓鄙,是一個(gè)線程安全的集合。
主配置文件SqlMapConfig.xml中的dataSource標(biāo)簽业舍,type屬性就是表示采用何種連接池方式抖拦。
? 1.POOLED
? 從池中獲取連接,采用傳統(tǒng)的javax.sql.DataSource規(guī)范中的連接池舷暮,mybatis中有針對規(guī)范的實(shí)現(xiàn)
? 2.UNPOOLE
? 每次new一個(gè)連接态罪,采用傳統(tǒng)的獲取連接的方式,雖然也實(shí)現(xiàn)Javax.sql.DataSource接口下面,但是并沒有使用池的思想向臀。
? 3.JNDI
采用服務(wù)器提供的JNDI技術(shù)實(shí)現(xiàn),來獲取DataSource對象诸狭,不同的服務(wù)器所能拿到DataSource是不一樣券膀。
注意:如果不是web或者maven的war工程,是不能使用的驯遇。
tomcat服務(wù)器,采用連接池就是dbcp連接池芹彬。
8.MyBatis事務(wù)
//生產(chǎn)SQLSession對象 session = factory.openSession(true);
它是通過sqlsession對象的commit方法和rollback方法實(shí)現(xiàn)事務(wù)的提交和回滾
session.commit();
session.close();
9.動態(tài)SQL
<where>
<if>
<foreach>
這是一個(gè)根據(jù)條件查詢的語句,但是條件有可能哦呦有可能沒有就要使用動態(tài)SQL標(biāo)簽了 [ids 是Vo類里的屬性名]
<include><sql id="defUser"> SELECT * FROM USER </sql>
<select id="findUserIn" resultType="User" parameterType="QueryVo">
<include refid="defUser"/>
<where>
<if test="#{ids!= null and ids.size > 0 }">
id in
<foreach collection="ids " open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</if>
</where>
</select>
10.MyBatis表與表之間的關(guān)系
10.1.多對一【包括一對一】(Account==>User)
10.1.1.實(shí)體類
package com.yuan.doman;
import java.util.Date;
import java.util.List;
public class User {
private Integer id;
/**
* 用戶姓名
*/
private String username;
/**
* 用戶生日
*/
private Date birthday;
/**
* 用戶性別
*/
private String sex;
/**
* 用戶地址
*/
private String address;
/**
*角色下的賬戶集合
* @return
*/
private List<Account> roles;
//Get() Set() 方法
}
10.1.2.映射文件
<?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.yuan.dao.AccountDao">
<!--配置一對多關(guān)系的resultMap-->
<resultMap id="accountUserMap" type="account">
<!--id是唯一標(biāo)識-->
<!--type是對應(yīng)的實(shí)體類-->
<id column="aid" property="id"/>
<!--id是主鍵-->
<!--result是普通列-->
<!--column是數(shù)據(jù)庫列名-->
<!--property是屬性名-->
<result column="uid" property="uid"/>
<result column="money" property="money"/>
<!--association對應(yīng)主表關(guān)系-->
<!--property表示外鍵屬性是User-->
<!--column表示用uid字段來獲取-->
<!--javaType表示返回的Java類型是什么-->
<association property="user" column="uid" javaType="com.yuan.doman.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="birthday" property="birthday"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
</resultMap>
<!--查詢?nèi)緼ccount-->
<select id="findAll" resultMap="accountUserMap">
SELECT a.id as AID,a.UID,a.MONEY,u.* from account a,user u where u.id = a.UID
</select>
</mapper>
10.1.3.測試
package com.yuan.test;
import com.yuan.dao.AccountDao;
import com.yuan.doman.Account;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class AccountDaoTest {
InputStream is = null;
SqlSessionFactory factory = null;
SqlSession session = null;
AccountDao accountDao = session.getMapper(AccountDao.class);
@Before
public void init() throws IOException {
//讀取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//創(chuàng)建會話工廠
factory = new SqlSessionFactoryBuilder().build(is);
//生產(chǎn)SQLSession對象
session = factory.openSession();
}
@After
public void close() throws IOException {
session.commit();
session.close();
is.close();
}
@Test
public void finAllAccount() {
List<Account> accountAll = accountDao.findAll();
for (Account account : accountAll) {
System.out.println("---------------");
System.out.println("account = " + account);
System.out.println(account.getUser());
}
}
}
10.2.一對多(User==>Account)
10.2.1.實(shí)體類
package com.yuan.doman;
import java.util.Date;
import java.util.List;
public class User {
private Integer id;
/**
* 用戶姓名
*/
private String username;
/**
* 用戶生日
*/
private Date birthday;
/**
* 用戶性別
*/
private String sex;
/**
* 用戶地址
*/
private String address;
/**
*角色下的賬戶集合
* @return
*/
private List<Account> roles;
//Get() Set() 方法
}
10.2.2.映射文件
<?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.yuan.dao.UserDao">
<sql id="defUser">
SELECT u.*,a.ID as aid,A.MONEY
FROM USER u LEFT JOIN ACCOUNT a
ON a.UID = u.id
</sql>
<resultMap id="userAccountMap" type="user">
<id property="id" column="id"></id>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<!--賬戶定義集合-->
<!--property 集合屬性名-->
<!--ofType 集合的泛型-->
<collection property="accounts" ofType="com.yuan.doman.Account">
<id column="aid" property="id"/>
<result column="uid" property="uid"/>
<result column="money" property="money"/>
</collection>
</resultMap>
<!--查詢?nèi)縐ser-->
<select id="findAll" resultMap="userAccountMap">
<include refid="defUser"/>
</select>
<!--根據(jù)ID查詢User-->
<select id="findById" resultMap="userAccountMap" parameterType="int">
<include refid="defUser"/>
<where>
ID = #{id}
</where>
</select>
</mapper>
10.2.3.測試
package com.yuan.test;
import com.yuan.dao.UserDao;
import com.yuan.doman.Account;
import com.yuan.doman.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class UserDaoTest {
InputStream is = null;
SqlSessionFactory factory = null;
SqlSession session = null;
@Before
public void init() throws IOException {
//讀取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//創(chuàng)建會話工廠
factory = new SqlSessionFactoryBuilder().build(is);
//生產(chǎn)SQLSession對象
session = factory.openSession();
}
@After
public void close() throws IOException {
session.commit();
session.close();
is.close();
}
@Test
public void finAllAccount() {
UserDao userDao = session.getMapper(UserDao.class);
List<User> userAccounts = userDao.findAll();
for (User userAccount : userAccounts) {
System.out.println("------------------------");
System.out.println("userAccount = " + userAccount);
if (!(userAccount.getAccounts().size()<=0)) {
for (Account account : userAccount.getAccounts()) {
System.out.println("account = " + account);
}
}
}
}
}
10.3.多對多(User<===>Role)
10.3.1.實(shí)體類
package com.yuan.doman;
import java.util.List;
public class Role {
private Integer id;
private String role_name;
private String role_desc;
/**
* 角色對應(yīng)的賬戶結(jié)合
*/
private List<User> users;
//Get() Set() 方法
}
package com.yuan.doman;
import java.util.Date;
import java.util.List;
public class User{
private Integer id;
/**
* 用戶姓名
*/
private String username;
/**
* 用戶生日
*/
private Date birthday;
/**
* 用戶性別
*/
private String sex;
/**
* 用戶地址
*/
private String address;
/**
*角色下的賬戶集合
* @return
*/
private List<Role> roles;
//Get() Set() 方法
}
10.3.2.映射文件
<?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.yuan.dao.RoleDao">
<resultMap id="roleUserMap" type="role">
<id property="id" column="rid"></id>
<result property="role_name" column="role_name"/>
<result property="role_desc" column="role_desc"/>
<collection property="users" ofType="user">
<id property="id" column="UID"></id>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
</collection>
</resultMap>
<!--查詢?nèi)縐ser-->
<select id="findAll" resultMap="roleUserMap">
SELECT
r.id as rid
,r.ROLE_NAME
,r.ROLE_DESC
,u.id AS UID
,u.username
,u.sex
,u.address
,u.birthday
from role r
LEFT JOIN user_role ur ON r.ID = ur.RID
LEFT JOIN user u ON u.id = ur.UID
</select>
<!--根據(jù)ID查詢User-->
<select id="findById" resultMap="roleUserMap" parameterType="int">
</select>
</mapper>
<?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.yuan.dao.UserDao">
<resultMap id="userRolestMap" type="user">
<id property="id" column="uid"></id>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<collection property="roles" ofType="role">
<id property="id" column="rid"></id>
<result property="role_name" column="role_name"/>
<result property="role_desc" column="role_desc"/>
</collection>
</resultMap>
<!--查詢?nèi)縐ser-->
<select id="findAll" resultMap="userRolestMap">
SELECT
u.id AS UID
,u.username
,u.sex
,u.address
,u.birthday
,r.id as rid
,r.ROLE_NAME
,r.ROLE_DESC
from user u
LEFT JOIN user_role ur ON u.ID = ur.UID
LEFT JOIN role r ON r.ID = ur.RID
</select>
<!--根據(jù)ID查詢User-->
<select id="findById" resultMap="userRolestMap" parameterType="int">
</select>
</mapper>
10.3.3.測試
package com.yuan.test;
import com.yuan.dao.RoleDao;
import com.yuan.doman.Role;
import com.yuan.doman.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class RoleDaoTest {
InputStream is = null;
SqlSessionFactory factory = null;
SqlSession session = null;
RoleDao roleDao = null;
@Before
public void init() throws IOException {
//讀取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//創(chuàng)建會話工廠
factory = new SqlSessionFactoryBuilder().build(is);
//生產(chǎn)SQLSession對象
session = factory.openSession();
roleDao = session.getMapper(RoleDao.class);
}
@After
public void close() throws IOException {
session.commit();
session.close();
is.close();
}
@Test
public void finAll() {
List<Role> roles = roleDao.findAll();
for (Role role : roles) {
System.out.println("-----------------");
System.out.println("role = " + role);
if(!(role.getUsers().size()<=0)){
for (User user : role.getUsers()) {
System.out.println("user = " + user);
}
}
}
}
}
package com.yuan.test;
import com.yuan.dao.UserDao;
import com.yuan.doman.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class UserDaoTest {
InputStream is = null;
SqlSessionFactory factory = null;
SqlSession session = null;
UserDao userDao = null;
@Before
public void init() throws IOException {
//讀取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//創(chuàng)建會話工廠
factory = new SqlSessionFactoryBuilder().build(is);
//生產(chǎn)SQLSession對象
session = factory.openSession();
userDao = session.getMapper(UserDao.class);
}
@After
public void close() throws IOException {
session.commit();
session.close();
is.close();
}
@Test
public void finAllAccount() {
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println("user = " + user);
}
}
}
11.MyBatis表與表之間的關(guān)系【注解實(shí)現(xiàn)】
11.1.pom.xml
參考3.1
11.2.編寫實(shí)體類
11.2.1.User.java
package com.yuan.doman;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
public class User implements Serializable {
private Integer id;
/**
* 用戶姓名
*/
private String username;
/**
* 用戶生日
*/
private Date birthday;
/**
* 用戶性別
*/
private String sex;
/**
* 用戶地址
*/
private String address;
/**
* 用戶下的賬戶信息
*/
private List<Account> accounts;
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
/**
*用戶下的角色集合
* @return
*/
private List<Role> roles;
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
11.2.2.Account.java
package com.yuan.doman;
import java.io.Serializable;
public class Account implements Serializable {
private Integer id;
/**
* 用戶Id
*/
private Integer uid;
/**
* 賬戶余額
*/
private Double money;
/**
* 所屬用戶【這個(gè)數(shù)據(jù)庫中表沒有】
*/
private User user;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
", user=" + user +
'}';
}
}
11.2.3.Role.java
package com.yuan.doman;
import java.io.Serializable;
import java.util.List;
public class Role implements Serializable {
private Integer id;
/**
* 角色名
*/
private String role_name;
/**
* 角色權(quán)限
*/
private String role_desc;
/**
* 角色對應(yīng)的賬戶結(jié)合
*/
private List<User> users;
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getRole_name() {
return role_name;
}
public void setRole_name(String role_name) {
this.role_name = role_name;
}
public String getRole_desc() {
return role_desc;
}
public void setRole_desc(String role_desc) {
this.role_desc = role_desc;
}
@Override
public String toString() {
return "Role{" +
"id=" + id +
", role_name='" + role_name + '\'' +
", role_desc='" + role_desc + '\'' +
'}';
}
}
11.3.編寫持久層接口
11.3.1.UserDao.java
package com.yuan.dao;
import com.yuan.doman.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* 叉庐,用戶的持久層接口
*/
public interface UserDao {
/**
* 查詢所有用戶
*
* @return
*/
@Select("select * from user")
@Results(
id = "userMap",
value = {
@Result(id = true, column = "id", property = "id"),
@Result(column = "username", property = "username"),
@Result(column = "sex", property = "sex"),
@Result(column = "address", property = "address"),
@Result(column = "birthday", property = "birthday")
}
)
List<User> findAll();
/**
* 根據(jù) id 查詢一個(gè)用戶
*
* @param userId
* @return
*/
@Select("select * from user where id = #{uid} ")
@ResultMap("userMap")
User findById(Integer userId);
/**
* 保存操作
*
* @param user
* @return
*/
@Insert("insert into user(username,sex,birthday,address)values(#{username},#{sex},#{birthday},#{address} )")
@SelectKey(
keyColumn = "id",
keyProperty = "id",
resultType = Integer.class,
before = false,
statement = {"select last_insert_id()"}
)
int saveUser(User user);
/**
* 更新操作
*
* @param user
* @return
*/
@Update("update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id =#{id} ")
int updateUser(User user);
/**
* 刪除用戶
*
* @param userId
* @return
*/
@Delete("delete from user where id = #{uid} ")
int deleteUser(Integer userId);
/**
* 查詢使用聚合函數(shù)
*
* @return
*/
@Select("select count(*) from user ")
int findTotal();
/**
* 模糊查詢
*
* @param name
* @return
*/
@Select("select * from user where username like #{username} ")
List<User> findByName(String name);
}
11.3.2.AccountDao.java
package com.yuan.dao;
import com.yuan.doman.Account;
import java.util.List;
public interface AccountDao {
/**
* 查詢所有賬戶
* @return
*/
List<Account> findAll();
/**
* 查詢所有賬戶
* @param aid
* @return
*/
Account findByUid(Integer aid);
}
11.3.3.RoleDao.java
package com.yuan.dao;
import com.yuan.doman.Role;
import com.yuan.doman.User;
import java.util.List;
/**
* 舒帮,用戶的持久層接口
*/
public interface RoleDao {
/**
* 全查User
*
* @return
*/
List<Role> findAll();
/**
* 查詢UserId
*
* @param rid
*/
Role findById(Integer rid);
}
11.4.編寫配置文件
<?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>
<!--引入外部配置文件-->
<properties resource="jdbc.properties">
</properties>
<settings>
<!-- 延遲加載的全局開關(guān) 默認(rèn)關(guān)閉 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- <setting name="aggressiveLazyLoading" value="true"/>-->
</settings>
<!--別名包-->
<typeAliases>
<package name="com.yuan.doman"/>
</typeAliases>
<!--配置環(huán)境-->
<environments default="def">
<!--配置默認(rèn)環(huán)境-->
<environment id="def">
<!--配置JDBC事務(wù)-->
<transactionManager type="JDBC"></transactionManager>
<!--配置POOLED連接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<mappers>
<!--引入映射文件-->
<package name="com.yuan.dao"/>
</mappers>
</configuration>
11.5.測試
package com.yuan.test;
import com.yuan.dao.UserDao;
import com.yuan.doman.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class UserDaoTest {
InputStream is = null;
SqlSessionFactory factory = null;
SqlSession session = null;
UserDao userDao = null;
@Before
public void init() throws IOException {
//讀取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//創(chuàng)建會話工廠
factory = new SqlSessionFactoryBuilder().build(is);
//生產(chǎn)SQLSession對象
session = factory.openSession();
userDao = session.getMapper(UserDao.class);
}
@After
public void close() throws IOException {
session.commit();
session.close();
is.close();
}
@Test
public void finAllTest() {
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println("user = " + user);
}
}
@Test
public void findByIdTest() {
User user = userDao.findById(61);
System.out.println(user);
}
@Test
public void saveUserTest() {
final User user = new User();
user.setUsername("GiaoWin");
System.out.println(user.getUsername()+"------------");
userDao.saveUser(user);
System.out.println(user.getId()+"------------");
}
@Test
public void updateUserTest() {
final User user = new User();
user.setId(61);
user.setUsername("GiaoWinner");
userDao.updateUser(user);
System.out.println(user.getUsername()+"------------");
}
@Test
public void deleteUserTest() {
System.out.println(userDao.deleteUser(61));
}
@Test
public void findTotalTest() {
System.out.println(userDao.findTotal());
}
@Test
public void findByNameTest() {
List<User> users = userDao.findByName("Giao%");
for (User user : users) {
System.out.println("user = " + user);
}
}
}
11.6多對一
這里只有接口文件有和測試文件變化
11.6.1.接口
UserDao.java
package com.yuan.dao;
import com.yuan.doman.User;
import org.apache.ibatis.annotations.*;
@CacheNamespace
public interface UserDao {
/**
* 根據(jù)用戶Id返回該用戶
* @param uid
* @return
*/
@Select("select * from user where id = #{id}")
User findById(Integer uid);
}
AccountDao.java
package com.yuan.dao;
import com.yuan.doman.Account;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
public interface AccountDao {
/**
* 查詢賬戶以及所屬用戶
* @return
*/
@Select("select * from account")
@Results(value = {
@Result(id = true,column = "id",property = "id"),
@Result(column = "uid",property = "user",
one = @One(select = "com.yuan.dao.UserDao.findById",
fetchType = FetchType.EAGER)
)
})
List<Account> findAll();
}
11.6.2.測試
package com.yuan.test;
import com.yuan.dao.AccountDao;
import com.yuan.doman.Account;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class AccountTest {
InputStream in;
SqlSessionFactory factory;
SqlSession session;
AccountDao accountDao;
@Before
public void before() throws IOException {
//讀取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//生成Session工廠
factory = new SqlSessionFactoryBuilder().build(in);
//生產(chǎn)Session對象
session = factory.openSession();
//獲取Dao對象
accountDao = session.getMapper(AccountDao.class);
}
@After
public void after() throws IOException {
session.commit();
session.close();
in.close();
}
/**
* 一對一查詢
* @throws IOException
*/
@Test
public void findAccountAllTest() {
List<Account> accountAll = accountDao.findAll();
for (Account account : accountAll) {
System.out.println("account = " + account);
}
}
}
11.7.多對一
11.7.1.接口
UserDao.java
package com.yuan.dao;
import com.yuan.doman.User;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
//開啟二級緩存
@CacheNamespace(blocking = true)
public interface UserDao {
/**
* 查詢用戶及其下屬賬戶
* @return
*/
@Select("select * from user")
@Results(value = {
@Result(id = true,column = "id",property = "id"),
@Result(column = "id",property = "accounts",
//配置一對多
many = @Many(select = "com.yuan.dao.AccountDao.findByUid",
//配置延遲加載
fetchType = FetchType.LAZY
))
})
List<User> findAll();
}
AccountDao.java
package com.yuan.dao;
import com.yuan.doman.Account;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface AccountDao {
/**
* 根據(jù)用戶Id查詢 賬戶信息
* @param uid
* @return
*/
@Select("select * from account where uid = #{uid}")
List<Account> findByUid(Integer uid);
}
11.7.2.測試
package com.yuan.test;
import com.yuan.dao.AccountDao;
import com.yuan.dao.UserDao;
import com.yuan.doman.Account;
import com.yuan.doman.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class UserTest {
InputStream in;
SqlSessionFactory factory;
SqlSession session;
UserDao userDao;
@Before
public void before() throws IOException {
//讀取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//生成Session工廠
factory = new SqlSessionFactoryBuilder().build(in);
//生產(chǎn)Session對象
session = factory.openSession();
//獲取Dao對象
userDao = session.getMapper(UserDao.class);
}
@After
public void after() throws IOException {
session.commit();
session.close();
in.close();
}
/**
* 一對多查詢
*/
@Test
public void findUserAllTest() {
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println("user = " + user);
List<Account> accounts = user.getAccounts();
System.out.println("accounts = " + accounts);
}
}
}
11.7常用注解
@Insert:實(shí)現(xiàn)新增
@Update:實(shí)現(xiàn)更新
@Delete:實(shí)現(xiàn)刪除
@Select:實(shí)現(xiàn)查詢
@Result:實(shí)現(xiàn)結(jié)果集封裝
@Results:可以與@Result 一起使用,封裝多個(gè)結(jié)果集
@ResultMap:實(shí)現(xiàn)引用@Results 定義的封裝
@One:實(shí)現(xiàn)一對一結(jié)果集封裝
@Many:實(shí)現(xiàn)一對多結(jié)果集封裝
@SelectProvider: 實(shí)現(xiàn)動態(tài) SQL 映射
@CacheNamespace:實(shí)現(xiàn)注解二級緩存的使用
11.6復(fù)雜注解
@Results 注解
代替的是標(biāo)簽<resultMap>
該注解中可以使用單個(gè)@Result 注解陡叠,也可以使用@Result 集合 @Results({@Result()玩郊,@Result()})或@Results(@Result())
@Resutl 注解
代替了 <id>標(biāo)簽和<result>標(biāo)簽
@Result 中 屬性介紹:
id 是否是主鍵字段
column 數(shù)據(jù)庫的列名
property 需要裝配的屬性名
one 需要使用的@One 注解(@Result(one=@One)()))
many 需要使用的@Many 注解(@Result(many=@many)()))
@One 注解(一對一)
代替了<assocation>標(biāo)簽,是多表查詢的關(guān)鍵枉阵,在注解中用來指定子查詢返回單一對象译红。
@One 注解屬性介紹:
select 指定用來多表查詢的
sqlmapper fetchType 會覆蓋全局的配置參數(shù) lazyLoadingEnabled。
使用格式:
@Result(column=" ",property="",one=@One(select=""))
@Many 注解(多對一)
代替了<Collection>標(biāo)簽,是是多表查詢的關(guān)鍵兴溜,在注解中用來指定子查詢返回對象集合侦厚。
注意:
聚集元素用來處理“一對多”的關(guān)系耻陕。需要指定映射的 Java 實(shí)體類的屬性,屬性的 javaType (一般為 ArrayList)但是注解中可以不定義刨沦;
使用格式:
@Result(property="",column="",many=@Many(select=""))
12.MyBatis的延遲加載
1.一對一(多對一)延遲加載
<resultMap id="accountUserMap" type="account">
<id property="id" column="id"/>
<result property="uid" column="uid"/>
<result property="money" column="money"/>
<!--
一(多)對一的關(guān)系映射:配置封裝user的內(nèi)容
select屬性指定的內(nèi)容:查詢用戶的唯一標(biāo)識:
column屬性指定的內(nèi)容:用戶根據(jù)id查詢時(shí)诗宣,所需要的參數(shù)的值
-->
<association
property="users"
column="uid"
javaType="user"
select="com.yuan.dao.UserDao.findById"
/>
</resultMap>
<!--查詢?nèi)緼ccount-->
<select id="findAll" resultMap="accountUserMap">
SELECT * FROM ACCOUNT
</select>
2.一對多延遲加載
<resultMap id="userAccountMap" type="user">
<id property="id" column="id"></id>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<!--賬戶定義集合-->
<!--property 集合屬性名-->
<!--ofType 集合的泛型-->
<!--column 用不到不寫 現(xiàn)在的作用是把用戶的ID作為參數(shù)傳到賬戶的查詢參數(shù)(一對多)-->
<!--select 用的時(shí)候調(diào)用賬戶配置文件中的查詢方法-->
<collection
property="accounts"
column = "id"
select="com.yuan.dao.AccountDao.findByUid"
ofType="account"/>
</resultMap>
<!--查詢?nèi)縐ser-->
<select id="findAll" resultMap="userAccountMap">
SELECT * FROM USER
</select>
13.MyBatis的緩存
像大多數(shù)的持久化框架一樣,Mybatis 也提供了緩存策略想诅,通過緩存策略來減少數(shù)據(jù)庫的查詢次數(shù)召庞,從而提 高性能。 Mybatis 中緩存分為一級緩存来破,二級緩存裁眯。
13.1.一級緩存
它指的是Mybatis中SqlSession對象的緩存。
當(dāng)我們執(zhí)行查詢之后讳癌,查詢的結(jié)果會同時(shí)存入到SqlSession為我們提供一塊區(qū)域中。
該區(qū)域的結(jié)構(gòu)是一個(gè)Map存皂。當(dāng)我們再次查詢同樣的數(shù)據(jù)晌坤,mybatis會先去sqlsession中
查詢是否有,有的話直接拿出來用旦袋。
當(dāng)SqlSession對象消失時(shí)骤菠,mybatis的一級緩存也就消失了。
一級緩存是 SqlSession 級別的緩存疤孕,只要 SqlSession 沒有 flush 或 close商乎,它就存在。 默認(rèn)開啟噠祭阀!
當(dāng)調(diào)用 SqlSession 的修改鹉戚,添加,刪除专控,commit()抹凳,close()等方法時(shí),就會清空一級緩存伦腐。
13.2.二級緩存
它指的是Mybatis中SqlSessionFactory對象的緩存赢底。由同一個(gè)SqlSessionFactory對象創(chuàng)建的SqlSession共享其緩存。
二級緩存(默認(rèn)開啟)的使用步驟:
第一步:讓Mybatis框架支持二級緩存(在SqlMapConfig.xml中配置)
<!--開啟二級緩存-->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
第二步:讓當(dāng)前的映射文件支持二級緩存(在IUserDao.xml中配置)
添加標(biāo)簽<cache/>【在映射文件中添加了這個(gè)標(biāo)簽就完事了】
第三步: 在select標(biāo)簽添加屬性useCache="true"
13.3.注意事項(xiàng)
當(dāng)我們在使用二級緩存時(shí)柏蘑,所緩存的類一定要實(shí)現(xiàn) java.io.Serializable 接口幸冻,這種就可以使用序列化 方式來保存對象。
小結(jié)3
什么是延遲加載
就是在需要用到數(shù)據(jù)時(shí)才進(jìn)行加載咳焚,不需要用到數(shù)據(jù)時(shí)就不加載數(shù)據(jù)洽损。延遲加載也稱懶加載. 好處:先從單表查詢,需要時(shí)再從關(guān)聯(lián)表去關(guān)聯(lián)查詢革半,大大提高數(shù)據(jù)庫性能趁啸,因?yàn)椴樵儐伪硪汝P(guān)聯(lián)查詢多張表速 度要快强缘。
延遲加載的壞處?
因?yàn)橹挥挟?dāng)需要用到數(shù)據(jù)時(shí)不傅,才會進(jìn)行數(shù)據(jù)庫查詢旅掂,這樣在大批量數(shù)據(jù)查詢時(shí),因?yàn)椴樵児ぷ饕惨?時(shí)間访娶,所以可能造成用戶等待時(shí)間變長商虐,造成用戶體驗(yàn)下降。
注解方式如何開啟二級緩存
第一步:配置文件開啟二級緩存
第二步:在接口文件接口名上添加注解@CacheNamespace(blocking = true)