初学mybatis

1.mybatis是什么
持久层框架
前身叫做ibatis
所有的持久层框架
底层代码都是通过JDBC实现的
JDBC是java访问数据库的唯一手段
1.1
持久层
dao层DataAccessObject
数据访问对象层
单一的持久化操作
1.2
框架
别人写好的,我们可以直接拿过来使用的
由其他程序员所封装的一系列的资源
对某些技术的封装
封装成jar、js、css...
简化了我们的开发
1.3
优点
提高代码复用性
是一种支持普通sql操作、存储过程和高级映射的一个ORM框架
几乎消除了所有的jdbc代码,不需要手动设置参数
对于简单映射会帮我们自动映射,会自动将数据库中的查询结果映射成java对象
1.4
ORM
Object Relational Mapping
对象关系映射
是一种程序技术,用于实现面向对象编程语言中不同类型系统的数据之间的转换
类 映射 表
属性 映射 字段
1.5
开发依赖
自己的:mybatisxxx.
jar
数据库的:mysqxxx.
jar/ojdbcx.jar


2.MaBatis配置文件
2.1
configuration配置
主配置文件,只能存在一个
主要配置连接信息、环境信息、总的一些影响到整个工程的配置信息
2.2
mapper配置
可以存在无数个
该配置类似于dao层实现类
针对每一个功能进行配置
sql操作
对象映射
2.3
xml添加dtd约束


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2.4新建带有dtd约束的xml文件

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3.conguration配置
31
environments标签
配置当前工程所使用的所有环境信息
environment标签:每一个环境的配置
transactionManager:事务管理器
    type属性:指定当前管理器的类型,值有两种
        jdbc:使用jdbc的简单事务,开启、提交、回滚
        managed:这个配置啥也不做,它从不关心事务,将事务交给其他框架来处理,例如:spring
dataSource:数据源配置
    type属性:当前数据源的类型,值有三种
        UNPOOLED:简单配置,相当于DriverManager.getConnection(url,username,password),没有使用连接池来处理
        POOLED:带有数据源连接池
        JNDI:向其他容器要连接
    property子标签:配置信息
        name属性:配置的选项
        value属性:选项所对应的值

<environment id="mybatis">
<!‐‐transactionManager:事务管理器type:当前管理器的类型,值有两种‐‐>
    <transactionManager type="jdbc"></transactionManager>
    <dataSource type="UNPOOLED">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&amp;characterEncoding=utf8"/>
        <property name="username" value="root"/>
        <property name="password" value=""/>
    </dataSource>
</environment>


3.2 mappers标签
    注册mapper文件
3.3 typeAliases标签
    typeAlias标签:为某一个对象取一个别名
        type属性:对象的路径名
        Alias属性:该对象的别名
    package标签:扫包,将某个路径下的所有的对象的别名用当前类名代替,最终的别名忽略大小写
        name属性:路径名(不含对象)

<typeAliases>
    <!‐‐ <typeAlias type="entity.User" alias="user"/> ‐‐>
    <package name="entity"/>
</typeAliases>


3.4 properties标签
读取properties

<!‐‐ 指定properties文件所在的位置 ‐‐>
    <properties resource="dataSource.properties"></properties>

<dataSource type="UNPOOLED">
    <property name="driver" value="${driver}"/>
    <property name="url" value="${url}"/>
    <property name="username" value="${username}"/>
    <property name="password" value="${password}"/>
</dataSource>

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&characterEncoding=utf8
username=root
password=

4.第一个Mybatis代码
数据库设计

drop database if exists mybatis;
create database mybatis;
use mybatis;
create table t_user(
    id int primary key auto_increment,
    username varchar(20),
    password varchar(50),
    phone varchar(20),
    address varchar(100)
)engine=Innodb default charset=utf8;

 

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>
<!‐‐
配置多个jdbc环境
通过default属性选择其中一个环境在当前使用
default属性:指向某一个环境的id
‐‐>
<environments default="mybatis">
<!‐‐
配置一个环境
id为当前环境的唯一性标识符
‐‐>
<environment id="mybatis">
<!‐‐
transactionManager:事务管理器
type:当前管理器的类型,值有两种
‐‐>
<transactionManager type="jdbc"></transactionManager>
<dataSource type="UNPOOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?
useUnicode=true&amp;characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</dataSource>
</environment>
<environment id="ajax">
<transactionManager type="jdbc"></transactionManager>
<dataSource type="UNPOOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?
useUnicode=true&amp;characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>
<mappers>
<!‐‐ 注册mapper文件 ‐‐>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>


UserMapper.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" >
<!‐‐ namespace:
可以随便写/必须是某一个值(dao层接口路径名)
不能重复
‐‐>
<!‐‐ <mapper namespace="aa"> ‐‐>
<mapper namespace="dao.UserDao">
<!‐‐ 语句块 ‐‐>
<sql id="userColumn">
id,
username,
password,
phone,
address
</sql>
<!‐‐
select标签:表示执行查询操作
id:方法名,可以随便写,如果有dao层,必须与dao层中方法名一致
parameterType:参数类型,是mybatis中的别名
在mybatis官方文档中,不支持多参数
resultType:返回值类型,指向某一个java对象
‐‐>
<select id="selectById" parameterType="integer" resultType="entity.User">
select <include refid="userColumn"></include>
from t_user
where id = #{id}
</select>
</mapper>

 


Test01.java
package test;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import dao.UserDao;
import entity.User;
public class Test01 {
public static void main(String[] args) {
//用于获取SqlSessionFactory
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//读取配置文件,非常消耗资源
SqlSessionFactory factory = builder.build(Test01.class.getClassLoader().getResourceAsStream("mybatisconfig.
xml"));
//获取会话,持久化管理器
//SqlSession是整个mybatis的核心
//包含一切想要的操作
SqlSession session = factory.openSession();
//方法一:
//参数1:表示的是调用的mapper中的方法名,值为namespace.方法id
//参数2:方法的参数
// User user = session.selectOne("aa.selectById", 1);
// User user = session.selectOne("dao.UserDao.selectById", 1);
//
System.out.println("id:"+user.getId()+",username:"+user.getUsername()+",password:"+user.getPassword()+",phone
:"+user.getPhone()+",address:"+user.getAddress());
//方法二:
UserDao userDao = session.getMapper(UserDao.class);
System.out.println(userDao);
User user = userDao.selectById(1);
System.out.println("id:"+user.getId()+",username:"+user.getUsername()+",password:"+user.getPassword()+",phone
:"+user.getPhone()+",address:"+user.getAddress());
session.close();
}
}


5.mapper配置
51
select标签
执行查询操作
id:方法名,可以随便写,如果有dao层,必须与dao层中方法名一致
parameterType:参数类型,是mybatis中的别名,在mybatis官方文档中,不支持多参数
package test;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import dao.UserDao;
import entity.User;
public class Test01 {
public static void main(String[] args) {
//用于获取SqlSessionFactory
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//读取配置文件,非常消耗资源
SqlSessionFactory factory = builder.build(Test01.class.getClassLoader().getResourceAsStream("mybatisconfig.
xml"));
//获取会话,持久化管理器
//SqlSession是整个mybatis的核心
//包含一切想要的操作
SqlSession session = factory.openSession();
//方法一:
//参数1:表示的是调用的mapper中的方法名,值为namespace.方法id
//参数2:方法的参数
// User user = session.selectOne("aa.selectById", 1);
// User user = session.selectOne("dao.UserDao.selectById", 1);
//
System.out.println("id:"+user.getId()+",username:"+user.getUsername()+",password:"+user.getPassword()+",phone
:"+user.getPhone()+",address:"+user.getAddress());
//方法二:
UserDao userDao = session.getMapper(UserDao.class);
System.out.println(userDao);
User user = userDao.selectById(1);
System.out.println("id:"+user.getId()+",username:"+user.getUsername()+",password:"+user.getPassword()+",phone
:"+user.getPhone()+",address:"+user.getAddress());
session.close();
}
}

resultType:返回值类型,指向某一个java对象
标签体内容:sql语句
<!‐‐
select标签:表示执行查询操作
id:方法名,可以随便写,如果有dao层,必须与dao层中方法名一致
parameterType:参数类型,是mybatis中的别名
在mybatis官方文档中,不支持多参数
resultType:返回值类型,指向某一个java对象
‐‐>
<select id="selectById" parameterType="integer" resultType="entity.User">
select <include refid="userColumn"></include>
from t_user
where id = #{id}
</select>

 

52
sql标签
语句块,可以在其他标签中调用该语句块的内容
id:该语句块的唯一性标识符,供其他语句块调用时使用
标签体内容:语句块中所包含的内容
如何引用:
在其他标签中使用include标签引用
refid:指向某个sql语句块的id
53
insert标签
执行添加操作
id:方法名,可以随便写,如果有dao层,必须与dao层中方法名一致
parameterType:参数类型,是mybatis中的别名,在mybatis官方文档中,不支持多参数
resultType:返回值类型,指向某一个java对象
useGeneratedKeys:保存时是否返回主键
keyProperty:主键所对应的属性
keyColumn:主键所对应的字段,可以不写
标签体内容:sql语句
54
resultMap标签
手动映射
type属性:该结果映射到哪一个对象中
id属性:该resultMap的唯一性标识符
id标签:映射主键
result标签:映射其他字段
property属性:映射的属性名
<sql id="userColumn">
id,
username,
password,
phone,
address
</sql>
<include refid="userColumn"></include>
<!‐‐
insert标签:表示执行添加操作
如果参数时一个对象
则使用#占位符,变量的名称即为当前对象中的属性名
useGeneratedKeys:保存时是否返回主键
keyProperty:主键所对应的属性
keyColumn:主键所对应的字段,可以不写
‐‐>
<insert id="insertUser" parameterType="entity.User" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
insert into
t_user
(username,password,phone,address)
values
(#{username},#{password},#{phone},#{address})
</insert>


column属性:映射的字段名
55
update标签
执行修改操作
id:方法名,可以随便写,如果有dao层,必须与dao层中方法名一致
parameterType:参数类型,是mybatis中的别名,在mybatis官方文档中,不支持多参数
resultType:返回值类型,指向某一个java对象
标签体内容:sql语句
56
delete标签
执行删除操作
id:方法名,可以随便写,如果有dao层,必须与dao层中方法名一致
parameterType:参数类型,是mybatis中的别名,在mybatis官方文档中,不支持多参数
resultType:返回值类型,指向某一个java对象
标签体内容:sql语句
6.log4j
61
是什么
日志管理器
用来记录在操作过程中所产生的一些信息
有价值的日志能够帮助开发人员迅速的找到错误所在的位置
62
如何使用
需要log4j的jar包
需要一个配置文件,该文件名字只能为log4j.properties,且该文件必须存放于根目录中
63
日志等级
debug:调试日志
info:消息日志
warn:警告日志
error:错误日志
fatal:灾难日志
7.多参数查询
mybatis中parameterType只能有一个
也就意味着,无法直接使用两个参数作为条件
解决方案:
将多个参数封装成一个参数对象,参数的类型即为当前的参数对象
通过参数的索引来实现
8.模糊查询
方式一:手动拼模糊查询的字符%或者_
方式二:通过bind标签来操作
name属性:需要处理的参数是谁
value属性:需要怎么处理
_parameter:表示当前方法的参数,如果参数是普通字段,直接使用
如果参数是对象,通过_parameter.属性名进行处理
9.注解方式
对于简单语句来说,使用注解代码会更加清晰,然而Java注解对于复杂语句来说就会混乱,应该限制使用。因此,如果你不得不做复杂
的事情,那么最好使用XML来映射语句。
<select id="selectByUsernameAndPassword" parameterType="user" resultType="user">
select <include refid="userColumn"></include>
from t_user
where username = #{username}
and password = #{password}
</select>
<select id="selectByUsernameAndPassword2" resultType="user">
select <include refid="userColumn"></include>
from t_user
where username = #{0}
and password = #{1}
</select>
<!‐‐
模糊查询
根据手机号进行模糊查询
有两种方式
1.手动拼%
2.代码自己拼%
‐‐>
<!‐‐ 方式一 ‐‐>
<select id="selectByPhone" parameterType="string" resultType="user">
select <include refid="userColumn"></include>
from t_user
where phone like #{phone} escape '/'
</select>
<!‐‐ 方式二 ‐‐>
<select id="selectByPhone2" parameterType="string" resultType="user">
select <include refid="userColumn"></include>
from t_user
<bind name="phone" value="'%'+ _parameter +'%'"/>
where phone like #{phone} escape '/'
</select>

10.动态sql
101
if
类似于jstl中的if标签
test属性:表达式内容,该表达式的值为true/false,
当值为true时,执行标签体的内容
当值为false是,不执行标签体的内容
package dao;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import entity.User;
public interface IUserDao {
//Select标签指定sql语句
@Select("select * from t_user where id = #{id}")
public User selectById(Integer id);
@Select("select * from t_user2 where user_id = #{id}")
//Results相当于ResultMap标签
@Results(value={
//Result相当于id/result标签
//其中属性id=true相当于使用的是id标签,默认为false
@Result(id=true,property="id",column="user_id"),
@Result(property="username",column="user_username"),
@Result(property="password",column="user_password"),
@Result(property="phone",column="user_phone"),
@Result(property="address",column="user_address")
})
public User selectById2(Integer id);
@Insert(value="insert into t_user(username,password,phone,address) values(#{username},#{password},#
{phone},#{address})")
public void insertUser(User user);
}
<mapper class="dao.IUserDao"/>

102
choose
类似于jstl中的choose
when标签:通过test定义一个表达式,返回值为true/false
表达式内容值为true,执行标签体的内容,跳出当前choose
表达式内容值为false,不执行标签体的内容,继续往下判断
otherwise标签:当choose中所有的when标签条件均未满足,则执行otherwise标签体中的内容
<!‐‐ 动态sql之if ‐‐>
<select id="selectByParams" parameterType="user" resultType="user">
select <include refid="userColumn"></include>
from t_user
where 1=1
<!‐‐ 此时的username表示的是参数对象中的某一个属性 ‐‐>
<if test="username != null and username != ''">
<bind name="username" value="'%'+ _parameter.username +'%'"/>
and username like #{username} escape '/'
</if>
<if test="password != null and password != ''">
and password = #{password}
</if>
<if test="phone != null and phone != ''">
<bind name="phone" value="'%'+ _parameter.phone +'%'"/>
and phone like #{phone} escape '/'
</if>
<if test="address != null and address != ''">
<bind name="address" value="'%'+ _parameter.address +'%'"/>
and address like #{address} escape '/'
</if>
</select>

103
where
一般会与if/choose组合使用
单独使用没有太大意义
会在where标签体中所生成的sql语句块前加一个where关键字
且会忽略第一个连接条件
<!‐‐ 动态sql之choose ‐‐>
<select id="selectByParams2" parameterType="user" resultType="user">
select <include refid="userColumn"></include>
from t_user
where 1 = 1
<choose>
<when test="username != null and username != ''">
<bind name="username" value="'%'+ _parameter.username +'%'"/>
and username like #{username} escape '/'
</when>
<when test="password != null and password != ''">
<bind name="password" value="'%'+ _parameter.password +'%'"/>
and password like #{password} escape '/'
</when>
<when test="phone != null and phone != ''">
<bind name="phone" value="'%'+ _parameter.phone +'%'"/>
and phone like #{phone} escape '/'
</when>
<when test="address != null and address != ''">
<bind name="address" value="'%'+ _parameter.address +'%'"/>
and address like #{address} escape '/'
</when>
<otherwise>
and id = #{id}
</otherwise>
</choose>
</select>
<!‐‐ 动态sql之where ‐‐>
<select id="selectByParams3" parameterType="user" resultType="user">
select <include refid="userColumn"></include>
from t_user
<where>
<if test="username != null and username != ''">
<bind name="username" value="'%'+ _parameter.username +'%'"/>
or username like #{username} escape '/'
</if>
<if test="password != null and password != ''">
or password = #{password}
</if>
<if test="phone != null and phone != ''">
<bind name="phone" value="'%'+ _parameter.phone +'%'"/>
and phone like #{phone} escape '/'
</if>
<if test="address != null and address != ''">
<bind name="address" value="'%'+ _parameter.address +'%'"/>
and address like #{address} escape '/'
</if>
</where>
</select>

104
set
一般会与if/choose组合使用
单独使用没有太大意义
会在set标签体中所生成的sql语句块前加一个set关键字
且会忽略语句块末尾的一个逗号
105
trim
可以在包含的语句块中加上某些前缀或者后缀
还可以忽略语句块首部/尾部的某些内容
prefix属性:添加前缀
suffix属性:添加后缀
prefixOverides属性:忽略首部内容
suffixOverides属性:忽略尾部内容
当忽略的内容选项有多种时,通过竖杠|来表示或者的意思
前竖杠后面要紧跟关键字,不能存在空格
<!‐‐ 动态sql之set ‐‐>
<update id="updateSelective" parameterType="user">
update t_user
<set>
<if test="username != null and username != ''">
username = #{username},
</if>
<if test="password != null and password != ''">
password = #{password},
</if>
<if test="phone != null and phone != ''">
phone = #{phone},
</if>
<if test="address != null and address != ''">
address = #{address},
</if>
</set>
where id = #{id}
</update>

106
foreach
用来构建in语句的时候使用
此时的条件的值是多个值
可以通过foreach迭代一系列的数据
collection属性:参数的类型
直接作为属性时,不关心参数名叫什么,关心的只是类型,类型的值有三种
list:当参数类型为List时使用
map:当参数类型为map时使用
array:当参数为数组时使用
item属性:集合中每一个元素进行迭代时的别名
<!‐‐ 动态sql之trim ‐‐>
<select id="selectByParams4" parameterType="user" resultType="user">
select <include refid="userColumn"></include>
from t_user
<trim prefix="where" prefixOverrides="and|or">
<if test="username != null and username != ''">
<bind name="username" value="'%'+ _parameter.username +'%'"/>
and username like #{username} escape '/'
</if>
<if test="password != null and password != ''">
or password = #{password}
</if>
<if test="phone != null and phone != ''">
<bind name="phone" value="'%'+ _parameter.phone +'%'"/>
and phone like #{phone} escape '/'
</if>
<if test="address != null and address != ''">
<bind name="address" value="'%'+ _parameter.address +'%'"/>
and address like #{address} escape '/'
</if>
</trim>
</select>
<update id="updateSelective2" parameterType="user">
update t_user
<trim prefix="set" suffixOverrides=",">
<if test="username != null and username != ''">
username = #{username},
</if>
<if test="password != null and password != ''">
password = #{password},
</if>
<if test="phone != null and phone != ''">
phone = #{phone},
</if>
<if test="address != null and address != ''">
address = #{address},
</if>
</trim>
where id = #{id}
</update>
select * from t_user where id in (1,2,3,4);


index属性:指定一个名字,用于表示在迭代过程中迭代到的当前的位置
open属性:表示该语句以什么开始
close属性:表示该语句以什么结束
separator属性:每次迭代的数据之间以什么作为分隔
11.mybatis多表操作
111
有一个的关系
多对一
一对一
一个员工有一个部门
部门表
部门id
部门名称name
员工表
员工id
员工姓名name
员工工资salary
所属的部门dept_id
有一个的关系的查询方式有三种
直接使用关联属性进行配置
<!‐‐ 动态sql之foreach ‐‐>
<select id="selectByIds" resultType="user">
select <include refid="userColumn"></include>
from t_user
where id in
<foreach collection="list" item="id" open="(" close=")" >
#{id}
</foreach>
</select>
create table t_dept(
id int primary key auto_increment,
name varchar(20)
)engine=Innodb default charset=utf8;
create table t_emp(
id int primary key auto_increment,
name varchar(20),
salary double,
dept_id int,
foreign key (dept_id) references t_dept(id)
)engine=Innodb default charset=utf8;

关联的嵌套结果
<resultMap type="emp" id="empMapper">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="salary" column="salary"/>
<!‐‐
association:配置关联属性,用来处理有一个的关系
property属性:指定映射的属性是谁
column属性:映射的属性通过哪一个字段进行映射
该字段不是直接映射到对象属性中
而是通过该字段能够获取到需要映射的对象所需要的所有属性
本质上就是当前的外键字段
‐‐>
<association property="dept" column="dept_id" javaType="Dept">
<!‐‐
标签体中执行对象属性dept中的所有属性的映射
‐‐>
<id property="id" column="d.id"/>
<result property="name" column="d.name"/>
</association>
</resultMap>
<!‐‐
根据员工id查询员工详情,并查询出所属部门名称
在映射过程中,属性映射字段
如果查询的结果中存在重复的字段名
那么在映射的时候映射的永远是前面的字段名,而映射不到后面的
因此,需要为同名的字段取一个不同的别名
‐‐>
<select id="selectById" parameterType="integer" resultMap="empMapper">
select e.id,e.name,e.salary,
e.dept_id,d.id 'd.id',d.name 'd.name'
from t_emp e
left join t_dept d
on e.dept_id = d.id
where e.id = #{id}
</select>

关联的嵌套查询
该方式存在N+1问题
N+1问题:
查询一次Emp,获取到N条Emp的信息
根据每一条Emp信息中的dept_id值
去查询dept表中的数据
一个Emp查询一次dept
N个Emp查询N次dept
总共查询次数=1次Emp+N次Dept
在开发过程中,尽量避免出现N+1问题
<resultMap type="dept" id="deptMapper">
<id property="id" column="d.id"/>
<result property="name" column="d.name"/>
</resultMap>
<resultMap type="emp" id="empMapper2">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="salary" column="salary"/>
<!‐‐
resultMap属性:调用另一个resultMap作为当前对象的映射结果
‐‐>
<association property="dept" column="dept_id" javaType="Dept" resultMap="dao.DeptDao.deptMapper">
</association>
</resultMap>
<select id="selectById2" parameterType="integer" resultMap="empMapper2">
select e.id,e.name,e.salary,
e.dept_id,d.id 'd.id',d.name 'd.name'
from t_emp e
left join t_dept d
on e.dept_id = d.id
where e.id = #{id}
</select>

有多个的关系
一对多
多对多
<!‐‐
根据id查询出员工信息
再根据员工信息中的dept_id去dept中再做一次查询
此时产生了两条sql语句
这就是持久层框架中常见的N+1问题
这样会导致效率过低
不建议使用
‐‐>
<select id="selectById3" parameterType="integer" resultMap="empMapper3">
select id,name,salary,dept_id
from t_emp
where id = #{id}
</select>
<!‐‐
N+1问题:
查询一次Emp,获取到N条Emp的信息
根据每一条Emp信息中的dept_id值
去查询dept表中的数据
一个Emp查询一次dept
N个Emp查询N次dept
总共查询次数=1次Emp+N次Dept
在开发过程中,尽量避免出现N+1问题
‐‐>
<select id="selectAll" resultMap="empMapper3">
select *
from t_emp
</select>
<select id="selectById" parameterType="integer" resultType="dept">
select id,name
from t_dept
where id = #{id}
</select>
<resultMap type="emp" id="empMapper3">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="salary" column="salary"/>
<!‐‐
resultMap属性:调用另一个resultMap作为当前对象的映射结果
‐‐>
<association property="dept" column="dept_id" javaType="Dept" select="dao.DeptDao.selectById">
</association>
</resultMap>
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Mybatis中,默认情况下是手动提交事务的。也就是说,当使用openSession()方法获取的SqlSession对象时,需要手动调用commit()方法来提交事务。只有在所有的SQL语句都成功执行后,才会进行事务的提交,否则会进行回滚操作,以保证数据的一致性。\[3\]所以,如果你想要手动提交事务,可以在执行完所有的数据库操作后,调用sqlSession.commit()方法来提交事务。\[2\] #### 引用[.reference_title] - *1* [Mybatis 的事务控制](https://blog.csdn.net/m0_67401606/article/details/123661655)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [MyBatis 3.5.4源码之旅六之sqlSession手动提交事务](https://blog.csdn.net/wangwei19871103/article/details/103686121)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [初学MyBatis的疑问:1、为什么JDBC默认自动提交事务,MyBatis中却需要自己手动提交事务](https://blog.csdn.net/qq_45785650/article/details/130206358)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值