1、概念
1.mybatis:支持普通 SQL查询,存储过程和高级映射的优秀持久层框架
2.作用: 配置数据源,注册对应的sqlMapper映射文件
2、使用mybatis
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.5.6</version>
</dependency>
<!-- 数据库驱动包,选择对应数据库的即可 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<build>
<!--在build中配置resources来防止资源导出失败的问题-->
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.xml</exclude>
</excludes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
2.配置mybatis-config.xml,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">
<!-- 在resources目录下进行创建mybatis-config.xml,配置文件需严格按照配置顺序进行配置!!! -->
<configuration>
<!--1、属性使用db.proper进行配置时,需先引入外部配置文件-->
<!-- <properties resource="db.properties"/>-->
<!--2、设置,mybatis的一些设置参数设置,具体参考官方文档-->
<settings>
<!--mybatis标准sql日志输出-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--3、类型别名,给类或包取别名,常使用到@Alias注解,具体参考官方文档-->
<!-- 配置数据源:default是值与当前需要使用的环境ID相匹配 -->
<environments default="development">
<!--每个 environment 元素定义的环境 ID,这个环境ID可以配置多个,一个数据库对应一个-->
<environment id="development">
<!--事务管理器的配置-->
<transactionManager type="JDBC" />
<!-- 配置数据库连接信息 -->
<dataSource type="POOLED">
<!-- value属性值也可通过【value="${driver}"】来引用db.properties配置文件中配置的值,从而将数据库连接相关信息单独做一个配置文件db.properties -->
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/UACS?useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!-- 9、映射器:注册对应的sqlMapper文件 -->
<mappers>
<!--第一种,使用多个mapper标签,逐个指定对应类路径-->
<mapper resource="com/hxzy/dao/UserMapper.xml"/>
<!--第二种,使用包名的方式指定 -->
<package name="com.hxzy.dao"/>
<!-- 第三种,当*mapper与*mapper.xml名称相同,且在同一目录下时,可以使用class -->
<mapper class="com.jiang.dao.UserMapper"/>
</mappers>
</configuration>
3.编写pojo与dao
package com.jiang.pojo;
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.jiang.dao;
import org.apache.ibatis.annotations.Select;
import com.jiang.pojo.User;
public interface UserDao {
int addUser(User user);
int updateUser(Map map);
List<User> selectAllByUser(String username);
//使用注解开发,可以不写sql对应的xml,@Param注解配置的值与sql语句中的对应
@Select("SELECT * FROM User WHERE id = #{id}")
User selectAById(@Param("id")int uid)
}
4.编写mapper.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.jiang.dao.UserDao">
<!-- 当出现一个类包含另一个类时,mapper文件中可以这么写,当前是user包含account-->
<resultMap id="userAccountMap" type="User">
<!-- property:实体类字段 column:数据库字段 ,配置两个字段的对应关系 -->
<id property="id" column="id"></id>
<result property="username" column="name"></result>
<result property="address" column="addresss"></result>
<result property="sex" column="sex"></result><!-- 两个字段名称相同时可省略 -->
<result property="birthday" column="birthday"></result><!-- 两个字段名称相同时可省略 -->
<!-- 配置user对象中accounts集合的映射 -->
<collection property="accounts" ofType="account">
<id column="aid" property="id"></id>
<result column="uid" property="uid"></result>
<result column="money" property="money"></result>
</collection>
</resultMap>
<!-- 当当前是Student类包含Teacher_ID,Student的resultMap与resultMap的id一致-->
<select id="getAllStudent" resultMap="Student_map">
select * FROM UACS.jx_student
</select>
<!-- 必须在上面这个select的下面-->
<resultMap id="Student_map" type="com.jiang.pojo.Student">
<!--普通字段的处理:property是pojo的类型,column数据库字段-->
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
<!--对象字段的处理:property是pojo的类型,column数据库字段,javaType查询结果的类型,select查询的方法-->
<association property="teacher" column="tid" javaType="com.jiang.pojo.Teacher" select="getTeacherById">
</association>
</resultMap>
<select id="getTeacherById" resultType="com.jiang.pojo.Teacher">
select * FROM UACS.jx_teacher where id = #{tid}
</select>
<!--
id:接口里面的方法
parameterType:方法参数的数据类型。基本数据类型可以省略,当方法有多个参数,又不是对象时,填map
resultType:返回值类型。,基本数据类型可以省略,如果返回值时User集合,则返回值填User就行
#{}:占位符,表示这里需要传值过来
${}:占位符,不安全,可以sql注入
uuid()函数(生成32位的,不重复的字符串)
limit 0,3 获取下标为0开始的3条记录,主要用于分页。l用在sql最后面,前面不需要加and、where
-->
<insert id="addUser" parameterType="com.jiang.pojo.User">
insert into user(username,password) VALUES(#{username},#{password})
</insert>
<delete id="deleteUser" parameterType="int">
delete from user where id = #{id}
</delete>
<update id="updateUser" parameterType="map">
update user set username=#{username} where id=#{id}
</update>
<select id="selectAllByUser" resultType="com.jiang.pojo.User">
select * from user where username like "%"#{username}"%"
</select>
<select id="selectById" parameterType="int" resultType="com.jiang.pojo.User">
select * from user where id=#{id}
</select>
<insert id="addUserIdUUID" parameterType="com.jiang.pojo.User">
insert into user2(id,username,password) VALUES(UUID(),#{username},#{password})
</insert>
</mapper>
5.编写测试类
import com.jiang.dao.UserDao;
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 com.jiang.pojo.User;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class MyTesr {
@Test
public void test() {
// 利用输入流读取对应配置
InputStream is = null;
try {
is = Resources.getResourceAsStream("mybatis-config.xml");
} catch (IOException e) {
e.printStackTrace();
}
// 利用配置文件构建SqlSessionFactory,最好用单例进行创建
SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(is);
// 打开连接 获取session,使用完必须关闭,避免资源浪费
SqlSession session = sf.openSession();
//操作数据库之前,先完成上面3步,可以考虑将其写成工具类
// 从session中实例化数据库访问接口
UserDao userDao = session.getMapper(UserDao.class);
//创建user对象 并且给对象初始化数据
User user = new User();
user.setUsername("赵日天");
user.setPassword("123456");
Integer addUser = userDao.addUser(user);
System.out.println("新增结果="+addUser);
Map<String, Object> map = new HashMap<>();
map.put("username","胡一天");
map.put("id","7");
Integer updateUser = userDao.updateUser(map);
System.out.println("修改结果="+updateUser);
List<User> selectAllUser = userDao.selectAllUser("赵");
System.out.println("模糊查询出的数据条数="+selectAllUser.size());
/**
* 在数据库的操作中:增 删 改,都需要提交数据
*/
session.commit();
//关闭数据库的链接
session.close();
}
}
3、log4j的使用
1.导入包
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2.编写 Log4j 的配置文件log4j.properties,log4j详细配置
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置,项目目录下会生成一个/log/lv.log文件,日志写入该文件
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/lv.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
3.mybatis-config.xml 中设置 setting(注意配置时的顺序位置)
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
4、编写测试类
import org.apache.log4j.Logger;
import org.junit.Test;
//@Log4j
public class LogTest {
//注意导包不要导错:org.apache.log4j.Logger
static Logger logger = Logger.getLogger(LogTest.class);//安装lombok后可以在类上面定义注解@Log4j,从而代替这行代码,写日志时用log对象进行操作
@Test
public void testLog4j(){
logger.info("info:进入了testLog4j");
logger.debug("debug:进入了testLog4j");
logger.error("error:进入了testLog4j");
}
}
4、lombok的使用
1.导入包
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
2、装插件
使用Lombok还需要插件的配合,我使用开发工具为idea. 打开idea的设置,点击Plugins,点击Browse repositories,在弹出的窗口中搜索lombok,然后安装即可.
3、可以使用注解了(用注解代替pojo的get/set等方法)
@Date: get、set、tostring、hascode、equals、无参构造
@AllArgsConstructor //全参构造
@NoArgsConstructor //无参构造
@Getter and @Setter
@ToString
5、一对多、多对一
多对一:多个学生对应一个老师: 关联 - association
一对多:一个老师对应多个学生: 集合 - collection
子查询(按照查询嵌套处理),联表查询(按照结果嵌套处理)
6、动态sql(官网动态sql)
1.if
<select id="findActiveBlogWithTitleLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
</select>
2.choose、when、otherwise,等同与swich、case,default
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<!--
当when的条件有一个满足时,就跳出choose;当when一个都没有满足时,就去到otherwise
-->
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
3.trim、where、set、sql
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<!-- 当where中有元素时,自动添加where -->
<where>
<if test="state != null">
state = #{state}
</if>
<!-- 当前一个元素不存在时,自动去除and -->
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
<update id="updateAuthorIfNecessary">
update Author
<!-- 当set中有元素时,自动添加set -->
<set>
<!-- 当后一个元素不存在,自动去除, -->
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
<update id="updateAuthorIfNecessary2">
update Author
<!-- 当set中有元素时,自动添加set -->
<set>
<!-- sql片段替换,用于提取公共部分。通过refid取找sql标签的内容,进行插入替换 -->
<include refid="qwer"></include>
</set>
where id=#{id}
</update>
<sql id="qwer">
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</sql>
<!-- 自定义set,也可以用trim自定义其他标签,prefix是前缀,suffixOverrides是后缀 -->
<trim prefix="SET" suffixOverrides=",">
...
</trim>
4.foreach
<!--用foreach拼接(1,2,3)-->
<select id="selectBy123" resultType="com.jiang.pojo.Student" parameterType="list">
select * from UACS.jx_student where id in
<foreach item="item" collection="list" open="(" close=")" index="index" separator=",">
#{item}
</foreach>
</select>
7、缓存
1.概念
是什么:存在内存中的数据,称为缓存
干什么用:使用缓存,能减少与数据库的交互,减少系统开销,提高效率
啥时候用:一般【经常查询,不经常修改的数据】使用缓存
2.一级缓存(本地缓存)
1、默认开启的,从SqlSessionFactory开启到结束有效。
2、当查询相同数据时,第二次会从缓存中读取数据。执行不相同的查询或其他任何的增删改都需要重新从数据库获取数据。从而刷新缓存
3.二级缓存(全局缓存)
1、SqlSessionFactory提交或关闭时,才会存入二级缓存。存储SQL 映射文件中的所有 select结果
2、开启全局缓存,缓存参数参见官网
SQL 映射文件(*mapper.xml)中添加一行,未设置eviction,需保证实体类序列化(implements Serializable)
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
3、当新的SqlSessionFactory查询一个已经查询过的数据时,会直接从缓存中获取。增删改则会刷新缓存
8、mybatis逆向工程
1.idea插件实现Mybatis逆向工程
- 安装插件Better-Mybatis-Generator
- IDEA连接数据库
- 在需要生成的表上右键选择mybatis-generator
- 四个文件夹选项都选项目路径即可
- 默认会在java与resources目录下新建generator,并将生成的文件放入其中
- 参考链接
2.使用逆向工程生成工具实现
1、在pom.xml中配置MyBatis逆向工程插件
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
2、在resource下新建generatorConfig.xml并做修改
<?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:\IdeaProjects\mysql-connector-java-5.1.25-bin.jar" /><!--修改1:数据驱动 -->
<context id="store" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true" />
<!-- 是否去除所有自动生成的文件的时间戳,默认为false -->
<property name="suppressDate" value="true"/>
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 --><!--修改2:数据链接信息 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://192.168.0.110:3306/UACS"
userId="root"
password="uacsapp">
</jdbcConnection>
<!-- targetPackage:包名称(自定义) targetProject:项目路径(自定义) -->
<!--定义model的包名称-->
<javaModelGenerator targetPackage="pojo" targetProject="src/main/java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- 配置生成相应的实体Mapper.xml,对于Mapper3.X我们需要把type="XMLMAPPER" -->
<!-- targetPackage:包名称(自定义) targetProject:项目路径(自定义) -->
<sqlMapGenerator targetPackage="mappers" targetProject="src/main/resources">
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- 配置生成相应的接口类,对应与Mapper.xml中的一系列CRUD方法SQL语句 -->
<!-- targetPackage:包名称(自定义) targetProject:项目路径(自定义) -->
<javaClientGenerator targetPackage="dao" targetProject="src/main/java" type="XMLMAPPER">
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名 mapperName是dao层名称--><!--修改3:表名、实体类名、dao接口名 -->
<table tableName="jx_books"
domainObjectName="jxBooks"
mapperName="jxBookDao"
enableCountByExample="false"
enableUpdateByExample="false"
enableDeleteByExample="false"
enableSelectByExample="false"
selectByExampleQueryId="false">
<!--value=true字段名和数据库列名相同,value=false则按驼峰命名(前提是数据库列名为下划线命名)-->
<property name="useActualColumnNames" value="false" />
</table>
</context>
</generatorConfiguration>
3、添加Edit Configurations
- 添加——>Maven——>Working directory选项目路径——>Command line配置mybatis-generator:generate -e
- Name名称随意(一般 generatorConfig)
- Run ‘generatorConfig’,即可生成实体类文件、Mapper文件和持久层的接口
- 参考链接
3.SpringBoot实现逆向工程
1、新建SpringBoot项目,勾选Spring Web
2、配置pom.xml
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<!-- mybatis-generator 插件 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
<configuration>
<overwrite>true</overwrite>
<configurationFile>src/main/resources/generator/generatorConfig.xml</configurationFile>
</configuration>
</plugin>
</plugins>
</build>
3、在resources包下创建一个generator文件夹,然后在文件夹中创建generatorConfig.xml文件
<?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>
<!-- 数据库驱动:选择你的本地硬盘上面的数据库驱动包-->
<classPathEntry location="D:\IdeaProjects\mysql-connector-java-5.1.25-bin.jar"/><!--修改1:数据驱动 -->
<context id="DB2Tables" targetRuntime="MyBatis3">
<!-- JavaBean 实现 序列化 接口 -->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
<!-- 生成toString -->
<plugin type="org.mybatis.generator.plugins.ToStringPlugin" />
<!-- optional,旨在创建class时,对注释进行控制 -->
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--数据库链接URL,用户名、密码 --><!--修改2:数据链接信息 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://192.168.0.110:3306/UACS"
userId="root"
password="uacsapp">
</jdbcConnection>
<!-- 类型转换 -->
<javaTypeResolver >
<!-- 是否使用bigDecimal,
false: 把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer(默认)
true: 把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal
-->
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- 生成模型的包名和位置-->
<javaModelGenerator targetPackage="com.example.demo.entity" targetProject="src/main/java">
<!-- 默认false 是否允许子包 -->
<property name="enableSubPackages" value="true" />
<!-- 默认false 是否对model添加 构造函数 -->
<property name="constructorBased" value="false"/>
<!-- 默认false 建立的Model对象是否 不可改变 即生成的Model对象不会有 setter方法,只有构造方法 -->
<property name="immutable" value="false"/>
<!-- 默认false 是否对类CHAR类型的列的数据进行trim操作 -->
<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.example.demo.dao" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名--><!--修改3 -->
<!-- <table tableName="risk_model_order" domainObjectName="DSRiskModelOrder" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="tel_bill_record" domainObjectName="DSTelBillRecord" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>-->
<table tableName="jx_books" domainObjectName="jxBooks" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
</context>
</generatorConfiguration>
4、右侧的Maven——>项目Plugins——>mybatis-generator——>mybatis-generator:generate——>Run maven build。控制台显示BUILD SUCCESS,表示创建成功。参考链接
4.常见问题
URI is not registered (Settings | Languages & Frameworks | Schemas and DTDs)