环境:
回顾:
SSM框架:配置文件
最好的方式:看官网文档
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a3i15Vzc-1666011193374)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20220925233949003.png)]
如何获得mybatis?
maven仓库
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.2version>
dependency>
GitHub:Releases · mybatis/mybatis-3 (github.com)
中文文档:mybatis – MyBatis 3 | 简介
数据持久化
为什么需要持久化?
有一些对象,不能让他丢掉
Dao层、Service层、Controller层…
帮助程序员将数据存入到数据库中
方便
传统的JDBC代码太复杂。简化。框架。自动化。
不用Mybatis也可以。更容易上手。技术没有高低之分
优点:
最重要的一点:使用的人多!
思路:搭建环境–>导入Mybatis–>编写代码–>测试
create database mytabis;
use mytabis;
create table user(
id int not null primary key ,
name varchar(30) default null,
pwd varchar(30) default null
)engine =INNODB default charset =utf8;
insert into user(id, name, pwd) VALUES (1,'西游记','吴承恩'),(2,'水浒传','施耐庵'),(3,'三国演义','罗贯中');
新建项目
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.2version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
dependencies>
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">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<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="123456"/>
dataSource>
environment>
environments>
configuration>
package com.kuang.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;
static {
try {
//使用Mybatis第一步获取sqlSessionFactory对象
String resource = "mybatis-config-xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
// SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
关于Java中static的使用有以下四种情况:
**1、静态成员变量
** 被static修饰的成员变量,叫静态成员变量或类变量;没有被static修饰的变量,叫实例变量。
两者的区别是:
静态成员变量在内存中只有一分拷贝(节省内存),JVM只为静态成员变量分配一次内存,在加载类的过程中完成静态成员变量的内存分配,可用类名直接访问(方便),当然也可以通过对象实例来访问(但是这是不推荐的)。 所以当静态成员变量内存分配好了后,所有的实例对象共同维护静态成员变量(类变量),任何一个对象对实例变量的修改都会影响到其他对象实例对该变量的访问。
对于实例变量,每创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。
**2、静态成员方法
** 静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和静态成员方法。因为实例成员与特定的对象关联!这个需要去理解,想明白其中的道理,不是记忆!!!
因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。
3、静态代码块
static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。
静态代码块在类加载时仅仅执行一次,而代码块在类加载时不执行,而是在每次对象创建时都会执行,并且先于构造函数执行。
4、静态嵌套类
为了生成对立于外部类对象的嵌套类对象,就需要将嵌套类生命为static。
实例代码:
public class Test {
// 嵌套类
public class InnerClass {
}
// 静态嵌套类
public static class StaticInnerClass {
public StaticInnerClass() {
System.out.println("--静态嵌套类构造器执行。");
}
}
// 静态成员变量
public static String param = "--静态成员变量值。";
// 静态代码块
static {
System.out.println("--静态代码块执行。");
}
// 代码块
{
System.out.println("--代码块执行。");
}
// 静态成员方法
public static void StaticMethod() {
System.out.println("--静态成员方法执行。");
}
// 构造器?
private Test() {
System.out.println("--构造器执行。");
}
// Main
public static void main(String[] args) {
Test app1 = new Test();
Test app2 = new Test();
System.out.println("------------两个对象生成完成。----------------");
// 使用类名调用静态成员方法
Test.StaticMethod();
// 使用实例对象调用静态成员方法
app1.StaticMethod();
// 使用类名调用静态成员变量
System.out.println(Test.param);
// 使用实例对象调用静态成员变量
System.out.println(app1.param);
// 所有对象共同维护静态成员变量
System.out.println(app2.param);
Test.StaticInnerClass sobj = new Test.StaticInnerClass();
}
}
运行结果:
--静态代码块执行。
--代码块执行。
--构造器执行。
--代码块执行。
--构造器执行。
------------两个对象生成完成。----------------
--静态成员方法执行。
--静态成员方法执行。
--静态成员变量值。
--静态成员变量值。
--静态成员变量值。
--静态嵌套类构造器执行。
package com.kuang.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 + '\'' +
'}';
}
}
public interface UserDao {
List<User> getUserList();
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.dao.UserDao">
<select id="getUserList" resultType="com.kaung.pojo.User">
select * from mybatis,user
select>
mapper>
package com.kuang.dao;
import com.kuang.pojo.User;
import com.kuang.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserDaoTest {
@Test
public void test(){
//第一步:获得SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//方式一:getMapper
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> userList = userDao.getUserList();
for (User user : userList) {
System.out.println(user);
}
//关闭SqlSession
sqlSession.close();
}
}
可能会遇到的问题:
选择、查询语句:
List<User> getUserList();
<select id="getUserList" resultType="com.kuang.pojo.User">
select * from mytabis.user;
select>
@Test
public void test(){
//第一步:获得SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
//方式一:getMapper
UserMapper userDao = sqlSession.getMapper(UserMapper.class);
List<User> userList = userDao.getUserList();
//方式二
// List userList = sqlSession.selectList("com.kuang.dao.getUserList");
for (User user : userList) {
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//关闭SqlSession
sqlSession.close();
}
}
User getUserById(int id);
<select id="getUserById" parameterType="int" resultType="com.kuang.pojo.User">
select * from mytabis.user where id = #{id};
select>
@Test
public void getUserById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getUserById(1);
System.out.println(user);
sqlSession.close();
}
int addUser(User user);
<insert id="addUser" parameterType="com.kuang.pojo.User">
insert into mytabis.user (id,name,pwd) values(#{id},#{name},#{pwd});
insert>
//增删改需要提交事务
@Test
public void addUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int res = mapper.addUser(new User(4, "红楼梦", "曹雪芹"));
if (res > 0) {
System.out.println("插入成功");
}
//提交事务
sqlSession.commit();
sqlSession.close();
}
修改用户
int updateUser(User user);
<update id="updateUser" parameterType="com.kuang.pojo.User">
update mytabis.user set name=#{name},pwd=#{pwd} where id = #{id};
update>
@Test
public void updateUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int res = mapper.updateUser(new User(2, "老人与海", "海明威"));
if (res > 0) {
System.out.println("修改成功");
}
sqlSession.commit();
sqlSession.close();
}
删除用户
int deleteUser(int id);
<delete id="deleteUser" parameterType="int">
delete from mytabis.user where id = #{id};
delete>
@Test
public void deleteUser() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int res = mapper.deleteUser(1);
if (res > 0) {
System.out.println("删除成功");
}
sqlSession.commit();
sqlSession.close();
}
假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应当考虑Map
//万能的Map
int addUser2(Map<String, Object> map);
<insert id="addUser" parameterType="map">
insert into mytabis.user (id,pwd) values (#{userid},#{password});
insert>
@Test
public void addUser2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<String, Object>();
map.put("userid", 5);
map.put("password", "海底两万里");
mapper.addUser2(map);
sqlSession.commit();
sqlSession.close();
}
User getUserById2(Map<String, Object> map);
<select id="getUserById2" parameterType="map" resultType="com.kuang.pojo.User">
select * from mytabis.user where id = #{helloid} and name = #{name};
select>
@Test
public void getUserById2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<String, Object>();
map.put("helloid",1);
mapper.getUserById2(map);
sqlSession.close();
}
Map传递参数,直接在sql中传递参数即可!【parameterType=“map”】
对象传递参数,直接在sql中取对象的属性即可!【parameterType=“Object”】
只有一个基本类型参数的情况下,可以直接在sql中取到!
多个参数用Map,或者注解!
模糊查询怎么写?
1. Java代码之下的时候,传递通配符%%
List<User> userList = mapper.getUserLike("%红%");
2. 在sql拼接中使用通配符
select * from mytabis.user where name like "%"{value}"%";
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
Mybatis可以适应多种环境
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
学会使用配置多套运行环境
Mybatis默认的事务管理器就是JDBC,连接池:POOLED
我们可以通过properties属性来实现引用配置文件
这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。 【db.properties】
编写一个配置文件
db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mytabis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=123456
在xml,所有的标签都可以规定其顺序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MJQE8GQr-1666011193375)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221006191843591.png)]
在核心配置中映入
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="pwd" value="123456"/>
properties>
<typeAliases>
<typeAlias type="com.kuang.pojo.User" alias="User"/>
typeAliases>
也可以指定一个包名,Mybatis会在包名下面搜索需要的Java Bean,比如:
<typeAliases>
<package name="com.kuang.pojo"/>
typeAliases>
在实体类比较少的时候,使用第一种方式
如果实体类十分多,建议使用第二种
第一种可以DIY别名,第二种则不行,如果非要改,需要在实体上增加注解
这样的话就得把xml文件里的完全限定名都改过来,不然会报错
@Alias("user") public class User {
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RNEDR34n-1666011193376)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221006200853249.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WG1yTfTs-1666011193376)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221006200917731.png)]
MapperRegistry:注册绑定我们的Mapper文件;
方式一:【推荐使用】
<mappers>
<mapper resource="com/kuang/dao/UserMapper.xml"/>
mappers>
方式二:使用class文件绑定注册
<mappers>
<mapper class="com.kuang.dao.UserMapper"/>
mappers>
注意点:
方式三:使用扫描包进行注入
<mappers>
<package name="com.kuang.dao"/>
mappers>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MzeJAxDV-1666011193377)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221006233239614.png)]
生命周期和作用域是至关重要的,因为错误的使用会导致非常严重的并发问题。
SqlSessionFactoryBuilder:
SqlSessionFactory:
SqlSession
这里面得每一个Mapper,就代表一个具体的业务
数据库中得字段
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CNRh9uUJ-1666011193377)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221006235013522.png)]
新建一个项目,拷贝之前的,测试实体类字段不一致得情况
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RzqQY80s-1666011193378)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221008195319608.png)]
测试出现问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H3eKSjDq-1666011193378)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221008195401631.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b6xryuoo-1666011193378)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221008195607937.png)]
解决方案:
<select id="getUserById" parameterType="int" resultType="com.kuang.pojo.User">
select id,name,pwd as password from mytabis.user where id = #{id};
select>
结果集映射
<resultMap id="UserMap" type="User">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="pwd" property="password"/>
resultMap>
<select id="getUserById" resultMap="UserMap">
select id,name,pwd from mytabis.user where id = #{id};
select>
resultMap
元素是 MyBatis 中最重要最强大的元素。ResultMap
的优秀之处——你完全可以不用显式地配置它们。如果一个数据库操作,出现了异常,我们需要排错。日志就是最好的助手!
曾经:sout、debug
现在:日志工厂!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZyOMiZRo-1666011193378)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221008203050761.png)]
在Mybatis中具体使用哪一个日志实现,在设置中设定
STDOUT_LOGGING标准日志输出
在mybatis核心配置文件中,配置我们的日志
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
settings>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-57grjSxB-1666011193379)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221008234815054.png)]
什么是log4j:
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
#将等级为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
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/xu.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>
4.log4j的使用,直接测试运行刚才的查询
"C:\Program Files\Java\jdk1.8.0_333\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.2\lib\idea_rt.jar=62169:C:\Program Files\JetBrains\IntelliJ IDEA 2022.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\JetBrains\IntelliJ IDEA 2022.2\lib\idea_rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2022.2\plugins\junit\lib\junit5-rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2022.2\plugins\junit\lib\junit-rt.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_333\jre\lib\rt.jar;C:\Users\22343\Desktop\EndWeb\Mybatis-Study\mybatis-03\target\test-classes;C:\Users\22343\Desktop\EndWeb\Mybatis-Study\mybatis-03\target\classes;D:\repository\log4j\log4j\1.2.17\log4j-1.2.17.jar;D:\repository\mysql\mysql-connector-java\8.0.30\mysql-connector-java-8.0.30.jar;D:\repository\com\google\protobuf\protobuf-java\3.19.4\protobuf-java-3.19.4.jar;D:\repository\org\mybatis\mybatis\3.5.11\mybatis-3.5.11.jar;D:\repository\junit\junit\4.13.2\junit-4.13.2.jar;D:\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 dao.UserDaoTest,getUserById
[org.apache.ibatis.logging.LogFactory]-Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
[org.apache.ibatis.logging.LogFactory]-Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
[org.apache.ibatis.io.VFS]-Class not found: org.jboss.vfs.VFS
[org.apache.ibatis.io.JBoss6VFS]-JBoss 6 VFS API is not available in this environment.
[org.apache.ibatis.io.VFS]-Class not found: org.jboss.vfs.VirtualFile
[org.apache.ibatis.io.VFS]-VFS implementation org.apache.ibatis.io.JBoss6VFS is not valid in this environment.
[org.apache.ibatis.io.VFS]-Using VFS adapter org.apache.ibatis.io.DefaultVFS
[org.apache.ibatis.io.DefaultVFS]-Find JAR URL: file:/C:/Users/22343/Desktop/EndWeb/Mybatis-Study/mybatis-03/target/classes/com/kuang/pojo
[org.apache.ibatis.io.DefaultVFS]-Not a JAR: file:/C:/Users/22343/Desktop/EndWeb/Mybatis-Study/mybatis-03/target/classes/com/kuang/pojo
[org.apache.ibatis.io.DefaultVFS]-Reader entry: User.class
[org.apache.ibatis.io.DefaultVFS]-Listing file:/C:/Users/22343/Desktop/EndWeb/Mybatis-Study/mybatis-03/target/classes/com/kuang/pojo
[org.apache.ibatis.io.DefaultVFS]-Find JAR URL: file:/C:/Users/22343/Desktop/EndWeb/Mybatis-Study/mybatis-03/target/classes/com/kuang/pojo/User.class
[org.apache.ibatis.io.DefaultVFS]-Not a JAR: file:/C:/Users/22343/Desktop/EndWeb/Mybatis-Study/mybatis-03/target/classes/com/kuang/pojo/User.class
[org.apache.ibatis.io.DefaultVFS]-Reader entry: ���� 4 =
[org.apache.ibatis.io.ResolverUtil]-Checking to see if class com.kuang.pojo.User matches criteria [is assignable to Object]
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.io.DefaultVFS]-Find JAR URL: file:/C:/Users/22343/Desktop/EndWeb/Mybatis-Study/mybatis-03/target/classes/com/kuang/dao
[org.apache.ibatis.io.DefaultVFS]-Not a JAR: file:/C:/Users/22343/Desktop/EndWeb/Mybatis-Study/mybatis-03/target/classes/com/kuang/dao
[org.apache.ibatis.io.DefaultVFS]-Reader entry: UserMapper.class
[org.apache.ibatis.io.DefaultVFS]-Reader entry: UserMapper.xml
[org.apache.ibatis.io.DefaultVFS]-Listing file:/C:/Users/22343/Desktop/EndWeb/Mybatis-Study/mybatis-03/target/classes/com/kuang/dao
[org.apache.ibatis.io.DefaultVFS]-Find JAR URL: file:/C:/Users/22343/Desktop/EndWeb/Mybatis-Study/mybatis-03/target/classes/com/kuang/dao/UserMapper.class
[org.apache.ibatis.io.DefaultVFS]-Not a JAR: file:/C:/Users/22343/Desktop/EndWeb/Mybatis-Study/mybatis-03/target/classes/com/kuang/dao/UserMapper.class
[org.apache.ibatis.io.DefaultVFS]-Reader entry: ���� 4
[org.apache.ibatis.io.DefaultVFS]-Find JAR URL: file:/C:/Users/22343/Desktop/EndWeb/Mybatis-Study/mybatis-03/target/classes/com/kuang/dao/UserMapper.xml
[org.apache.ibatis.io.DefaultVFS]-Not a JAR: file:/C:/Users/22343/Desktop/EndWeb/Mybatis-Study/mybatis-03/target/classes/com/kuang/dao/UserMapper.xml
[org.apache.ibatis.io.DefaultVFS]-Reader entry:
[org.apache.ibatis.io.ResolverUtil]-Checking to see if class com.kuang.dao.UserMapper matches criteria [is assignable to Object]
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection
[org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 1064265473.
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3f6f6701]
[com.kuang.dao.UserMapper.getUserById]-==> Preparing: select id,name,pwd from mytabis.user where id = ?;
[com.kuang.dao.UserMapper.getUserById]-==> Parameters: 2(Integer)
[com.kuang.dao.UserMapper.getUserById]-<== Total: 1
User{id=2, name='老人与海', password='海明威'}
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3f6f6701]
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3f6f6701]
[org.apache.ibatis.datasource.pooled.PooledDataSource]-Returned connection 1064265473 to pool.
进程已结束,退出代码0
简单使用
static Logger logger= Logger.getLogger(UserDaoTest .class);
logger.info("info:进入了testLog4j");
logger.debug("debug:进入了testLog4j");
logger.error("error:进入了testLog4j");
思考:为什么要分页?
使用limit分页
select * from mytabis.user limit startIndex,pageSize;
使用Mybatis实现分页,核心SQL
接口
List<User> getUserByLimit(Map<String, Integer> map);
Mapper.xml
<select id="getUserByLimit" parameterType="map" resultMap="UserMap">
select * from mytabis.user limit #{startIndex},#{pageSize};
select>
测试
@Test
public void getUserByLimit(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
HashMap map = new HashMap<>();
map.put("startIndex",0);
map.put("pageSize",2);
List userByLimit = mapper.getUserByLimit(map);
for (User user : userByLimit) {
System.out.println(user);
}
sqlSession.close();
}
面向接口编程的根本原因:解耦,可拓展,提高复用,分层开发中、上层不用管具体的实现,大家都遵守共同的标准,使得开发变得容易,规范性好
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yLmaPVYk-1666011193379)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221010225948263.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-raKSsk9p-1666011193379)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221010230006336.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2KF18KLI-1666011193380)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221010230018856.png)]
我们可以在工具类创建的时候实现自动提交事务!
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession(true);
}
编写接口,增加注解
@Select("select * from mytabis.user")
List<User> getUsers();
//方法存在多个参数,所有的参数前面必须加上@Param("id")注解
@Select("select * from mytabis.user where id =#{id}")
User getUserBuID(@Param("id") int id);
@Insert("insert into mytabis.user (id,name,pwd) values (#{id},#{name},#{password})")
int addUser(User user);
@Update("update mytabis.user set name=#{name},pwd=#{password} where id=#{id}")
int updateUser(User user);
@Delete("delete from mytabis.user where id = #{id}")
int deleteUser(@Param("id") int id);
测试类
【注意:我们必须要将接口注册绑定到我们的核心配置文件中】
关于@Param()注解
#{} 与 ${}的区别
使用步骤:
在IDEA中安装Lombok插件
在项目中导入lombok的jar包
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.24version>
dependency>
在实体类上加注解即可
package com.kuang.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
//实体类
//@Alias("user")
public class User {
private int id;
private String name;
private String password;
}
@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
@StandardException
@val
@var
experimental @var
@UtilityClass
@Data:无参构造,get、set、tostring、hashcode、equals
说明:
@Data:无参构造,get、set、tostring、hashcode、equals
@AllArgsConstructor
@NoArgsConstructor
@ToString
@EqualsAndHashCode
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KrykucGv-1666011193380)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221011225359600.png)]
多个学生,对应一个老师
对于学生这边而言,关联…多个学生关联一个老师【多对一】
对于老师而言,集合,一个老师有很多学生【一对多】
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mais3sRj-1666011193380)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221011232032997.png)]
use mytabis;
create table teacher(
id int not null ,
name varchar(30) default null,
primary key (id)
)engine =INNODB default charset =utf8;
insert into teacher(id, name) VALUES (1,'秦老师');
create table student
(
id int not null,
name varchar(30) default null,
tid int default null,
key fktid (tid),
primary key (id),
constraint fktid foreign key (tid) references teacher (id)
) engine = INNODB
charset = utf8;
show create table student;
INSERT INTO mytabis.student (id, name, tid) VALUES (1, '小红', 1);
INSERT INTO mytabis.student (id, name, tid) VALUES (2, '小明', 1);
INSERT INTO mytabis.student (id, name, tid) VALUES (3, '小张', 1);
INSERT INTO mytabis.student (id, name, tid) VALUES (4, '小李', 1);
INSERT INTO mytabis.student (id, name, tid) VALUES (5, '小王', 1);
<select id="getStudent" resultMap="StudentTeacher">
select * from student;
select>
<resultMap id="StudentTeacher" type="Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
resultMap>
<select id="getTeacher" resultType="Teacher">
select * from mytabis.teacher where id=#{id};
select>
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid,t.name tname,s.name sname from mytabis.student s ,teacher t where s.tid = t.id;
select>
<resultMap id="StudentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="name"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
association>
resultMap>
回顾Mysql多对一查询方式:
比如:一个老师拥有多个学生!
对于老师而言,就是一对多的关系!
1. 环境搭建,和刚才一样
实体类
package com.kuang.pojo;
import lombok.Data;
@Data
public class Student {
private int id;
private String name;
private int tid;
}
package com.kuang.pojo;
import lombok.Data;
import java.util.List;
@Data
public class Teacher {
private int id;
private String name;
//一个老师拥有多个学生
private List<Student> students;
}
注意点:
面试高频
什么是动态SQL:动态SQL就是根据不同的条件生成不同的SQL语句
在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
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;
创建一个基础工程
导包
编写配置文件
编写实体类
package com.kuang.pojo;
import lombok.Data;
import java.util.Date;
@Data
public class Blog {
private int id;
private String title;
private String author;
private Date creatTime;
private int views;
}
编写实体类对应的Mapper接口和Mapper.xml
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mytabis.blog where 1=1
<if test="title!=null">
and title = #{title}
if>
<if test="author!=null">
and author = #{author}
if>
select>
<select id="queryBlogChoose" parameterType="map" resultType="blog">
select * from mytabis.blog
<where>
<choose>
<when test="title!=null">
title=#{title}
when>
<when test="author!=author">
and author=#{author}
when>
<otherwise>
views=#{views}
otherwise>
choose>
where>
select>
<where>
<if test="title!=null">
and title = #{title}
if>
<if test="author!=null">
and author = #{author}
if>
where>
<update id="updateBlog" parameterType="map">
update mytabis.blog
<set>
<if test="title!=null">
title=#{title},
if>
<if test="author!=null">
author=#{author},
if>
set>
where id=#{id};
update>
所谓的动态SQL,本质还是SQL语句,只是我们可以在SQL层面,去执行一个逻辑代码
有的时候,我们可能会将一些功能的部分抽取出来,方便复用
使用SQL标签抽取公共部分
<sql id="if-title-author">
<if test="title!=null">
title=#{title},
if>
<if test="author!=null">
author=#{author},
if>
sql>
<include refid="if-title-author">include>
注意事项:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u72P2Ldf-1666011193381)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20221016085010919.png)]
select * from mytabis.user where 1=1 and
<foreach item="id" collection="ids"
open="(" separator="or" close=")">
#{id}
foreach>
(id=1 or id=2 or id=3)
动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了
建议:
查询:连接数据库,耗资源
一次查询的结果,给他暂存在一个可以直接收到的地方–>内存:缓存
我们再次查询相同数据的时候,直接走缓存,就不用走数据库啦