1、介绍mybatis框架
(1)什么是框架:框架就是别人搭建好的某些功能,你只需要引用该框架并加入自己的业务代码
(2)mybatis的介绍:MyBatis 是一款优秀的持久层Dao框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Java实体类)映射成数据库中的记录。
2、如何使用mybatis
(1)在pom.xml中引入mybatis和mysql的jar包
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
(2) 创建mybatis的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<!--数据源的配置:name的值固定 value的值要根据客户自己修改-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghai" />
<property name="username" value="root" /> //自己用户
<property name="password" value="root" /> //自己密码
</dataSource>
</environment>
</environments>
</configuration>
(3)创建数据库和表(省略)
(4) 创建实体类(省略)
(5) 创建mybatis和数据库的映射文件
作用: 映射实体和表之间的映射关系
<?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="com.user">
<!--查询 根据id查询用户信息
select标签用于查询的标签
id:标签的唯一标识
resultType: 定义返回的类型 把sql查询的结果封装到哪个实体类钟
#{id}===表示占位符等价于? 这是mybatis框架的语法
-->
<select id="findById" resultType="com.dsf.entity.User">
select * from tb_user where userid=#{id}
</select>
</mapper>
(6) 测试mybatis
public class Test01 {
public static void main(String[] args) throws Exception {
//1.读取mybatis配置文件的内容----未来不需要写tomcat 解析配置文件
Reader reader = Resources.getResourceAsReader("mybatis.xml");
//2. 获取SqlSessionFactory对象
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(reader);
//3. 获取SqlSession对象----封装了对数据库操作的各种方法
SqlSession session=factory.openSession();
//调用查询一个结果的接口
//String statement, 命名空间+id----指向sql标签
// Object parameter 需要实参
User user = session.selectOne("com.user.findById", 2);
System.out.println(user);
//4.关闭
session.close();
}
}
3、初学mybatis出现的错误
(1)不要使用关键字:mybatis
(2) selectOne方法时statement+id, 写错了 ;你没有把映射文件注册到配置文件上
(3) xml格式不正确
(4) 属性名不正确
4、 lombok插件
作用:它可以帮你生成实体类的get和set方法 而且可以帮你生成构造方法;重写toString方法
(1) idea安装lombok插件
(2) 在pom.xml工程中引入lombok依赖
<!--lombok的依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
(3)在实体类上添加lombok注解
@Data //set和get方法以及toString方法
@NoArgsConstructor //无参构造方法
@AllArgsConstructor //所有参数的构造方法
public class User {
private int userid;
private String username;
private String realname;
}
5、 使用mybatis完成crud(查增改删)
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="com.user">
<select id="findById" resultType="com.dsf.entity.User">
select * from tb_user where userid=#{id}
</select>
<!--添加
parametertype: 参数类型
#{必须和属性对应}
-->
<insert id="add" parameterType="com.dsf.entity.User">
insert into tb_user(username,realname) values(#{username},#{realname})
</insert>
<!--删除-->
<delete id="delete" parameterType="int">
delete from tb_user where userid=#{id}
</delete>
<!--修改-->
<update id="update" parameterType="com.dsf.entity.User">
update tb_user set username=#{username},realname=#{realname} where userid=#{userid}
</update>
<!--查询所有-->
<select id="findAll" resultType="com.dsf.entity.User">
select * from tb_user
</select>
</mapper>
测试:
public class Test01 {
//查询所有
@Test
public void testFindAll()throws Exception{
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(reader);
SqlSession session=factory.openSession();
List<User> users = session.selectList("com.user.findAll");
System.out.println(users);
session.commit();//必须提交
session.close();
}
//修改
@Test
public void testUpdate()throws Exception{
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(reader);
SqlSession session=factory.openSession();
User user=new User(8,"lm","黎明");
int row = session.update("com.user.update", user);
System.out.println(row);
session.commit();//必须提交
session.close();
}
//删除
@Test
public void testDelete()throws Exception{
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(reader);
SqlSession session=factory.openSession();
int row = session.delete("com.user.delete", 1);
System.out.println(row);
session.commit();//必须提交
session.close();
}
//测试添加
@Test
public void testAdd() throws Exception{
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(reader);
SqlSession session=factory.openSession();
User user=new User();
user.setUsername("xxn");
user.setRealname("小仙女");
int row = session.insert("com.user.add", user);
System.out.println(row);
session.commit();//必须提交
session.close();
}
}
6、 mybatis一些优化
6.1 为实体类起别名
mybatis.xml配置文件:
<typeAliases>
<!--单独为某个实体类起别名 -->
<typeAlias type="com.dsf.entity.User" alias="u"/>
<!--为指定包下的实体类起别名该别名就是实体类名-->
<package name="com.dsf.entity"/>
</typeAliases>
<select id="delete" parameterType="User">
select * from user where id=#{id}
</select>
<select id="findOne" resultType="u">
select * from
</select>
6.2 添加sql日志
(1)添加日志的jar
<!--log4f-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
(2) 添加日志的文件配置--log4j.properties必须
log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
7、通过dao和映射文件的关联来完成操作---企业开发模式
7.1 如何实现
(1)创建一个dao接口并定义自己需要的方法
public interface UserDao {
//查询所有
public List<User> findAll();
}
(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">
<!--namespace:命名空间
必须和dao相同
-->
<mapper namespace="com.dsf.dao.UserDao">
<select id="findAll" resultType="com.dsf.entity.User">
select * from tb_user
</select>
</mapper>
注意: namespace必须和dao接口一样,而且标签的id必须和你接口的方法名一样
(3)测试
@Test
public void testFindAll() throws Exception{
Reader resourceAsReader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(resourceAsReader);
SqlSession session=factory.openSession();
//获取相应接口的代理对象
UserDao userDao=session.getMapper(UserDao.class);
List<User> list = userDao.findAll();
System.out.println(list);
session.commit();
session.close();
}
7.2 安装mybatis插件
作用: 检查dao和映射文件是否匹配
8、传递多个参数
我们在dao接口中某些方法可能需要传递多个参数,例如: 登录(ame,pwd)
我们需要在参数处使用@Param()为参数起名
9、添加时如何返回递增的主键值
<!--添加用户
useGeneratedKeys:设置使用生成的主键
keyProperty: 赋值给哪个属性
-->
<insert id="addUser" parameterType="com.dsf.entity.User"
useGeneratedKeys="true" keyProperty="userId">
insert into tb_user values(null,#{name},#{pwd})
</insert>
//需要返回添加数据库后的id值
10、解决列名和属性名不一致
问题: 查询时返回一个null,或者某个列没有值
可以有两种解决办法:
(1)为查询的列起别名,而别名和属性名一致
<!--根据id查询学生信息-->
<select id="findOne" resultType="com.dsf.entity.Student">
select stu_id id,stu_name name,stu_age age from tb_stu where stu_id=#{id}
</select>
第二种: 使用resultMap完成列和属性之间的映射关系
<resultMap id="StuMapper" type="com.dsf.entity.Student">
<!--主键的映射关系 column:列名 property:属性名-->
<id column="stu_id" property="id"/>
<!--普通列的映射关系-->
<result column="stu_name" property="name"/>
<result column="stu_age" property="age"/>
</resultMap>
<!--resultType和ResultMap二者只能用一个-->
<select id="findOne" resultMap="StuMapper">
select * from tb_stu where stu_id=#{id}
</select>
如果列名和属性名有些一致的,可以在resultMap中不写映射关系
11、动态sql
11.1什么是动态sql:根据参数的值,判断sql的条件
name!=null address
select * from 表名 where name=#{name} and address=#{address}
name==null
select * from 表名.
11.2mybatis中动态sql标签有哪些
元素 | 作用 | 描述 |
if | 条件判断 | 单条件判断 |
choose(when、otherwise) | 条件选择、相当java when | 多条件分支判断 |
where、set | 辅助 | 处理sql语句拼接问题 |
foreache | 循环 | 循环 |
11.3 if标签--单条件判断
//如果name不为null则按照name查询 如果为null则查询所有
public List<Account> findByCondition(@Param("name")String name,@Param("money") Double money);
<select id="findByCondition" resultType="com.dsf.entity.Account">
select * from account where 1=1
<if test="name!=null and name!=''">
and name=#{name}
</if>
<if test="money!=null">
and money=#{money}
</if>
</select>
11.4 choose标签 多条件分支判断
<select id="findByCondition2" resultType="com.dsf.entity.Account">
select * from account where 1=1
<choose>
<when test="name!=null and name!=''">
and name=#{name}
</when>
<when test="money!=null">
and money=#{money}
</when>
<otherwise>
and isdeleted=0
</otherwise>
</choose>
</select>
11.5 where标签
<select id="findByCondition" resultType="com.dsf.entity.Account">
select * from account
<where>
<if test="name!=null and name!=''">
and name=#{name}
</if>
<if test="money!=null">
and money=#{money}
</if>
</where>
</select>
11.6set标签
这个配合if标签一起用,一般用在修改语句;如果传递的参数值为null,那么应该不修改该列的值
<!--set:可以帮我们生成关键字 set 并且可以去除最后一个逗号-->
<update id="update" parameterType="com.dsf.entity.Account">
update account
<set>
<if test="name!=null and name!=''">
name=#{name},
</if>
<if test="money!=null">
money=#{money},
</if>
<if test="isdeleted!=null">
isdeleted=#{isdeleted},
</if>
<if test="created!=null">
created=#{created},
</if>
<if test="updated!=null">
updated=#{updated},
</if>
</set>
where id=#{id}
</update>
11.7foreach标签(循环标签 )
查询:
<!-- select * from account where id in(2,3,5,7,0)
如果你使用的为数组array 如果你使用的为集合 那么就用list
collection:类型
item:数组中每个元素赋值的变量名
open: 以谁开始
close:以谁结束
separator:分割符
-->
<select id="findByIds" resultType="com.dsf.entity.Account">
select * from account where id in
<foreach collection="array" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</select>
删除:
<delete id="batchDelete">
<foreach collection="array" item="id" open="delete from account where id in(" close=")" separator=",">
#{id}
</foreach>
</delete>
添加:
<insert id="saveBatch">
insert into account(name,isdeleted) values
<foreach collection="list" item="acc" separator=",">
(#{acc.name},#{acc.isdeleted})
</foreach>
</insert>
12、mybatis映射文件处理特殊字符
<!--
第一种:转义标签 <
第二种: <![CDATA[sql]]>
-->
<select id="findByMaxMin" resultType="com.dsf.entity.Account">
<![CDATA[select * from account where id >#{min} and id <#{max}]]>
</select>
13、mybatis完成模糊查询
(1)使用字符串函数 完成拼接 concat
<select id="findByLike" resultType="com.dsf.entity.Account">
select * from account where name like concat('%',#{name},'%')
</select>
(2) 使用${}
<select id="findByLike" resultType="com.dsf.entity.Account">
select * from account where name like '%${name}%'
</select>
14、联表查询
多对一 : 从多的一方来查询一的一方
例如:班级表和学生表
根据学生id查询学生信息并携带班级信息
select * from tb_stu s join tb_class c on s.class_id=c.cid where stu_id=1
实体类:
学生表:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private int id;
private String name;
private int age;
private String sex;
private Integer classId;
private Clazz clazz;//学生所属的班级
}
班级表:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Clazz {
private Integer cid;
private String cname;
}
xml:
<resultMap id="baseMap" type="com.dsf.entity.Student">
<id column="stu_id" property="id"/>
<result column="stu_name" property="name"/>
<result column="stu_age" property="age"/>
<result column="sex" property="sex"/>
<result column="class_id" property="classId"/>
<!--association: 表示一的一方
property: 它表示属性名
javaType: 该属性名对应的数据类型
-->
<association property="clazz" javaType="com.dsf.entity.Clazz">
<id column="cid" property="cid"/>
<result column="cname" property="cname"/>
</association>
</resultMap>
<select id="findStudentById" resultMap="baseMap">
select * from tb_stu s join tb_class c on s.class_id=c.cid where stu_id=#{id}
</select>
测试:
@Test
public void findStudentById()throws Exception{
Reader reader= Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(reader);
SqlSession session= factory.openSession();
StudentDao studentDao=session.getMapper(StudentDao.class);
Map map=StudentDao.findStudentById(1);
System.out.println("cname");
session.commit();
session.close();
}