1、如何使用mybatis
(1)在pom.xml中引用mybatis和SQL的jar包和要用到的jar包
<groupId>com.wk</groupId>
<artifactId>mybatis05</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- sql的jar包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<!-- junit的jar包-->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- log4j的依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
</dependencies>
(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/mybatis?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="">
<!--查询 根据id查询用户信息
select标签用于查询的标签
id:标签的唯一标识
resultType: 定义返回的类型 把sql查询的结果封装到哪个实体类钟
#{id}===表示占位符等价于? 这是mybatis框架的语法
-->
</mapper>
注意:==把映射文件注册到配置文件上== mybatis.xml上
<!--注册映射文件-->
<mappers>
<!--resource:引用资源文中的映射文件 url:网络上的映射文件-->
<mapper resource="mapper/UserMapper.xml" />
</mappers>
2、初学者容易犯的错误
(1)
(2)
(3)
(4)
(5)
(6)
3、Lombok插件
作用:它可以帮你生成实体类的get和set方法 而且可以帮你生成构造方法。重写toString方法
(2)、pom.xml中引入lombok依赖
(3)在实体类上添加lombok注解。
@Data //set和get方法以及toString方法
@NoArgsConstructor //无参构造方法
@AllArgsConstructor //所有参数的构造方法
4、使用mybatis完成crud
<?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="">
<!--查询 根据id查询用户信息
select标签用于查询的标签
id:标签的唯一标识
resultType: 定义返回的类型 把sql查询的结果封装到哪个实体类钟
#{id}===表示占位符等价于? 这是mybatis框架的语法
-->
<select id="findById" resultType="">
select * from tb_user where userid=#{id}
</select>
<!--添加
parametertype: 参数类型
#{必须和属性对应}
-->
<insert id="add" parameterType="">
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="">
update tb_user set username=#{username},realname=#{realname} where userid=#{userid}
</update>
<!--查询所有-->
<select id="findAll" resultType="">
select * from tb_user
</select>
</mapper>
测试
package com.test;
import com.ykq.entity.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.Test;
import java.io.Reader;
import java.util.List;
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("namespace起的名字.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","we");
int row = session.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("", 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("lmtb");
// user.setRealname("xx");
int row = session.insert("", user);
System.out.println(row);
session.commit();//必须提交
session.close();
}
}
5、mybatis一些优化
(1)mybatis.xml配置文件
<typeAliases>
<!--单独为某个实体类起别名 -->
<typeAlias type="com.ykq.entity.User" alias="u"/>
<!--为指定包下的实体类起别名该别名就是实体类名-->
<package name="com.ykq.entity"/>
</typeAliases>
(2)添加sql的日志--mybatis.xml配置文件
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
6、dao和映射文件的关联
(1)创建一个dao接口并定义自己需要的方法。
public interface ###Dao {
/**
* 查询所有
* @return
*/
public List<###> 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="你所创建的dao的路径">
<select id="findAll">
</select>
</mapper>
注意: namespace必须和dao接口一样,而且标签的id必须和你接口的方法名一样。
(3)测试
@Test
public void testFindAll()throws Exception{
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session =factory.openSession();
//获取相应接口的代理对象
StudentDao studentDao = session.getMapper(StudentDao.class);
List<Student> list = studentDao.findAll();
System.out.println(list);
session.close();
}
7、传递多个参数
在dao接口中某些方法可能需要传递多个参数,例如:查询单条信息的限制条件
不加@param进行注解报的错误
8、添加时返回递增的主键值
需要返回添加数据库后的id值。
<!--添加用户
useGeneratedKeys:设置使用生成的主键
keyProperty: 赋值给哪个属性
-->
<insert id="addUser" parameterType=""
useGeneratedKeys="true" keyProperty="userId">
insert into tb_user values(null,#{username},#{realname})
</insert>
9、列名和属性名不一致
列名和属性名不一致时, 查询的结果是null,或者某个列没有值
可以有两种解决办法:
(1) 为查询的列起别名,而别名和属性名一致。
列名和属性名不一致
列名和属性名不一致时, 查询的结果是null,或者某个列没有值
可以有两种解决办法:
(1) 为查询的列起别名,而别名和属性名一致。
<select id="findOne" resultType="com.ykq.entity.Student">
//as可以省略
select stu_id id,stu_name as name,stu_age age from tb_stu where stu_id=#{id}
</select>
(2)使用resultMap完成列和属性之间的映射关系。
<resultMap id="StuMapper" type="com.wk.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="findAll" resultMap="StuMapper">
select * from student;
</select>
10、动态sql
动态sql:根据参数的值,判断sql的条件。
mybatis中动态sql标签:
11、dao和映射文件的关联
1、操作流程
(1)创建一个dao接口并定义自己需要的方法。
-
public interface ###Dao { /** * 查询所有 * @return */ public List<###> 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="你所创建的dao的路径"> <select id="findAll"> </select> </mapper>
注意: namespace必须和dao接口一样,而且标签的id必须和你接口的方法名一样。
(3)测试
-
@Test public void testFindAll()throws Exception{ Reader reader = Resources.getResourceAsReader("mybatis.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader); SqlSession session =factory.openSession(); //获取相应接口的代理对象 StudentDao studentDao = session.getMapper(StudentDao.class); List<Student> list = studentDao.findAll(); System.out.println(list); session.close(); }
2、传递多个参数
在dao接口中某些方法可能需要传递多个参数,例如:查询单条信息的限制条件
不加@param进行注解报的错误
3、添加时返回递增的主键值
需要返回添加数据库后的id值。
<!--添加用户
useGeneratedKeys:设置使用生成的主键
keyProperty: 赋值给哪个属性
-->
<insert id="addUser" parameterType=""
useGeneratedKeys="true" keyProperty="userId">
insert into tb_user values(null,#{username},#{realname})
</insert>
4、列名和属性名不一致
列名和属性名不一致时, 查询的结果是null,或者某个列没有值
可以有两种解决办法:
(1) 为查询的列起别名,而别名和属性名一致。
(2)使用resultMap完成列和属性之间的映射关系。
-
<resultMap id="StuMapper" type="com.wk.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="findAll" resultMap="StuMapper"> select * from student; </select>
5、动态sql
动态sql:根据参数的值,判断sql的条件。
mybatis中动态sql标签:
if标签--单条件判断
<select id="findByCondition" resultType="">
select * from account
<where>
<if test="name!=null and name!=''">
and name=#{name}
</if>
<if test="money!=null">
and money=#{money}
</if>
</where>
choose标签 多条件分支判断
choose标签在有一个条件满足时,就跳出,不在往下进行判断。
<select id="findByCondition02" resultType="">
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>
where标签
作用:可以自动为你添加where关键字,并且可以帮你去除第一个and |or
<select id="findOne" resultMap="StuMapper">
select * from student
<where>
<choose>
<when test="name!=null and name!=''">
and stu_name=#{name}
</when>
<when test="age!=null ">
and stu_age=#{age}
</when>
</choose>
</where>
</select>
set标签
这个配合if标签一起用,一般用在修改语句。如果传递的参数值为null,那么应该不修改该列的值。
<!--set:可以帮我们生成关键字 set 并且可以去除最后一个逗号-->
<update id="update">
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>
</set>
where id=#{id}
</update>
foreach标签
循环标签.
查询:
<!-- select * from account where id in(2,3,5,7,0)
如果你使用的为数组array 如果你使用的为集合 那么就用list
collection:类型
item:数组中每个元素赋值的变量名
open: 以谁开始
close:以谁结束
separator:分割符
-->
<select id="findByIds" resultType="com.ykq.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>
mybatis映射文件处理特殊字符
<!--
第一种:转义标签 <
第二种: <![CDATA[sql]]>
-->
<select id="findByMaxMin" resultType="com.ykq.entity.Account">
<![CDATA[select * from account where id >#{min} and id <#{max}]]>
</select>
mybatis完成模糊查询。
(1)使用字符串函数 完成拼接 concat
<select id="findByLike" resultType="">
select * from account where name like concat('%',#{name},'%')
</select>
(2) 使用${}
<select id="findByLike" resultType="
select * from account where name like '%${name}%'
</select>
联表查询
-
多对一 : 从多的一方来查询一的一方。
如:班级表(一):
学生表(多):
select * from tb_stu s join tb_class c
on s.class_id=c.cid
where stu_id=
创建两个实体类
<resultMap id="baseMap" type="com.ykq.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="实体类的路径">
<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>
分页插件PageHelper
使用流程:
(1)引入pageHelper的jar包
<!--引入pageHelper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.11</version>
</dependency>
(2)mybatis中设置pageHelper的拦截器
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
(3)使用pageHelper
@Test
public void testFindAll() throws Exception{
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = factory.openSession();
StudentDao studentDao = session.getMapper(StudentDao.class);
// 设置分页属性pageNum:显示第几页 PageSize:每页显示的条数
PageHelper.startPage(1,1);
//把查询的结果封装到PageInfo类中。
List<Student> list = studentDao.findAll();
PageInfo<Student> pageInfo = new PageInfo<Student>(list);
System.out.println(pageInfo.getPages());
System.out.println(list);
session.close();
}
注意:在这一步要把相关实体类实现可序列化
否则会报错:
解决方法:
原理:
mybatis的代码生成器--generator
作用: 根据表帮你生成实体类,和dao和xml映射文件。就是简单的CRUD
使用流程:
(1)引入mybatis-generator的依赖jar包
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
(2)generator的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--找到mysql驱动jar的位置-->
<classPathEntry location="D:\repMaven\mysql\mysql-connector-java\8.0.28\mysql-connector-java-8.0.28.jar" />
<context id="DB2Tables" targetRuntime="MyBatis3">
<!--抑制注释:使其不生成相关的英文注释-->
<commentGenerator>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--数据库的配置信息-->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mys1?serverTimezone=Asia/Shanghai"
userId="root"
password="123456de">
</jdbcConnection>
<javaTypeResolver >
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!--java实体类的配置-->
<javaModelGenerator targetPackage="com.aaa.entity" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!--映射文件的配置-->
<sqlMapGenerator targetPackage="mapper" targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!--dao数据访问层的配置-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.aaa.dao"
targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!--数据库表和实体的映射关系
schema:数据库名称
tableName: 表名
domainObjectName:实体类名
enableUpdateByExample:是否生成复杂的修改操作
-->
<table schema="mys1" tableName="teacher" domainObjectName="Teacher"
enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="false"
enableUpdateByExample="false" >
</table>
</context>
(3)运行你的配置文件
在测试类里进行运行即可
@Test
public void test0001()throws Exception{
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("geneator.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
}
mybatis的缓存
缓存是存在于==内存中==的临时数据
使用缓存的好处:使用缓存减少和数据库的交互次数,提高执行效率。
mybatis也支持缓存
mybatis支持两种缓存
(1)一级缓存----基于SqlSession级别的缓存。默认一级缓存是开启的,不能关闭。
(2)二级缓存--基于SqlSessionFactory级别的缓存,它可以做到多个SqlSession共享数据。默认它是关闭。需要手动开启。