文章目录
- Mabatis入门
Mabatis入门
1.简介
1.1.什么是Mybatis
- MyBatis是一款优秀的持久化框架
- 它支持定制化SQL、存储过程以及高级映射
- Mybatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果数据集
- MyBatis可以使用简单的XML或注解来配置和映射原生类型、接口和Java的POJO为数据库中的记录。
- Mybatis本身apache的一个开源项目iBatis,2010移动google code并更名为MyBatis。
- 获取Mybatis框架,maven导入即可,使用使用人数最多的那个
1.2.持久化
数据持久化
- 持久化就是将程序的数据在持久状态和顺势状态的转化过程
- 内存:断电即失
- 数据库(JDBC),io文件持久化。
- 生活例子:罐头
1.3.持久层
Dao层,Service层,Controller层
- 完成持久化工作的代码块
- 层界限十分明显
1.4为什么需要Mybatis
- 将数据存入数据库
- 方便
- 传统的JDBC代码太复杂了。
- 不用Mybatis也可以。更容易上手。
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
- 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql。 [2]
2.搭建一个Mybatis程序
思路:搭建环境–>导入Mybatis–>编写代码–>测试!
2.1.搭建一个环境
新建项目
-
新建一个普通的mavan项目
-
删除src目录
-
导入maven依赖
<dependencies> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <!--设置mysql数据驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</version> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <!--设置mybatis依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <!-- https://mvnrepository.com/artifact/junit/junit --> <!--导入junit依赖--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
2.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"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <!--版本大于8的需要设置时区,即在后面添加&serverTimezone=UTC"--> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="z231245.."/> </dataSource> </environment> </environments> </configuration>
-
编写mabatis工具类
private static SqlSessionFactory sqlSessionFactory; static { //获取Mybatis第一步:获取sqlSessionFactory对象 String resource = "mybatis-config.xml"; //InputStream inputStream = null; try { InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } /*有了sqlSessionFactoru,就可以获得SqlSession的实例 * SqlSession完全包含了面向数据库执行SQL命令所需的所有方法 **/ /** * @return sqlSession */ public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(); }
2.3.编写代码
-
poji下的类,及数据库的对应的数据类型
package com.zeng.pojo; /** * @author zeng * @data 2021/06/30 15:51 */ public class User { private int id; private String name; private String pwd; public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } public User() { } 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 + '\'' + '}'; } }
-
DAO接口
public interface UserDao { List<User> getUser(); }
-
接口实现由原来的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接口--> <!--此处第三次时候发生过修改,namespace绑定勒指定的接口--> <mapper namespace="com.zeng.dao.UserDao"> <!--这是一个查询语句select,相当于重写getUser方法,返回类型写全限名称--> <select id="getUser" resultType="com.zeng.pojo.User"> select * from mybatis.user; </select> </mapper>
2.4.测试
-
mapporg.apache.ibatis.binding.BindingException: Type interface com.zeng.dao.UserDao is not known to the MapperRegistry需要mybatis-config.xml配置核心文件mapper
<mappers> <mapper resource="com/zeng/dao/Mapperipml.xml"/> </mappers>
-
在maven中约定大于配置,配置文件可能无法导出或者生效,解决方法
<build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> <filtering>true</filtering> </resource> </resources> </build>
-
版本问题,降版本
WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by org.apache.ibatis.reflection.Reflector (file:/D:/Program%20Files%20(x86)/software/Maven/m2/repository/org/mybatis/mybatis/3.4.6/mybatis-3.4.6.jar) to method java.lang.Class.checkPackageAccess(java.lang.SecurityManager,java.lang.ClassLoader,boolean) WARNING: Please consider reporting this to the maintainers of org.apache.ibatis.reflection.Reflector WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations WARNING: All illegal access operations will be denied in a future release Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
-
当没有依赖时自己要去添加依赖
2.5.哪些操作不需要改变
- 导入依赖包
- 工具类
- 连接Mysql库中的方法
- SQL语句
3.CRUD
3.1.namespace
- namespace中的包名要和Dao/mapper中一致
3.2.select查询语句
-
id:就是对应的namespace中的方法名;
-
resultType:sql语句执行的返回值!
-
paramentType:传入类型
<select id="getUserByid" resultType="com.zeng.pojo.User"> select * from mybatis.user where id=#{id} </select>
3.3.insert插入语句
<insert id="InsertUser" parameterType="com.zeng.pojo.User" >
insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd})
</insert>
3.4.update修改语句
<update id="UpdateUser" parameterType="com.zeng.pojo.User" >
update mybatis.user set name = #{name},pwd = #{pwd} where id = #{id};
</update>
3.5.delete删除语句
<delete id="delete" parameterType="int">
delete from mybatis.user where id=#{id};
</delete>
3.6.小结
- #{par}为par量
- 增,删,改需要提交事务才能进行
- 多个参数用map,注解
3.7使用Map传参
使用情况:当一个类的属性有多个,但只需要修改部分,参数过多
-
之中的#{parement}要与字典中的名字相对应
<insert id="InsertUserByMap" parameterType="map"> insert into mybatis.user (id, name) values (#{Userid},#{Username}) </insert>
-
使用方法,先在接口类中编写插入方法。
public void Insert2(){ SqlSession sqlSeession = Mybatis.getSqlSeession(); UserMapper mapper = sqlSeession.getMapper(UserMapper.class); Map<String,Object> map = new HashMap<>(); map.put("Username","faded"); map.put("Userid",12); mapper.InsertUserByMap(map); sqlSeession.commit(); sqlSeession.close(); }
3.8.思考
方法不能进行重载
可以直接传参数
模糊查询like,要限定内容加百分号
#{}防止注入,${}注入
4.配置解析
4.1.配置文件
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器):JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。
dataSource(数据源):用来连接数据库
databaseIdProvider(数据库厂商标识)
mappers(映射器)
4.2.环境配置
可以配置多套环境,一般两个环境,一个测试,一个正式
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="..."/>
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
4.3.属性(properties)
这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
设置好的属性可以在整个配置文件中用来替换需要动态配置的属性值。比如:
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
-
配置过程中出现的异常
- url配置问题,要把;去掉
- jdbcurl=jdbc:mysql://localhost:3306/mybatis?useSSL=true&**;useUnicode=true&;characterEncoding=UTF-8&;**serverTimezone= GMT
Caused by: com.mysql.cj.exceptions.WrongArgumentException: Malformed database URL, failed to parse the connection string near ';useUnicode=true&;characterEncoding=UTF-8&;serverTimezone=UTC}'. at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61) at com.mysql.cj.conf.ConnectionUrlParser.processKeyValuePattern(ConnectionUrlParser.java:539) at com.mysql.cj.conf.ConnectionUrlParser.parseQuerySection(ConnectionUrlParser.java:519) at com.mysql.cj.conf.ConnectionUrlParser.getProperties(ConnectionUrlParser.java:644) at com.mysql.cj.conf.ConnectionUrl.collectProperties(ConnectionUrl.java:303) at com.mysql.cj.conf.ConnectionUrl.<init>(ConnectionUrl.java:288) at com.mysql.cj.conf.url.SingleConnectionUrl.<init>(SingleConnectionUrl.java:47) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at com.mysql.cj.util.Util.handleNewInstance(Util.java:191) at com.mysql.cj.util.Util.getInstance(Util.java:166) at com.mysql.cj.util.Util.getInstance(Util.java:173) at com.mysql.cj.conf.ConnectionUrl.getConnectionUrlInstance(ConnectionUrl.java:200) at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:196)
-
细节问题
Caused by: java.sql.SQLException: Access denied for user 'root}'@'localhost' (using password: YES) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:835) at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:455) at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:240) at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:199) at java.sql.DriverManager.getConnection(DriverManager.java:664) at java.sql.DriverManager.getConnection(DriverManager.java:208) at org.apache.ibatis.datasource.unpooled.UnpooledDataSource.doGetConnection(UnpooledDataSource.java:201) at org.apache.ibatis.datasource.unpooled.UnpooledDataSource.doGetConnection(UnpooledDataSource.java:196) at org.apache.ibatis.datasource.unpooled.UnpooledDataSource.getConnection(UnpooledDataSource.java:93) at org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:404) at org.apache.ibatis.datasource.pooled.PooledDataSource.getConnection(PooledDataSource.java:90) at org.apache.ibatis.transaction.jdbc.JdbcTransaction.openConnection(JdbcTransaction.java:139) at org.apache.ibatis.transaction.jdbc.JdbcTransaction.getConnection(JdbcTransaction.java:61) at org.apache.ibatis.executor.BaseExecutor.getConnection(BaseExecutor.java:338) at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:84) at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:62) at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:326) at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156) at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109) at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:83) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:148)
<dataSource type="POOLED"> <property name="driver" value="${driver}"/> <!--主要这里不要写错了--> <property name="url" value="${jdbcurl}}"/> <property name="username" value="${username}}"/> <property name="password" value="${password}}"/> </dataSource>
-
在 properties 元素的子元素中设置和xml文件设置xml文件中优先级更高
4.4.类型别名(typeAliases)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:
<typeAliases>
<!--typealias一个类,package指定一个包-->
<!--type和alias可以调换顺序-->
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
也可以指定一个包名,扫描这个包下的类,并以首小写来代表起了一个别名,MyBatis 会在包名下面搜索需要的 Java Bean,比如
<typeAliases>
<package name="domain.blog"/>
</typeAliases>
也可以通过注解来起别名,注解优先级最高
@Alias("user")
public class User(){}
存在默认别名
4.5.设置
了解即可
4.6.其他配置
4.7.映射器
既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:///
形式的 URL),或类名和包名等。例如:
四种映射器方法:
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) 不推荐使用-->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 注意:接口和它的Mapper配置文件同名,必须在同一个包下-->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
4.8.生命周期和作用域
5.解决属性名和字段名不一致的问题,及数据库和所属类属性名不一致的情况
创建的mybatis子项目和父项目版本不一致不能导入父项目所有的依赖,可以在pom.xml中修改为相同版本即可
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
不一致问题
<!--显式设计,用as,其实默认的也是用as,但这里没有明式指出,这样如果很多属性不一致则由于麻烦,使用结果映射能解决这一问题-->
<select id="getUser" resultType="User" >
select id,name,pwd as password from mybatis.user;
</select>
resultMap,结果集映射
-
使用案例
<resultMap id="UserMap" type="User"> <!--property指类中的属性,column指数据库的列名--> <result property="password" column="pwd"/> </resultMap>
6.日志
6.1.日志工厂
为什么需要日志,使用mysql时会生成一个日志,但使用mybatis没有任何关于此的信息,就直接报错了,因此需要一个日志来记录下操作。
以前:sout,debug SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING
mybatis:日志工厂
-
SLF4J
-
LOG4J (掌握)
-
LOG4J2
-
JDK_LOGGING
-
COMMONS_LOGGING
-
STDOUT_LOGGING (标准日志输出,掌握)
-
NO_LOGGING
配置日志
<settings> <!--配置日志--> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>
6.2.LOG4J
6.2.1.介绍
Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码
6.2.2.导包
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
配置log4j.properties
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
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/kuang.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
实现
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
7.分页
为什么要分页
- 信息量太大,一个表放不下,而且也没这么多内存
- 减少处理的数据量
使用limit查询
select * from user limit 1,3;
使用mybatis 查询
ROWBOUND 分页
8.面向注解开发
8.1.面向接口编程,便于解耦
public interface UserMapper {
@Select("select * from user")
List<User> getUser();
}
<mappers>
<mapper class="com.zeng.dao.UserMapper"/>
</mappers>
简单的可以使用,复杂的话就不建议使用了
本质:反射机制实现
底层:动态代理
8.2。注解实现增删改查
首先要在xml文件中配置,绑定接口
<mappers>
<mapper class="com.zeng.dao.UserMapper"/>
</mappers>
1.查
@Select("select * from user")
List<User> getUser();
//方法存在多个参数,所有的参数前面必须加上@Param()的注解,多个参数,不用排序,参数名要和实际的参数名一致
@Select("select * from user where id = #{id}")
User getUserById(@Param("id") int id);
2.更新
//更新条目
@Update("update user set name =#{name},pwd = #{password} where id = #{id}")
void Update(User user);
3.删除
//删除
@Delete("delete from user where id = #{id}")
void Delete(@Param("id") int id);
4.增加
//增加
@Insert("insert into user (id, name, pwd) values (#{id},#{name},#{password})")
void Insert( User user);
当传入多个参数后没有参数相对应会报错
Parameter 'id' not found. Available parameters are [user, param1]
关于@Param()注解
- 基本类型的参数或者String类型需要加上
- 应用类型不需要加
- 如果为一个基本类型的话就不需要加
- @Param()设定的属性名
9.Lombok
9.1.lombok介绍
Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.
Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.
使用步骤:
-
安装插件
-
导入lombok包
-
使用
使用介绍:
@Getter and @Setter set和get方法 @FieldNameConstants @ToString 重写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)
10.多对一处理
多个学生对应一个老师
多个老师对应一个学生
集合 collection
关联 association
10.1.多对一查询
-
子查询
<!--思路:1.查询所有的学生信息 2.根据查询学生信息中的tid来选择老师 3.要事先在数据表中查询一下 -->
写法:
<resultMap id="StudentMap" type="Student"> <!--复杂属性单独处理,将一个类型对应一个tid,用association,集合用collection--> <association property="teacher" column="tid" javaType="Teacher" select="getTeacherInfo"/> </resultMap> <!--resultType需要写全路径,或者起一个别名--> <select id="getStudentInfo1" resultMap="StudentMap"> select * from student </select> <select id="getTeacherInfo" resultType="Teacher"> select * from teacher where id=#{tid} </select>
2.联表查询
<!--思路:
1.写两表查询语句
2.resultMap写相对应的属性,如果是类就将嵌套
-->
写法:
<resultMap id="StudentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
<select id="getStudentInfo2" resultMap="StudentTeacher2">
<!--注意写别名,方便识别-->
select s.id sid, s.name sname, t.name tname from student s, teacher t where s.tid = t.id;
</select>
10.2.一对多查询
-
<!--结果集查询--> <resultMap id="TeacherStudent" type="Teacher"> <result property="name" column="tname"/> <result property="id" column="tid"/> <!--注意这里用ofType--> <collection property="students" ofType="Student"> <result property="name" column="sname"/> </collection> </resultMap> <select id="getTeacherInfo" resultMap="TeacherStudent"> select t.name tname,t.id tid,s.name sname from teacher t, student s where t.id = s.tid; </select>
-
<resultMap id="TeacherStudent1" type="Teacher"> <collection property="students" column="id" ofType="Student" select="getStudentsInfo"> <result property="name" column="sname"/> </collection> </resultMap> <select id="getTeacherInfo1" resultMap="TeacherStudent1"> select * from teacher; </select> <select id="getStudentsInfo" resultType="Student"> select * from student where tid = #{id} </select>
小结:javaType用来指定类型,如果为集合则用ofType来指定类型
11.动态SQL
什么是动态SQL:按照选择条件生成的SQL语句
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
11.1.环境搭建
创建blog表和添加数据
在mysql创建一个blog表
CREATE TABLE `blog`(
`id` VARCHAR(50) NOT NULL COMMENT 博客id,
`title` VARCHAR(100) NOT NULL COMMENT 博客标题,
`author` VARCHAR(30) NOT NULL COMMENT 博客作者,
`create_time` DATETIME NOT NULL COMMENT 创建时间,
`views` INT(30) NOT NULL COMMENT 浏览量
)ENGINE=INNODB DEFAULT CHARSET=utf8
添加数据:
<insert id="InsertBlog" parameterType="Blog">
insert into mybatis.blog (id,title,author,creat_time,views) VALUES (#{id},#{title},#{author},#{creatTime},#{views})
</insert>
记得提交事务
11.2.动态SQL中if语句
<select id="queryBlog" parameterType="map" resultType="Blog">
select * from blog where 1=1
-- 原来写错了
<if test="author != null">
and author = #{author}
</if>
</select>
注意这里的where一定要写,不然会报错
set写法,更新数据库
<update id="UpdateBlogId" parameterType="map">
update mybatis.blog
<set>
<if test="author != null">
<!--不能直接赋值-->
author = #{author}
</if>
</set>
where title = #{title};
</update>
动态SQL,本质上还是SQL语句,只有我们可以在SQL层去执行一个逻辑代码
sql片段:将重复的sql语句整合起来,但这样会降低代码的可读性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A9kK2VFI-1627442149588)(D:\Program Files (x86)]\softwarefile\typorafile\Note\image-20210722194332792.png)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DTl4d545-1627442149589)(D:\Program Files (x86)]\softwarefile\typorafile\Note\image-20210722194259609.png)
foreach执行满足多个添加的语句,详细请查看官方文档
12.缓存
MyBatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制。 为了使它更加强大而且易于配置,我们对 MyBatis 3 中的缓存实现进行了许多改进。
默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。 要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:
<cache/>
基本上就是这样。这个简单语句的效果如下:
- 映射语句文件中的所有 select 语句的结果将会被缓存。
- 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
- 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
- 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
- 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
- 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。