Mybatis
1.pom.xml 基础配置:
<?x`ml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>`
<groupId>org.example</groupId>
<artifactId>MavenProject04</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>Mybatis01</module>
<module>Mybatis02</module>
<module>Mybatis03</module>
</modules>
<dependencies>
//数据库jar包
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
2.如果遇到资源无法导出的问题在pom.xml配置文件末尾加入:
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
3.mybatis-config.xml 配置文件
<?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>
//开启驼峰命名
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<properties resource="db.properties">
</properties>
<environments default="test">
<environment id="test">
<transactionManager type="JDBC"/>
<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>
<mappers>
<mapper class="dao.UserMapper"/>
</mappers>
</configuration>
4.每一个mapper.xml都要在mybatis-config.xml文件中注册
``<ma`ppers>
`5.接口对应的Mapper映射文件
<?xml version="1.0" encoding="UTF-8" ?><select id="selectUser" resultType="User">
select * from user
</select>
6.utils代码:
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;
public class MybatisUtils {
static SqlSessionFactory sqlSessionFactory;
static {
try {
String resource = "mybatis-config.xml";
InputStream inputStream;
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlsession(){
return sqlSessionFactory.openSession();
}
}
7.mapper.xml配置文件代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.dao.UserMapper">
<!--实现分页查询-->
<select id="selectUserLimit" resultType="aa" parameterType="map" >
select * from user.user limit #{startIndex},#{pageSize}
</select>
</mapper>
8.db.properties:
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone = GMT
username=root
password=123
9.log4j.properties
### 设置###
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 级别以上的日志到=log/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = log/log.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 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =log/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
10.log4j maven依赖
<!--<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.6</version>
</dependency>-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.6</version>
</dependency>
<!-- <dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>-->
复杂查询环境搭建
1.多对一:称之为关联
1.关于传参
用注解来简化xml配置的时候,@Param注解的作用是给参数命名,参数命名后就能根据名字得到参数值,正确的将参数传入sql语句中
我们先来看Mapper接口中的@Select方法
package` `Mapper;
public` `interface` `Mapper {
@Select``(``"select s_id id,s_name name,class_id classid from student where s_name= #{aaaa} and class_id = #{bbbb}"``)
``public` `Student select(``@Param``(``"aaaa"``) String name,``@Param``(``"bbbb"``)``int` `class_id);
@Delete``......
@Insert``......
}
1.@Select(…)注解的作用就是告诉mybatis框架,执行括号内的sql语句
2.s_id id,s_name name,class_id classid 格式是 字段名+属性名,例如s_id是数据库中的字段名,id是类中的属性名
这段代码的作用就是实现数据库字段名和实体类属性的一一映射,不然数据库不知道如何匹配
3.where s_name= #{aaaa} and class_id = #{bbbb} 表示sql语句要接受2个参数,一个参数名是aaaa,一个参数名是bbbb,如果要正确的传入参数,那么就要给参数命名,因为不用xml配置文件,那么我们就要用别的方式来给参数命名,这个方式就是@Param注解
4.在方法参数的前面写上@Param(“参数名”),表示给参数命名,名称就是括号中的内容
public Student select(@Param(“aaaa”) String name,@Param(“bbbb”)int class_id);
给入参 String name 命名为aaaa,然后sql语句…where s_name= #{aaaa} 中就可以根据aaaa得到参数值了
2.在控制台输出日志
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.6</version>
</dependency>
标准日志:在Mybatis-config.xml配置文件中加入
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
3.多对一查询结果处理 xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.mapper.StudentMapper">
<!--
根据查询出来的结果来嵌套处理
-->
<select id="getStudent1" resultMap="TeacherStudent1" >
select s.num snum,s.name sname,s.timi stimi,t.id tid,t.name tname
from student s,teacher t where s.timi=t.id
</select>
<resultMap id="TeacherStudent1" type="com.kuang.pojo.Student">
<result property="num" column="snum"/>
<result property="name" column="sname"/>
<result property="timi" column="stimi"/>
<association property="teacher" javaType="com.kuang.pojo.Teacher">
<result property="id" column="tid"></result>
<result property="name" column="tname"></result>
</association>
</resultMap>
<!--
查询出所有学生的信息
根据学生的timi找到对应的老师
-->
<select id="getStudent" resultMap="TeacherStudent">
select * from student
</select>
<resultMap id="TeacherStudent" type="com.kuang.pojo.Student">
<association property="teacher" column="timi" javaType="com.kuang.pojo.Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="com.kuang.pojo.Teacher">
select * from teacher where id=#{dd}
</select>
</mapper>
4.实体类
1.student
package com.kuang.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private int num;
private String name;
private int timi;
Teacher teacher;
}
2.teacher
package com.kuang.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@AllArgsConstructor
@Data
@NoArgsConstructor
public class Teacher {
private int id;
private String name;
}
2.和一对多:称之为集合
1.TeacherStudent.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.mapper.TeacherMapper">
<select id="getTeacher" resultMap="TeacherStudent1">
select s.num,s.name,s.timi,t.id,t.name from student s,
teacher t where t.id=s.timi
</select>
<!--
-->
<resultMap id="TeacherStudent1" type="com.kuang.pojo.Teacher">
<result property="id" column="t.id"/>
<result property="name" column="t.name"/>
<!--
collection:一对多
ofType:集合中泛型信息用ofType获取
-->
<collection property="student" ofType="com.kuang.pojo.Student" >
<result property="num" column="s.num"/>
<result property="name" column="s.name"/>
<result property="timi" column="s.timi"/>
</collection>
</resultMap>
</mapper>
2.student的实体类:
package com.kuang.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private int num;
private String name;
private int timi;
}
3.teacher的实体类
package com.kuang.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@AllArgsConstructor
@Data
@NoArgsConstructor
public class Teacher {
private int id;
private String name;
private List<Student> student;
}
动态sql
1.like通配符
通配符的分类:
%
百分号通配符: 表示任何字符出现任意次数 (可以是0次).
_
下划线通配符:表示只能匹配单个字符,不能多也不能少,就是一个字符.
like操作符:
LIKE作用是指示mysql后面的搜索模式是利用通配符而不是直接相等匹配进行比较.
注意: 如果在使用like操作符时,后面的没有使用通用匹配符效果是和=
一致的,SELECT * FROM products WHERE products.prod_name like '1000';
只能匹配的结果为1000
,而不能匹配像JetPack 1000
这样的结果.
1)%
通配符使用:
匹配以"yves"
开头的记录:(包括记录"yves"
)
SELECT * FROM products WHERE products.prod_name like 'yves%';
匹配包含"yves"
的记录(包括记录"yves"
)
SELECT * FROM products WHERE products.prod_name like '%yves%';
匹配以"yves"
结尾的记录(包括记录"yves"
,不包括记录"yves "
,也就是yves后面有空格的记录,这里需要注意)
SELECT * FROM products WHERE products.prod_name like '%yves';
2)_
通配符使用:
SELECT * FROM products WHERE products.prod_name like '_yves';
匹配结果为: 像"yyves"
这样记录.
SELECT * FROM products WHERE products.prod_name like 'yves__';
匹配结果为: 像"yvesHe"
这样的记录.(一个下划线只能匹配一个字符,不能多也不能少)
注意事项:
- 注意大小写,在使用模糊匹配时,也就是匹配文本时,mysql是可能区分大小的,也可能是不区分大小写的,这个结果是取决于用户对MySQL的配置方式.如果是区分大小写,那么像
YvesHe
这样记录是不能被"yves__"
这样的匹配条件匹配的. - 注意尾部空格,
"%yves"
是不能匹配"heyves "
这样的记录的. - 注意NULL,
%
通配符可以匹配任意字符,但是不能匹配NULL,也就是说SELECT * FROM products WHERE products.prod_name like '%';
是匹配不到products.prod_name
为NULL的的记录.
技巧与建议:
正如所见, MySQL的通配符很有用。但这种功能是有代价的:通配符搜索的处理一般要比前面讨论的其他搜索所花时间更长。这里给出一些使用通配符要记住的技巧。
- 不要过度使用通配符。如果其他操作符能达到相同的目的,应该 使用其他操作符。
- 在确实需要使用通配符时,除非绝对有必要,否则不要把它们用 在搜索模式的开始处。把通配符置于搜索模式的开始处,搜索起 来是最慢的。
- 仔细注意通配符的位置。如果放错地方,可能不会返回想要的数.
2.IF
<if test="bookName != null">
bookName like #{bookName}
</if>
<if test="bookCount != null">
AND bookCounts like #{bookCount}
</if>
3.trim、where、set
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
<trim prefix="SET" suffixOverrides=",">
...
</trim>
4.choose、when、otherwise
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
<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>
5.sql片段
提取公共部分实现代码复用
<sql id="bookName">将公共部分代码放入sql中,要用的地方加入<include></include标签
<if test="bookName != null">
bookName like #{bookName}
</if>
</sql>
<include refid="bookName"></include>
6.froeach循环(报错)
select * from books
<where> //collection是map传输进来的
<foreach collection="list" item="id" open="and (" separator="," close=")">
#{goodsId}>
bookId=#{id}
</foreach>
</where>
SqlSession sqlsession = MybatisUtils.getSqlsession();
BookMapper bookmapper = sqlsession.getMapper(BookMapper.class);
Map map=new HashMap();
//map.put("bookName","Mysql数据库");
// map.put("bookCount",3);
ArrayList<Integer> list=new ArrayList<Integer>();
list.add(2);
list.add(4);
map.put("list",list);
List<Book> books = bookmapper.SelectBook(map);
for (Book bookList: books
) {
System.out.println(bookList);
7.缓存
什么是缓存:存在内存中的临时数据
为什么使用缓存:减少用户与数据库的交互次数,减少系统开销,提高效率
什么时候使用缓存:经常查询且不改变的数据
mybati自带一级缓存和二级缓存。
1.一级缓存:默认情况是开启的(sqlSession级别缓存,又称本地缓存)
SqlSession sqlsession= MybatisUtils.getsqlSession();
UserMapper usermapper=sqlsession.getMapper(UserMapper.class);
List<User>userlist=usermapper.selectUserList();
for (User user:userlist
) {
System.out.println(user);
}
sqlsession.clearCache();//清楚缓存,缓存数据不存在
List<User>userlist1=usermapper.selectUserList();
for (User user:userlist1
) {
System.out.println(user);
}
System.out.println(userlist==userlist1);
sqlsession.close();
2.二级缓存:需要手动开启,基于namespace级别。
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。
3.缓存的实现原理
serList();
for (User user:userlist
) {
System.out.println(user);
}
sqlsession.clearCache();//清楚缓存,缓存数据不存在
List<User>userlist1=usermapper.selectUserList();
for (User user:userlist1
) {
System.out.println(user);
}
System.out.println(userlist==userlist1);
sqlsession.close();
### 2.二级缓存:需要手动开启,基于namespace级别。
这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。
3.缓存的实现原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XGC8juy0-1604053421343)(C:\Users\asus\AppData\Roaming\Typora\typora-user-images\image-20201014135315075.png)]