环境:
回顾:
SSM框架:配置文件
最好的方式:看官网文档
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a3i15Vzc-1666011193374)(C:\Users\22343\AppData\Roaming\Typora\typora-user-images\image-20220925233949003.png)]
如何获得mybatis?
maven仓库
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
数据持久化
为什么需要持久化?
有一些对象,不能让他丢掉
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>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--mybatis-->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!--Junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<?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核心配置文件-->
<configuration>
<environments default="development">
<environment id="development">
<!--transactionManager事务管理-->
<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();
}
<?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">
<!--namespace=绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.kuang.dao.UserDao">
<!--select 查询语句-->
<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<User> 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文件;
方式一:【推荐使用】
<!--每一个Mapper.XML都需要在Mybatis核心配置文件中注册!-->
<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">
<!--column数据库中的字段,property实体类中的属性-->
<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>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</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: <?xml version="1.0" encoding="UTF-8" ?>
[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<String, Integer> map = new HashMap<>();
map.put("startIndex",0);
map.put("pageSize",2);
List<User> 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.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</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
集合:collection
-->
<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的格式,去排列组合就可以了
建议:
查询:连接数据库,耗资源
一次查询的结果,给他暂存在一个可以直接收到的地方–>内存:缓存
我们再次查询相同数据的时候,直接走缓存,就不用走数据库啦
文章浏览阅读3.4k次,点赞8次,收藏42次。一、什么是内部类?or 内部类的概念内部类是定义在另一个类中的类;下面类TestB是类TestA的内部类。即内部类对象引用了实例化该内部对象的外围类对象。public class TestA{ class TestB {}}二、 为什么需要内部类?or 内部类有什么作用?1、 内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据。2、内部类可以对同一个包中的其他类隐藏起来。3、 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。三、 内部类的分类成员内部_成员内部类和局部内部类的区别
文章浏览阅读118次。分布式系统要求拆分分布式思想的实质搭配要求分布式系统要求按照某些特定的规则将项目进行拆分。如果将一个项目的所有模板功能都写到一起,当某个模块出现问题时将直接导致整个服务器出现问题。拆分按照业务拆分为不同的服务器,有效的降低系统架构的耦合性在业务拆分的基础上可按照代码层级进行拆分(view、controller、service、pojo)分布式思想的实质分布式思想的实质是为了系统的..._分布式系统运维工具
文章浏览阅读174次。1.数据源准备2.数据处理step1:数据表处理应用函数:①VLOOKUP函数; ② CONCATENATE函数终表:step2:数据透视表统计分析(1) 透视表汇总不同渠道用户数, 金额(2)透视表汇总不同日期购买用户数,金额(3)透视表汇总不同用户购买订单数,金额step3:讲第二步结果可视化, 比如, 柱形图(1)不同渠道用户数, 金额(2)不同日期..._exce l趋势分析数据量
文章浏览阅读3.3k次。堡垒机可以为企业实现服务器、网络设备、数据库、安全设备等的集中管控和安全可靠运行,帮助IT运维人员提高工作效率。通俗来说,就是用来控制哪些人可以登录哪些资产(事先防范和事中控制),以及录像记录登录资产后做了什么事情(事后溯源)。由于堡垒机内部保存着企业所有的设备资产和权限关系,是企业内部信息安全的重要一环。但目前出现的以下问题产生了很大安全隐患:密码设置过于简单,容易被暴力破解;为方便记忆,设置统一的密码,一旦单点被破,极易引发全面危机。在单一的静态密码验证机制下,登录密码是堡垒机安全的唯一_horizon宁盾双因素配置
文章浏览阅读7.7k次,点赞4次,收藏16次。Chrome作为一款挺不错的浏览器,其有着诸多的优良特性,并且支持跨平台。其支持(Windows、Linux、Mac OS X、BSD、Android),在绝大多数情况下,其的安装都很简单,但有时会由于网络原因,无法安装,所以在这里总结下Chrome的安装。Windows下的安装:在线安装:离线安装:Linux下的安装:在线安装:离线安装:..._chrome linux debian离线安装依赖
文章浏览阅读153次。中国发达城市榜单每天都在刷新,但无非是北上广轮流坐庄。北京拥有最顶尖的文化资源,上海是“摩登”的国际化大都市,广州是活力四射的千年商都。GDP和发展潜力是衡量城市的数字指...
文章浏览阅读3.3k次。前言spark在java使用比较少,多是scala的用法,我这里介绍一下我在项目中使用的代码配置详细算法的使用请点击我主页列表查看版本jar版本说明spark3.0.1scala2.12这个版本注意和spark版本对应,只是为了引jar包springboot版本2.3.2.RELEASEmaven<!-- spark --> <dependency> <gro_使用java调用spark注册进去的程序
文章浏览阅读4.8k次。汽车零部件开发工具巨头V公司全套bootloader中UDS协议栈源代码,自己完成底层外设驱动开发后,集成即可使用,代码精简高效,大厂出品有量产保证。:139800617636213023darcy169_uds协议栈 源代码
文章浏览阅读4.6k次,点赞20次,收藏148次。AUTOSAR基础篇之OS(下)前言首先,请问大家几个小小的问题,你清楚:你知道多核OS在什么场景下使用吗?多核系统OS又是如何协同启动或者关闭的呢?AUTOSAR OS存在哪些功能安全等方面的要求呢?多核OS之间的启动关闭与单核相比又存在哪些异同呢?。。。。。。今天,我们来一起探索并回答这些问题。为了便于大家理解,以下是本文的主题大纲:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JCXrdI0k-1636287756923)(https://gite_autosar 定义了 5 种多核支持类型
文章浏览阅读2.2k次,点赞6次,收藏14次。原因:自己写的头文件没有被加入到方案的包含目录中去,无法被检索到,也就无法打开。将自己写的头文件都放入header files。然后在VS界面上,右键方案名,点击属性。将自己头文件夹的目录添加进去。_vs2013打不开自己定义的头文件
文章浏览阅读3.3w次,点赞80次,收藏342次。此时,可以将系统中所有用户的 Session 数据全部保存到 Redis 中,用户在提交新的请求后,系统先从Redis 中查找相应的Session 数据,如果存在,则再进行相关操作,否则跳转到登录页面。此时,可以将系统中所有用户的 Session 数据全部保存到 Redis 中,用户在提交新的请求后,系统先从Redis 中查找相应的Session 数据,如果存在,则再进行相关操作,否则跳转到登录页面。当数据量很大时,count 的数量的指定可能会不起作用,Redis 会自动调整每次的遍历数目。_redis命令
文章浏览阅读449次,点赞3次,收藏3次。URP的设计目标是在保持高性能的同时,提供更多的渲染功能和自定义选项。与普通项目相比,会多出Presets文件夹,里面包含着一些设置,包括本色,声音,法线,贴图等设置。全局只有主光源和附加光源,主光源只支持平行光,附加光源数量有限制,主光源和附加光源在一次Pass中可以一起着色。URP:全局只有主光源和附加光源,主光源只支持平行光,附加光源数量有限制,一次Pass可以计算多个光源。可编程渲染管线:渲染策略是可以供程序员定制的,可以定制的有:光照计算和光源,深度测试,摄像机光照烘焙,后期处理策略等等。_urp渲染管线