SSM-MyBatis
1、简介:
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
-
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。
-
MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集
-
。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),用于实现面向对象编程语言里不同类型系统的数据之间的转换。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象与关系数据库相互映射。
配置:
-
maven:
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency>
-
github:
https://github.com/mybatis/mybatis-3/releases/tag/mybatis-3.5.4
-
中文文档
2、持久化:
数据持久化:
-
持久化就是将程序的数据在吃就状态和瞬时状态转化的过程
-
内存:断电即失
-
数据库(JDBC)、io文件持久化
为什么需要持久化:
-
有一些对象,不能让他丢掉
-
内存太贵了
持久层:
-
Dao层、Service层、Controller层...
3、第一个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核心配置文件--> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&characterEncoding=utf-8&useSSL=true&useUnicode=true"/> <property name="username" value="root"/> <property name="password" value="979416"/> </dataSource> </environment> </environments> </configuration>
-
创建一个模块
package com.xsw.utils;
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 java.io.IOException; import java.io.InputStream; //SqlSessionFactory -->SqlSession public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory; { //使用Mybatis第一步:获取SqlSessionFactory对象 try { String resource = "mybatis-config.xml"; InputStream inputStream; inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } //既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。 // SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。 public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }
-
编写代码
3.1实体类
package com.xsw.pojo; //实体类 public class User { private int id; private String name; private String pwd; public User() { } public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } }
3.2Dao接口
public interface UserDao { List<User> getUserList(); }
3.3接口实现类由原来的UserDaoImpl转变成一个Mapper配置文件
<?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接口--> <mapper namespace="com.xsw.Dao.UserDao"> <select id="getUserList" resultType="com.xsw.pojo.User"> select * from mybatis.user </select> </mapper>
-
测试
-
注意点:
org.apache.ibatis.binding.BindingException: Type interface com.xsw.Dao.UserDao is not known to the MapperRegistry.
MapperRegistry是什么?
-
-
junit测试
可能会遇到的问题:
-
配置文件没有注册
-
绑定接口错误
-
方法名不对
-
返回类型不对
-
Maven到处资源问题
4、万能的Map
假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应当考虑使用Map!
int addUser2(Map<String,Object> map);
<insert id="addUser2" parameterType="map">
insert into user (id,name,pwd) value (#{Userid},#{Username},#{Userpwd})
</insert>
-
Map传递参数,直接在sql中取出key即可! 【parameteType="map"】
-
对象传递参数,直接在sql中取对象即可!【parameteType="Object"】
-
只有一个基本类型参数的情况下,可以直接在sql中取到
<!--每一个Mapper.xml配置文件都需要再Mybatis核心配置文件中注册--> <mappers> <mapper resource="com/xsw/Dao/UserMapper.xml"/> </mappers> <!--在build中配置resuorces,来防止我们的资源导出失败--> <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> </build>
5、模糊查询
-
模糊查询怎么写
-
在java代码中使用通配符 %%
List<User> userList = mapper.getUserLike("%x%");
-
在sql中使用字符串拼接
select * from mybatis.user where name like "%"#{value}"%"
-
6、配置解析
-
核心配置文件
-
mybatis-config.xml
-
MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
-
-
环境配置
MyBatis 可以配置成适应多种环境
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
学会使用配置多套运行环境!
Mybatis默认的事务管理器就是 JDBC ,连接池 POOLED
-
属性(properties)
-
我们可以通过properties属性来实现引用配置文件
-
这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。
-
编写一个配置文件
db.properties
<properties resource="org/mybatis/example/config.properties"> <property name="username" value="dev_user"/> <property name="password" value="F2Fa3!33TYyg"/> </properties>
-
可以直接使用引入的外部文件
-
可以在其中增加一些属性配置
-
如果两个文件有同一个字段,优先使用外部配置文件的!
-
-
-
类型别名(typeAliases)
-
类型别名可为 Java 类型设置一个缩写名字
-
它仅用于 XML 配置,意在降低冗余的全限定类名书写
<!--可以给实体类起别名--> <typeAliases> <typeAlias type="com.xsw.pojo.User" alias="User" /> </typeAliases> 也可以指定一个包名,Mybati
s会在包名下面直接搜索需要的Java Bean,比如:
扫描实体类的包,它的默认别名就为这个类的类名,首字母小写!
<typeAliases> <package name="com.xsw.pojo"/> </typeAliases>
在实体类比较少的时候 使用第一种
在实体类比较多的时候 建议使用第二种
第一种可以DIY别名
第二种不行 如果非要修改 则使用注解
-
-
设置(settings)
-
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。
-
-
其他设置
typeHandlers(类型处理器) objectFactory(对象工厂) plugins(插件) mybatis-generator-core mybatis-plus 通用mapper
-
映射器(mappers)
MapperRegistry:注册绑定我们的Mapper文件;
-
方式一:
<mappers> <mapper resource="com/xsw/Dao/UserMapper.xml"/> </mappers>
-
方式二:
<!-- 使用映射器接口实现类的完全限定类名 --> <mappers> <mapper class="org.mybatis.builder.AuthorMapper"/> <mapper class="org.mybatis.builder.BlogMapper"/> <mapper class="org.mybatis.builder.PostMapper"/> </mappers>
注意点:
-
接口和他的Mapper配置文件必须同名
-
接口和他的Mapper配置文件必须在同一个包下
-
-
方式三
<!-- 将包内的映射器接口实现全部注册为映射器 --> <mappers> <package name="org.mybatis.builder"/> </mappers>
注意点:
-
接口和他的Mapper配置文件必须同名
-
接口和他的Mapper配置文件必须在同一个包下
-
-
7、生命周期和作用域
作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。
SqlSessionFactoryBuilder
-
这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。
-
局部变量
SqlSessionFactory
-
说白了就是可以想象为:数据库连接池
-
SqlSessionFactory一旦被创建就应该在应用运行期间一直存在,没有任何理由丢弃它或者重新创建另一个实例
-
因此 SqlSessionFactory 的最佳作用域是应用作用域。
-
最简单的就是使用单例模式或者静态单例模式。
SqlSession
-
连接到连接池的一个请求
-
SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
-
用完之后赶紧关闭,否则资源被占用
8、resultMap 结果映射
id name pwd id name password <!--column 数据库中的字段,property 实体类中的属性--> <resultMap id="map" type="User"> <id property="id" column="id" /> <result property="name" column="name"/> <result property="password" column="pwd"/> </resultMap> <select id="selectUsers" resultType="map"> select id, username, hashedPassword from some_table where id = #{id} </select>
-
resultMap 元素是MyBatis 中最重要最强大的元素
-
ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
-
resultMap 最优秀的地方在于,虽然你已经对它相当了解,但是根本就不需要显示的用到他们
9、日志
-
日志工厂
-
SLF4J
-
LOG4J 【掌握】
-
LOG4J2
-
JDK_LOGGING
-
COMMONS_LOGGING
-
STDOUT_LOGGING 【掌握】
-
NO_LOGGING
在mybatis中具体使用哪个日志工厂,在设置中设定
STDOUT_LOGGING标准日志输出
-
-
日志的使用
-
导包
<dependencies> <!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies>
-
编写log4j配置文件
### 设置### log4j.rootLogger = debug,stdout,D,E ### 输出信息到控制抬 ### log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target = System.out log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n ### 输出DEBUG 级别以上的日志到=/home/duqi/logs/debug.log ### log4j.appender.D = org.apache.log4j.DailyRollingFileAppender log4j.appender.D.File = /home/duqi/logs/debug.log log4j.appender.D.Append = true log4j.appender.D.Threshold = DEBUG log4j.appender.D.layout = org.apache.log4j.PatternLayout log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n ### 输出ERROR 级别以上的日志到=/home/admin/logs/error.log ### log4j.appender.E = org.apache.log4j.DailyRollingFileAppender log4j.appender.E.File =/home/admin/logs/error.log log4j.appender.E.Append = true log4j.appender.E.Threshold = ERROR log4j.appender.E.layout = org.apache.log4j.PatternLayout log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
-
设置setting
<settings> <setting name="logImpl" value="LOG4J2"/> </settings>
-
编写测试类
//导包注意不要导java.util的包 import org.apache.log4j.Logger; @Test public void testLog4j(){ static Logger logger = LogManager.getLogger(UserDaoTest.class); logger.info("info:进入了testLog4j"); logger.debug("debug:进入了testLog4j"); logger.error("error:进入了testLog4j"); }
-
10、分页
减少数据得处理量使用分页
-
使用Limit分页
--语法:
select * from user limit startIndex,pageSize;
11、使用注解开发
注解实现增删改查
-
设置为自动提交
public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(true); }
-
编写实体类
//查询全部用户 @Select("select*from user") List<User> getUserList(); //根据id进行查询 @Select("select*from user where id=#{id}") User getUserById(@Param("id" +"") int id);
-
测试
@Test public void getUserList(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userList = mapper.getUserList(); for (User user : userList) { System.out.println(user); } sqlSession.close(); }
注意:我们必须要将接口注册绑定到我们的核心配置文件中!
关于@Param()注解:
-
基本类型的参数或者String类型,需要加上
-
引用类型不需要加
-
如果只有一个基本类型的话,可以忽略.......但是建议加上
-
我们在SQL中引用的就是我们这里的@Param()中设定的属性
-
#{} ${} 区别
-
#{} 有防止SQL注入
-
${} 无法防止SQL注入
12、Lombok (偷懒专用)
说明:不用写 构造方法 set get..... 只需要添加注解即可
-
导入Lombok jar包
-
添加Lombok
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> <scope>provided</scope> </dependency>
-
添加注解
@Getter and @Setter @FieldNameConstants @ToString @EqualsAndHashCode @AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor @Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog @Data @Builder @SuperBuilder @Singular @Delegate @Value @Accessors @Wither @With @SneakyThrows @val @var experimental @var @UtilityClass Lombok config system Code inspections Refactoring actions (lombok and delombok)
13、多对一的处理
-
多对一
14、动态 SQL
什么是动态 SQL:动态SQL就是指根据不同的条件生成不同的SQL语句
利用动态 SQL,可以彻底摆脱这种痛苦。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。 if choose (when, otherwise) trim (where, set) foreach
14.1 if
使用动态 SQL 最常见情景是根据条件包含 where 子句的一部分。比如:
<select id="findActiveBlogWithTitleLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <if test="title != null"> AND title like #{title} </if> </select>
14.2 choose、when、otherwise
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
还是上面的例子,但是策略变为:传入了 “title” 就按 “title” 查找,传入了 “author” 就按 “author” 查找的情形。若两者都没有传入,就返回标记为 featured 的 BLOG(这可能是管理员认为,与其返回大量的无意义随机 Blog,还不如返回一些由管理员挑选的 Blog)。
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <choose> <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>
14.3 trim、where、set