Mybatis学习日记
mybatis是什么
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
mybatis地址链接: link
如何使用mybatis
在pom文件中引用mybatis相关依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!--mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-mxj-db-files</artifactId>
<version>5.0.12</version>
</dependency>
在数据库中新建数据,并且新增对应实体类;
@Data
public class UserDto {
private long id;
private String name;
private String phone;
private String sex;
private String id_number;
private String avatar;
private long status;
}
配置对应的配置文件config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<!--JDBC事务管理-->
<transactionManager type="JDBC"/>
<!--JDBC事务管理-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="754750"/>
<!-- <property name="driver" value="${driver}"/>-->
<!-- <property name="url" value="${url}"/>-->
<!-- <property name="username" value="${username}"/>-->
<!-- <property name="password" value="${password}"/>-->
</dataSource>
</environment>
</environments>
<!-- 映射文件-->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
Mybatis有两种使用方式
第一种为原生接口,SQL需要开发者自定义卸载Mapper.xml中,实际开发中会为每一个实体类创建对应的Mapper.xml来管理对应的SQL;
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.UserMapper">
<insert id="save" parameterType="dto.UserDto">
insert into user(name,phone,sex,id_number,avatar,status) values(#{name},#{phone},#{sex},#{id_number},#{avatar},#{status})
</insert>
</mapper>
接下来就可以调用原生接口了:
public class Test {
public static void main(String[] args) {
//加载Mybatis配置文件
InputStream inputStream=Test.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory=sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
String statement="mapper.UserMapper.save";
UserDto userDto=new UserDto(1L,"李四","123456789","1","123","http",0);
sqlSession.insert(statement,userDto);
sqlSession.commit();
}
}
此时执行会报错:
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
### Error building SqlSession.
### The error may exist in mapper/UserMapper.xml
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource mapper/UserMapper.xml
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:82)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:66)
at test.Test.main(Test.java:16)
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource mapper/UserMapper.xml
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:133)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:110)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:80)
... 2 more
Caused by: java.io.IOException: Could not find resource mapper/UserMapper.xml
at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:132)
at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:113)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement(XMLConfigBuilder.java:395)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:131)
... 4 more
Process finished with exit code 1
原因为maven只能读取resource下的文件不能直接读取Java下文件,这里我们在pom文件中添加配置
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>*.xml</include>
<include>*.properties</include>
</includes>
</resource>
</resources>
</build>
然后执行成功,我们看一下数据库就会有新增的数据了。
接下来看mybatis的第二种方式通过Mapper代理的方式实现自定义接口
定义自定义接口,只需要定义相关的业务方法和与方法对应的mapper.xml
package repository;
import dto.UserDto;
import java.util.List;
public interface UserRepository {
public int save(UserDto userDto);
public List<UserDto> qryAll();
}
创建接口对应的Mapper.xml,定义接口方法对应的SQL语句。
statement标签会执行对应的SQL执行
Mybatis框架会根据规则自动创建接口实现对应的代理对象
规则:
1.Mapper.xml中的namespace为接口的全类名
2.Mapper.xml的statement为接口对应的方法名
3.Mapper.xml的statement的parameterTyper和方法的入参一致
4.Mapper.xml的statement的resultType和方法的出参一致
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="repository.mapper.UserRepositoryMapper">
<insert id="save" parameterType="dto.UserDto">
insert into user(name,phone,sex,id_number,avatar,status) values(#{name},#{phone},#{sex},#{id_number},#{avatar},#{status})
</insert>
<select id="qryAll" resultType="dto.UserDto">
select * from user;
</select>
</mapper>
然后在config.xml中注册xml即可
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
<mapper resource="repository/mapper/UserRepositoryMapper.xml"/>
</mappers>
最后测试即可
import java.io.InputStream;
import java.util.List;
public class Test2 {
public static void main(String[] args) {
//加载Mybatis配置文件
InputStream inputStream=Test.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory=sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
//获取实现接口的代理对象
UserRepository mapper = sqlSession.getMapper(UserRepository.class);
List<UserDto> userDtos = mapper.qryAll();
for (UserDto userDto:
userDtos) {
System.out.println(userDto);
}
}
}
Mapper.xml
1.statement标签,如insert,select等
2.parameterType:参数数据类型
多个参数用@Param注解
3.resultType:反参数据类型
Mybatis逆向工程
如何使用Mybatis Generator,简称MBG,是一个专门为Mybatis框架开发者设计的代码生成器,可自动生成框架所需的实体类,Mapper接口,Mapper.xml,支持基本的CRUD操作
首先加入pom和相关配置文件
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.2</version>
</dependency>
</dependencies>
配置文件:
1.jdbcConnection 数据库连接信息
2.javaModelGenerator配置javabean的生成策略
3.sqlMapgenerator配置sql映射文件
4.javaClientGenerator配置mapper接口的生成策略
5.table配置目标数据表(tableName:表名,domainObjectName:实体类名)
<?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>
<context id="testTbales" targetRuntime="Mybatis3">
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=UTF-8"
userId="root"
password="754750"
></jdbcConnection>
<!--实体类的映射 targetPackage代表存放的包 targetProject代表包放在哪-->
<javaModelGenerator targetPackage="com.shop.db.model" targetProject="./src/main/java"/>
<!--sql的映射-->
<sqlMapGenerator targetPackage="com.shop.db.dao" targetProject="./src/main/java"/>
<!--sqlMapper文件的映射-->
<javaClientGenerator targetPackage="com.shop.db.dao.sqlMap" targetProject="./src/main/java"/>
<table tableName="user" domainObjectName="User"></table>
</context>
</generatorConfiguration>
创建Generator的执行类
public class test {
public static void main(String[] args) {
List<String> warnings=new ArrayList<>();
boolean overwrite=true;
String genCig="/generatorConfig.xml";
File config=new File(test.class.getResource(genCig).getFile());
ConfigurationParser configurationParser=new ConfigurationParser(warnings);
Configuration configuration=null;
try {
configuration=configurationParser.parseConfiguration(config);
} catch (IOException e) {
e.printStackTrace();
} catch (XMLParserException e) {
e.printStackTrace();
}
DefaultShellCallback callback=new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator=null;
try {
myBatisGenerator=new MyBatisGenerator(configuration,callback,warnings);
} catch (InvalidConfigurationException e) {
e.printStackTrace();
}
try {
myBatisGenerator.generate(null);
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
然后就是Mybatis的延迟加载(懒加载),是为了提高程序的运行效率,针对数据持久层的操作,在特定的情况去访问特定的数据库,在其他情况下可以不访问某些表,从一定程序下减少了Java程序与数据库的交互。
Mybatis缓存
同样是为了减少Java与数据之间的交互,当多次查询相同的对象,只需要第一次将查询结果放入缓存中,之后的查询再从缓存中读取就行。
Mybatis缓存分类
1、一级缓存:SqlSession级别,默认开启,并且不能关闭
操作数据库时需要创建sqlsession对象,在对象中有一个HashMap存储缓存数据,不同的sqlsession之间互不影响。
需要注意的是:如果sqlsession执行了DML操作,Mybatis就必须把缓存清空以保证数据的准确性
2、二级缓存Mapper级别,默认关闭,可以开启
使用二级缓存时,多个sqlsession使用同一个Mapper的SQL 语句操作数据库,得到的数据会存在二级缓存区,同样是使用HashMap进行数据存储,相比较于一级缓存,范围更大,多个sqlsession可以共用一个缓存
Config.xml
<settings>
<!--打印sql->
<setting name="logImpl" value="STDOUT_LOGGING">
<!--开启延迟加载->
<setting name="lazyLoadingEnabled" value="true">
<!--开启二级缓存->
<setting name="cacheEnabled" value="true">
</settings>
Mapper.xml
<cache></cache>
然后接口实现序列化即可