1、MyBatis是什么
View ------ Controller ----- Service ----- DAO ------ 数据库
jsp/HTML Servlet/SpringMVC Spring jdbc/dbutils/jdbctemplate/mybatis
mybatis实际上就是 DAO层的一个解决方案
学习过jdbc、dbutils、jdbcTemplate、Hibernate 那么为什么我们还要学习 mybatis呢
JDBC:代码非常复杂、速度快
Hibernate:代码精简、致命的缺点(速度慢)
dbutils、jdbcTemplate:框架都不算 只是对jdbc的一个简单的封装而已
mybatis:他是属于效率处于 JDBC和Hibernate之间
他的代码的复杂度也是趋于 JDBC和Hibernate之间
代码灵活、怎么写都是对的
iBatis和mybatis之间的关系是什么?
ibatis是以前的叫法 mybatis是现在的叫法
2、iBatis能干什么
数据库的访问(CRUD)
整合缓存、还可以给类取别名、IBatis还提供了整合Spring的第三方的包
3、为什么要学习这个iBatis
上面的理由已经很充分了
4、ibatis的简单的使用
4.1、导包
<dependency>
<groupId>junit
</groupId>
<artifactId>junit
</artifactId>
<version>4.11
</version>
<scope>test
</scope>
</dependency>
<dependency>
<groupId>org.mybatis
</groupId>
<artifactId>mybatis
</artifactId>
<version>3.4.6
</version>
</dependency>
<dependency>
<groupId>mysql
</groupId>
<artifactId>mysql-connector-java
</artifactId>
<version>5.1.6
</version>
</dependency>
<dependency>
<groupId>log4j
</groupId>
<artifactId>log4j
</artifactId>
<version>1.2.17
</version>
</dependency>
<dependency>
<groupId>org.slf4j
</groupId>
<artifactId>slf4j-api
</artifactId>
<version>1.5.10
</version>
</dependency>
<dependency>
<groupId>org.slf4j
</groupId>
<artifactId>slf4j-log4j12
</artifactId>
<version>1.6.1
</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter
</groupId>
<artifactId>junit-jupiter-api
</artifactId>
<version>RELEASE
</version>
<scope>compile
</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter
</groupId>
<artifactId>junit-jupiter-api
</artifactId>
<version>RELEASE
</version>
<scope>compile
</scope>
</dependency>
4.2、编写mybatis.xml配置文件
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///cd200101"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</dataSource>
</environment>
<environment id="oracle">
<transactionManager type=""></transactionManager>
<dataSource type=""></dataSource>
</environment>
</environments>
<mappers>
<mapper resource="UserMapper.xml"></mapper>
</mappers>
</configuration>
4.3、编写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">
<mapper namespace="UserMapper">
<insert id="add">
insert into t_user(userName,password) values('小小波','123');
</insert>
</mapper>
4.4、编写测试文件
@Test
public void testA() throws IOException
{
Reader reader
= Resources
.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory
= new SqlSessionFactoryBuilder().build(reader
);
SqlSession sqlSession
= sqlSessionFactory
.openSession();
sqlSession
.insert("UserMapper.add");
sqlSession
.commit();
sqlSession
.close();
}
5、iBatis的基本的增删改查的玩法
5.1、增删改查的玩法
public class Test001 {
@Test
public void testA() throws IOException
{
Reader reader
= Resources
.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory
= new SqlSessionFactoryBuilder().build(reader
);
SqlSession sqlSession
= sqlSessionFactory
.openSession();
sqlSession
.selectOne("UserMapper.delete");
sqlSession
.commit();
sqlSession
.close();
}
@Test
public void testAdd(){
MyBatisUtils myBatisUtils
= new MyBatisUtils();
SqlSession sqlSession
= myBatisUtils
.getSqlSession();
sqlSession
.insert("UserMapper.add");
myBatisUtils
.close();
}
@Test
public void testUpdate(){
MyBatisUtils myBatisUtils
= new MyBatisUtils();
SqlSession sqlSession
= myBatisUtils
.getSqlSession();
sqlSession
.insert("UserMapper.update");
myBatisUtils
.close();
}
@Test
public void testQuery(){
MyBatisUtils myBatisUtils
= new MyBatisUtils();
SqlSession sqlSession
= myBatisUtils
.getSqlSession();
Object user
= sqlSession
.selectOne("UserMapper.queryById");
System
.out
.println("对象是:"+user
);
myBatisUtils
.close();
}
@Test
public void testDelete(){
MyBatisUtils myBatisUtils
= new MyBatisUtils();
SqlSession sqlSession
= myBatisUtils
.getSqlSession();
Object user
= sqlSession
.selectOne("UserMapper.delete");
System
.out
.println("对象是:"+user
);
myBatisUtils
.close();
}
}
6、iBatis的基本的工具类的使用
public class MyBatisUtils {
private SqlSessionFactory sqlSessionFactory
=null
;
private ThreadLocal
<SqlSession> threadLocal
;
{
try {
threadLocal
=new ThreadLocal<>();
Reader reader
= Resources
.getResourceAsReader("mybatis.xml");
sqlSessionFactory
=new SqlSessionFactoryBuilder().build(reader
);
} catch (IOException e
) {
e
.printStackTrace();
}
}
public SqlSession
getSqlSession(){
SqlSession sqlSession
= threadLocal
.get();
if(null
!=sqlSession
){
return sqlSession
;
}
sqlSession
=sqlSessionFactory
.openSession();
threadLocal
.set(sqlSession
);
return sqlSession
;
}
public void close(){
SqlSession sqlSession
= threadLocal
.get();
if(null
!=sqlSession
){
sqlSession
.commit();
sqlSession
.close();
threadLocal
.remove();
}
}
}
7、iBatis的数据传参的问题
7.1、传递简单参数
<update id="update1" parameterType="string">
update t_user set password='5555' where userName=#{value}
</update>
sqlSession.insert("UserMapper.update1","小波波");
7.2、传递map集合
<update id="delete" parameterType="map">
delete from t_user where userName=#{userName} and password=#{password}
</update>
Map
<String,String> map=new HashMap<>();
map.put("userName","小波波");
map.put("password","5555");
sqlSession.insert("UserMapper.delete",map);
7.3、传递自定义的类的对象
<select id="findUserByNameAndPassword"parameterType="com.qf.cd.helloworld.User" resultType="com.qf.cd.helloworld.User">
select * from t_user t where t.userName=#{userName} and t.password=#{password}
</select>
User user = new User(1, "小小波", "123");
User user1= sqlSession.selectOne("UserMapper.findUserByNameAndPassword",user);
疑问:能不能一次性传递多个简单的参数呢?
因为后面在接受数据的时候 采用的key是随机的 也就说 可以随便写的 假设你传递了多个简单的参数 那么后面如何区分 这个值是哪一个的 呢?
没有办法进行传递 ------ 如果要进行传递 那么你就封装成 map集合 或者 java的类
8、动态SQL的问题
什么是动态SQL? 在进行查询的时候 会根据前端传递数据的条件 来动态的进行SQL语句的拼接的这种方法 就称为动态SQL
需求:前端随地的给定一串id 要求的是 这一串的id的用户信息全部查询出来 这一串id可以是任意的
id:6,7,9 或者 6,7,8,9 或者 7,8,9
select * from t_user where id in(不确定)
动态sql解决的问题
8.1、传递数组来解决问题
<select id="findUserByIds" parameterType="list" resultType="com.qf.cd.helloworld.User">
select * from t_user
<if test="array != null">
where id
<foreach collection="array" open="in (" close=")" separator="," item="id">
#{id}
</foreach>
</if>
</select>
8.2、传递个集合来解决问题
<select id="findUserByIds2" parameterType="list" resultType="com.qf.cd.helloworld.User">
select * from t_user
<if test="list != null">
where id
<foreach collection="list" open="in (" close=")" separator="," item="id">
#{id}
</foreach>
</if>
</select>
8.3、更新数据(插入数据)
<insert id="insert222" parameterType="com.qf.cd.helloworld.User">
insert into t_user
<trim prefix="(" suffix=")" suffixOverrides="," prefixOverrides="">
<if test="userName != null">
userName,
</if>
<if test="password !=null">
password
</if>
</trim>
<trim prefix="values(" suffix=")" suffixOverrides=",">
<if test="userName != null">
#{userName},
</if>
<if test="password !=null">
#{password}
</if>
</trim>
</insert>
8.4、动态sql和sql片段
<select id="findUserByCondition" parameterType="com.qf.cd.helloworld.User" resultType="com.qf.cd.helloworld.User">
select * from t_user where 1=1
<if test="userName != null">
and userName=#{userName}
</if>
<if test="password !=null">
and password=#{password}
</if>
</select>
<select id="findUserByCondition1" parameterType="com.qf.cd.helloworld.User" resultType="com.qf.cd.helloworld.User">
select * from t_user
<include refid="xiaobobo"></include>
</select>
<sql id="xiaobobo">
<where>
<if test="userName != null">
and userName=#{userName}
</if>
<if test="password !=null">
and password=#{password}
</if>
</where>
</sql>
9、iBatis的结果集的返回问题
9.1、返回简单参数
<select id="findIdByUserName" parameterType="string" resultType="int">
select id from t_user where userName=#{value}
</select>
Object id=sqlSession.selectOne("UserMapper.findIdByUserName","小小波");
9.2、返回自定义的类的对象
<select id="findUserById" parameterType="int" resultType="com.qf.cd.helloworld.User">
select * from t_user where id=#{value}
</select>
Object user=sqlSession.selectOne("UserMapper.findUserById",9);
9.3、返回list集合 但是集合中是常见的数据类型
需求:通过一连串的id查询用户的名字
<!--返回简单参数
需求:通过一连串的id 查询一连串的名字
如果返回集合的数据类型 那么下面的结果集的返回只用写 集合中泛型的数据类型就OK了
-->
<select id
="findNamesByIds" resultType
="string">
select userName from t_user where id
in(6,7,9)
</select
>
List
<String> strs
=sqlSession
.selectList("UserMapper.findNamesByIds");
9.4、返回一个集合 集合中的泛型是自定义的类的类型
<select id="findUserAll" resultType="com.qf.cd.helloworld.User">
select * from t_user
</select>
List
<User> users=sqlSession.selectList("UserMapper.findUserAll");
9.5、数据库的字段和实体不对应怎么办?
9.5.1、取别名解决这个问题
<select id="findDeptAll" resultType="com.qf.cd.result.Dept">
select id as deptId,dept_name as deptName,dept_des as deptDes from t_dept
</select>
9.5.2、通过结果集映射解决这个问题
<resultMap id="findDeptAll2ResultMap" type="com.qf.cd.result.Dept">
<id property="deptId" column="id"></id>
<result property="deptName" column="dept_name"></result>
<result property="deptDes" column="dept_des"></result>
</resultMap>
<select id="findDeptAll2" resultMap="findDeptAll2ResultMap">
select * from t_dept
</select>
10、注意事项
10.1、增删改的标签或者方法也好、是可以随便换的、因为最终真正的执行的是sql语句、跟调用的方法是没有关系的
10.2、查询的方法一般不能换、因为查询要返回具体查询出来的值、不是返回影响的行数
11、一对一映射的关系
需求:一个用户拥有一个身份证、一个身份证唯一的对应了一个用户
用户------------------身份证----------------->一对一的关系 在查询 用户的时候 我希望的是 能查询出身份证
11.1、先准备用户实体
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id
;
private String userName
;
private String password
;
private Idcard idcard
;
}
11.2、准备IdCard实体
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Idcard {
private int id
;
private Date birthday
;
private String cardNum
;
private int userId
;
}
11.3、编写方法的配置
<resultMap id="findUserAllResultMap" type="com.qf.cd.one2one.User">
<id property="id" column="id"></id>
<result property="userName" column="userName"></result>
<result property="password" column="password"></result>
<association property="idcard" javaType="com.qf.cd.one2one.Idcard">
<id property="id" column="idcardId"></id>
<result property="birthday" column="birthday"></result>
<result property="cardNum" column="cardNum"></result>
<result property="userId" column="userId"></result>
</association>
</resultMap>
<select id="findUserAll" resultMap="findUserAllResultMap">
select * from t_user t1,t_idcard t2 where t1.id=t2.userId
</select>
11.4、测试
@Test
public void testAdd(){
MyBatisUtils myBatisUtils
= new MyBatisUtils();
SqlSession sqlSession
= myBatisUtils
.getSqlSession();
List
<User> users
=sqlSession
.selectList("UserMapper.findUserAll");
System
.out
.println(users
);
myBatisUtils
.close();
}
12、一对多的映射关系
12.1、准备Dept对象
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dept {
private int deptId
;
private String deptName
;
private String deptDes
;
private List
<Employee> emps
;
}
12.2、准备Employee对象
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
private int empId
;
private String empName
;
private int gender
;
}
12.3、准备配置文件
<resultMap id="findDept1AllResultMap" type="com.qf.cd.one2many.Dept">
<id property="deptId" column="deptId"></id>
<result property="deptName" column="deptName"></result>
<result property="deptDes" column="deptDes"></result>
<collection property="emps" ofType="com.qf.cd.one2many.Employee">
<id property="empId" column="empId"></id>
<result property="empName" column="empName"></result>
<result property="gender" column="gender"></result>
</collection>
</resultMap>
<select id="findDept1All" resultMap="findDept1AllResultMap">
select * from t_dept1 t1,t_emp t2 where t1.deptId=t2.deptId
</select>
12.4、测试
@Test
public void testDelete(){
MyBatisUtils myBatisUtils
= new MyBatisUtils();
SqlSession sqlSession
= myBatisUtils
.getSqlSession();
List
<Dept> depts
=sqlSession
.selectList("UserMapper.findDept1All");
System
.out
.println(depts
);
myBatisUtils
.close();
}
13、取别名的问题
为什么要整个别名? 因为我们很多时候在写 这个java类型的时候 都写的的全路径
简单的说就是为了解决 传入参数的类型过长 以及 返回参数的类型 过长的问题
mybatis.xml中进行配置
<typeAliases>
<package name="com.qf.cd.one2many"></package>
</typeAliases>
14、懒加载的问题
14.1、关闭积极的加载、开启懒加载
<settings>
<setting name="lazyLoadingEnabled" value="true" />
<setting name="aggressiveLazyLoading" value="false" />
</settings>
14.2、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="UserMapper">
<resultMap id="findUserAllResultMap" type="com.qf.cd.one2one.User">
<id property="id" column="id"></id>
<result property="userName" column="userName"></result>
<result property="password" column="password"></result>
<association property="idcard" column="id" javaType="com.qf.cd.one2one.Idcard" select="IdCardMapper.findIdCardByUserId" fetchType="lazy">
</association>
</resultMap>
<select id="findUserAll" resultMap="findUserAllResultMap">
select * from t_user where id=6
</select>
</mapper>
14.3、测试问题
@Test
public void testAdd() throws IOException
{
Reader reader
= Resources
.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory
= new SqlSessionFactoryBuilder().build(reader
);
SqlSession sqlSession
= sqlSessionFactory
.openSession();
User users
=sqlSession
.selectOne("UserMapper.findUserAll");
System
.out
.println("中国好");
System
.out
.println("中国好");
System
.out
.println("中国好");
System
.out
.println("中国好");
sqlSession
.commit();
sqlSession
.close();
}