Mybatis
一、步骤
1、resources目录
放在resources下的文件相当于放在java类根目录下
2、开发步骤
第一步:打包方式jar
第二步:加入依赖mybatis和Mysql驱动
第三步:配置mybatis-config.xml(一般放于resources下)
第四步:编写XxxMapper.xml文件(编写SQL语句,放于类根目录下)
第五步:在mybatis-config.xml文件中指定XxxMapper.xml的路径(<Mapper resource=” ”>其中resource属性默认是从根路径下)
第六步:编写Mybatis程序。
注意:Sqlsession是专用用来执行SQL语句的,是数据库和Java程序一次连接。要想获得Sqlsession对象,首先要获得SqlSessionFactory对象,通过SqlSessionFactory工厂来产生一个Sqlsession对象。要想获得SqlSessionFactory对象,首先要获得SqlSessionFactoryBuilder对象,通过SqlSessionFactoryBuilder对象的build方法来获得
Mybatis的核心:SqlSessionFactoryBuilder、SqlSessionFactory、Sqlsession
public static void main(String[] args) {
SqlSession sqlSession=null;
try{
//获得SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
//获得SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory=sqlSessionFactoryBuilder.build(Resources.getResourceAsStream ("mybatis-config.xml"));
//获得Sqlsession对象
sqlSession =sqlSessionFactory.openSession();
//执行SQL语句
int number=sqlSession.insert("insertUser");//XxxMapper.xml中insert的id
System.out.println("提交成功");
//手动提交
sqlSession.commit();
}catch(Exception e) {
if (sqlSession != null) {
sqlSession.rollback();
}
e.printStackTrace();
}finally{
if(sqlSession!=null){
sqlSession.close();
}
}
}
3、从xml中构建SqlSessionFactory
4、Mybatis中有两个主要的文件
mybatis-config.xml用来配置数据库信息
XxxMapper.xml专门用来写SQL语句(一个表对应一个xml)
5、Mybatis的事务管理
<transactionManager type="JDBC"/>
(1)JDBC:默认conn.setAutoCommit(false)开启事务
手动提交conn.commit();
(2)MANAGED:表示事务让其他来管,如spring
6、Junit单元测试
7、Mybatis集成日志组件
在mybatis-config.xml中<configuration>
的<settings>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
logback是目前日志框架中性能较好的,较流行的,所以我们选它。
引入logback的步骤:
第一步:引入logback相关依赖
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
第二步:引入logback相关配置文件(文件名叫做logback.xml或logback-test.xml,放到类路径当中)
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>100MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!--mybatis log configure-->
<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
<!-- 日志输出级别,logback日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR -->
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
二、工具类
public class SqlSessionUtil {
private SqlSessionUtil(){}
private static SqlSessionFactory sqlSessionFactory;
static{
try {
sqlSessionFactory=new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream
("mybatis-config.xml"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static SqlSession opensession(){
return sqlSessionFactory.openSession();
}
}
public static void main(String[] args) {
SqlSession sqlSession=SqlSessionUtil.opensession();
//执行SQL语句
int number=sqlSession.insert("insertUser");//XxxMapper.xml中insert的id
System.out.println("提交成功");
//手动提交
sqlSession.commit();
sqlSession.close();
}
三、传参
占位符:#{}
1、Java程序中可以用Map给SQL语句的占位符传值:
Map<String,Object> map=new HashMap<>();
map.put(“carName”,”比亚迪”);
map.put(“carNumber”,”1000”);
Insert into car(id,car_name,car_number) value(null,${carName},${carNumber});
2、Java类给SQL语句的占位符传值:
public class car{
private Long id;
private String carName;
private Long carNumber;
//get和set方法
}
<insert id="insertcar">
Insert into car(id,car_name,car_number) value(null,${carName},${carNumber});
</insert>
@Test
public void fun(){
Car car=new car(null,比亚迪,1000);
sqlSession.insert(“insertcar”,car);
}
注:
1、${ }
里面的是,getXxx()去掉get再小写。即${xxx}
2、其中delete语句的where id = ${可以任意命名}
3、查询所有用List<类>
4、对于不同的namespace,使用:使用它时用namespace+id,例如sqlSession.insert(“namespace.insertcar”,car)
四、配置多环境
<environments default="development">
<!--default指定时某认环境id-->
<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/mybatisstudy?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
注:environment 可以多个环境,一个数据库对应一个SqlSessionFctory对象
使用:SqlSessionFactoryBuilder().build(Resources.getResourceAsStream(“mybatis-config.xml”),“指定的环境id”)
(1)transactionManager 标签
1、作用:配置事务管理器,指定mybatis使用什么方式去管理
2、JDBC或MANAGED
(2)dataSource标签
提供Connection对象的数据源。dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
大多数 MyBatis 应用程序会按示例中的例子来配置数据源。虽然数据源配置是可选的,但如果要启用延迟加载特性,就必须配置数据源。
有三种内建的数据源类型(也就是 type=“[UNPOOLED|POOLED|JNDI]”):
UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。 性能表现则依赖于使用的数据库,对某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。UNPOOLED 类型的数据源仅仅需要配置以下 5 种属性:
driver – 这是 JDBC 驱动的 Java 类全限定名(并不是 JDBC 驱动中可能包含的数据源类)。
url – 这是数据库的 JDBC URL 地址。
username – 登录数据库的用户名。
password – 登录数据库的密码。
defaultTransactionIsolationLevel – 默认的连接事务隔离级别。
defaultNetworkTimeout – 等待数据库
(3)properties标签
1、正常情况下:
<!-- 配置数据源 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisstudy?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
2、但可以采用变量:
<properties>
<property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatisstudy?useSSL=false"/>
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="123456"/>
</properties>
<!-- 配置数据源 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
3、还可采用配置文件jdbc.properties来配置
在配置文件中写入参数
jdbc.driver=com.mysql.jdbc.Drive
jdbc.url=jdbc:mysql://localhost:3306/mybatisstudy?useSSL=false
jdbc.username=root
jdbc.password=123456
再到mybatis-config.xml中引入 <properties resource="jdbc.properties"/>
注:resource是相当路径而url是绝对路径
(4)mapper标签
<!-- 配置映射器 -->
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
是来映射SQL语句的xml文件
resource:这种从根路径下开始查找资源
url:这种方式是绝对路径
class:写全限定接口名,这个位置提供的是mapper接口的全限定接口名,必须带有包名
四、web中应用
1、步骤:
(1)maven中导入依赖,mybatis、MySQL、logbcak、servlet
(2)配置tomcat和development
(3)新建包:com.公司.项目名.dao/pojo/service/utils/web
(4)核心配置文件xml
2、在Html中
<form action="/项目名/服务名" method="post">
<input type="text" name="text1">
<input type="text" name="text2">
<input type="text" name="number">
<input type="submit" value="转账">
</form>
3、在web包中继承HttpServlet获取数据
@WebServlet("/服务名")
public class servlet extends HttpServlet {
private Service service=new ServiceImpl();
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException {
//1、获取表单数据
String text1=request.getParameter("text1");
String text2=request.getParameter("text2");
double number=Double.parseDouble(request.getParameter("number"));
//2、调用service(调业务层)
response.sendRedirect(request.getContextPath()+"/页面路径");
}
}
4、在service中用接口
public interface Service{
void funtion(String text1,String text2,double number);
}
5、在service/impl中实现
public class ServiceImpl implements Service{
private ServiceDao dao=new DaoImpl();
@Override
public void funtion(String text1,String text2,double number){
类名 类名=dao.selectById(text1);
//书写各种方法
}
}
6、在dao创建接口
public interface ServiceDao{
类名 selectById(String id);
}
7、在dao/Impl中实现dao接口
public class DaoImpl implements ServiceDao{
@Override
public 类名 selectById(String id){
SqlSession sqlSession= SqlSessionUtil.opensession();
类名 类名=(类)sqlSession.select("selectById",类中的id名);
return null;
}
}
8、在类Mapper.xml中书写SQL语句
<select id="selectById" resultType="com.公司.项目名.pojo.类名">
select * from 表名 where id=#{属性名}
</select>
注:namespace中必须是Dao类的名字,例如com.powernode.bank.AccountDao
Id必须是方法名/函数名,例如selectById
9、注意事务的提交
应该将SqlSessionUtil中
public class SqlSessionUtil {
private SqlSessionUtil(){}
private static SqlSessionFactory sqlSessionFactory;
static{
try {
sqlSessionFactory=new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static ThreadLocal<SqlSession> loacl=new ThreadLocal<SqlSession>();
public static SqlSession opensession(){
SqlSession sqlSession=loacl.get();
if (sqlSession==null){
sqlSession=sqlSessionFactory.openSession();
//将sqlSession与线程绑定
loacl.set(sqlSession);
}
return sqlSession;
}
public static void close(SqlSession sqlSession){
if(sqlSession!=null){
sqlSession.close();
//移除sqlSession与线程绑定
loacl.remove();
}
}
}
五、自动生成类
package com.wms.common;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
// 演示例子,执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
public class CodeGenerator {
/**
* <p>
* 读取控制台内容
* </p>
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入" + tip + ":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotBlank(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir")+"/wms";//生成的代码找到wms文件
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("wms");
gc.setOpen(false);
// gc.setSwagger2(true); 实体属性 Swagger2 注解
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/wms?useUnicode=true&useSSL=false&characterEncoding=utf8");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
//pc.setModuleName(scanner("模块名"));
pc.setParent("com.wms")
.setEntity("entity")
.setMapper("mapper")
.setService("service")
.setServiceImpl("service.impl")
.setController("controller");
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
// 如果模板引擎是 freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 如果模板引擎是 velocity
// String templatePath = "/templates/mapper.xml.vm";
// 自定义输出配置
List<FileOutConfig> focList = new ArrayList<>();
// 自定义配置会被优先输出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
/*
cfg.setFileCreate(new IFileCreate() {
@Override
public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
// 判断自定义文件夹是否需要创建
checkDir("调用默认方法创建的目录,自定义目录用");
if (fileType == FileType.MAPPER) {
// 已经生成 mapper 文件判断存在,不想重新生成返回 false
return !new File(filePath).exists();
}
// 允许生成模板文件
return true;
}
});
*/
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
// 配置自定义输出模板
//指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
// templateConfig.setEntity("templates/entity2.java");
// templateConfig.setService();
// templateConfig.setController();
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
// strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
// 公共父类
// strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
// 写于父类中的公共字段
// strategy.setSuperEntityColumns("id");
strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}
六、javassist动态生成类
导入依赖javassist帮助生成class
七、${}和#{}的注意
注:#{}
:底层使用的是PreparedStatement。特点:先进行SQL语句的编译,然后给SQL语句的占位符?传值,可以避免SQL注入的风险
${}
:底层使用的是Statement。特点:先进行SQL语句的拼接,然后再对SQL语句进行编译。存在SQL注入的风险.
用#{}
则是传值,如:str =“123,456”到#{str}
则是,先去掉双引号再加上单引号,即‘123,456’
而${}
可以进行拼接,如:str =“123,456”到${str}
则是,直接去掉双引号,即123,456,主要用于拼接
1、批量删除
(1)or
Delete from 表 where id=1 or id=2 or id=3;
(2)in
Delete from 表 where id in(1,2,3);
应该用${}
2、模糊查询like
例子:
Public interface CarMapper{
List<Car> selectByBrand(String brand);
}
<mapper namespcase=”com.powernode.mapper.CarMapper”>
<select id=”selectByBrand” resultType=”com.powernode.pojo.car”>
Select
id,
car_num as carNum,
brand
guide_price as guidePrice
From
car
Where
brank like ‘%${brand}%’ //或者brank like concat(‘%’,#{brand},’%’ )
</select>
测试:
Public class CarMapperTest{
@Test
Public void test selectByBrand(){
SqlSession sqlsession = SqlSessionUtil.openSession();
CarMapper mapper = sqlsession.getMapper(CarMapper.class);
List<Car> cars=mapper.selectByBrand(“奔驰”);
Cars.forEach(car -> System.out.println(car));
sqlsession.close();
}
}
3、起别名
在mybatis-config.xml中起别名
<typeAliases>
<typeAliase type=”com.powernode.pojo.car” alias=”aaa”>
<package type=”com.powernode.pojo”>
</typeAliases>
则在SQL的xml文件中可以直接用
省略alias则默认为简名car/Car/cAr不区分大小写
Namescape不能起别名
package可以使得pojo包下的类起别名,使用简名
八、Mapper配置
mybatis-config.xml中的mapper标签中:
resource:这是从类的根路径下开始查找
url:绝对路径
class:提供mapper接口的全限定接口名,必须带有包名。
<mapper class=”com.powenode.mybatis.mapper.CarMapper”/>
则在java包下的com.powenode.mybatis.mapper.包中的CarMapper.xml,注意要求resoucers中的包和java包是一样的即同个目录名下
最终写法:
<package name=”com.powenode.mybatis.mapper”/>
九、自定义一键设置
十、插入数据时获得主键
<insert id=”方法名” useGeneratedKeys=”true” keyProperty=”id”>
十一、参数问题
1、对于Date参数
(其实date也是普通参数)
Public class CarMapperTest{
@Test
Public void testselectByDate(){
SqlSession sqlsession = SqlSessionUtil.openSession();
CarMapper mapper = sqlsession.getMapper(CarMapper.class);
SimpleDateFormat sdf=new SimpleDateFormat(“yyyy-MM-dd”);
Date birth=sdf.pares(“2024-01-10”);
List<Car> cars=mapper.selectByDate(birth);
Cars.forEach(car -> System.out.println(car));
sqlsession.close();
}
}
2、Map参数
Public class CarMapperTest{
@Test
Public void testinsertCarByDirver(){
SqlSession sqlsession = SqlSessionUtil.openSession();
CarMapper mapper = sqlsession.getMapper(CarMapper.class);
Map<String,Object> map=new HashMap<>();
Map.put(“姓名”,”张三”);
Map.put(“日期”,new Date() );
Map.put(“年龄”,12);
Mapper.insertCarByDirver(map);
Sqlsession.commit();
sqlsession.close();
}
}
<insert id=”insertCarByDirver” parameterType=”map”>
Insert into car(id,name,date,age) values(null.#{姓名}.#{日期}.#{年龄})
</insert>
3、POJO实体类参数
Public class CarMapperTest{
@Test
Public void testinsertCarByDirver(){
SqlSession sqlsession = SqlSessionUtil.openSession();
CarMapper mapper = sqlsession.getMapper(CarMapper.class);
Car car =new car();
car .setname(”张三”);
car .setdate(new Date() );
car .setage(12);
Mapper.insertCarByDirver(car);
Sqlsession.commit();
sqlsession.close();
}
}
<insert id=”insertCarByDirver” parameterType=”car”>
Insert into car(id,name,date,age) values(null.#{name}.#{date}.#{age})
</insert>
4、多参数
多参数的话,自动创建Map集合:
map.put(“arg0”,name);
map.put(“arg1”,age);
或
map.put(“param1”,name);
map.put(“param2”,age);
List<car> 方法名(String name,Character age);
<select id=”方法名” resultType=”car”>
Select * from car where name=#{arg0} and age=#{arg1}
</select >
5、Param注解
该注解是给默认map集合起别名的,arg失效,但param还可以用
List<car> 方法名(@Param(value=”name”)String name,@Param(value=”age”)String age);
<select id=”方法名” resultType=”car”>
Select * from car where name=#{name} and age=#{age}
</select >
6、返回的类型
返回单个实体类:car selectByid(Integer id);
返回多个实体类:List<car> selectAll( );
输出:car.forEach(car->System.out.println(car));
模糊查询:where brand like “%”#{brand}“%”
输出:List<car>
用Map返回一个:Map<String,Objetct> selectBymap(Integer id);
其中 ReusltType=”map“
用Map返回多个:List<Map<String,Objetct>> selectAll( );
用Map返回大Map:Map<Long,Map<String,Objetct>>
这样查找出来的map中容易拿出指定table
7、ResultType返回结果映射
(1)用as起别名
<select id="selectById" resultType="car">
select
id,
car_num as carNum,
brand,
guide_price as guidePrice,
produce_time as produceTime,
car_type as carType
from t_car where id=#{id}
</select>
(2)使用<resultMap id="唯一标识CarResultMap" type="POJO实体类名"></resultMap>
<resultMap id="CarResultMap" type="car">
<id property="id" column="id"/>
<result property="carNum" column="car_num"/>
<result property="guidePrice" column="guide_price"/>
<result property="produceTime" column="produce_time"/>
<result property="carType" column="car_type"/>
</resultMap>
<select id="selectById" resultMap ="CarResultMap">
Select * from t_car where id=#{id}
</select>
(3)驼峰命名自动映射(在mybatis核心配置文件中配置)
<settings>
<setting name="mapUnderscoreToCamelCase" value="ture"/>
</settings>
Java命名规则:首字母小写,后面接的单词首字母大写
SQL命名规则:全小写,单词之间用_隔开
这样的命名规则mybatis自动会转换
8、返回总记录条数
Select count(*) from t_car
十二、动态SQL
1、if标签
List<Car> select(@Param("brand") String brand,@Param("guidePrice")Double guidePrice,@Param("carType") String carType);
注意:不能用&&得用and
<select id="select" resultType="car">
select * from t_car where 1=1
<if test="brand !=null and brand!=''">
and brand like "%"#{brand}"%"
</if>
<if test="guidePrice !=null and guidePrice!=''">
and guide_price > #{guidePrice}
</if>
<if test="carType !=null and carType!=''">
and car_type > #{carType}
</if>
</select>
2、where标签
自动去除多余的and或or
<select id="select" resultType="car">
select * from t_car
<where>
<if test="brand !=null and brand!=''">
brand like "%"#{brand}"%"
</if>
<if test="guidePrice !=null and guidePrice!=''">
and guide_price > #{guidePrice}
</if>
<if test="carType !=null and carType!=''">
and car_type > #{carType}
</if>
</where>
</select>
3、trim标签
<select id="select" resultType="car">
select * from t_car
<trim prefixOverrides="删除前缀" prefix="增加前缀" suffixOverrides="删除后缀" suffix="增加后缀">
SQL句子
</trim>
</select>
例如:where + SQL 句子 + and ,此时增减前缀where ,并且and就多余,要删除后缀and
4、set标签
<update id="updateByid">
update t_car set
brand=#{brand},
car_type=#{carType}
where id=#{id}
</update>
注:set标签会自动去除逗号
<update id="updateByid">
update t_car
<set>
<if test="brand !=null and brand!=''">brand=#{brand}, </if>
<if test="car_type !=null and car_type!=''"> car_type=#{carType}, </if>
where id=#{id}
</set>
</update>
5、Choose when otherwise标签
<chose>
<when test=””></when>
<when test=””></when>
<otherwise></otherwise>
</chose>
等价于
if( ){
}else if( ){
else{
}
6、foreach批量删除
int deleteByid(@Param(“ads”)Long[] ads);
<delete id="deleteByID">
delete from t_car where id in (
<foreach collection="ads" item="aaa" separator=",">
#{aaa}
</foreach>
)
</delete>
Separator:自动添加逗号
Collection:为array或者arg0,若有配@Param,则直接用自定义名
<delete id="deleteByID">
delete from t_car where id in
<foreach collection="ads" item="aaa" separator="," open="(" close=")">
#{aaa}
</foreach>
</delete>
或者用or
<delete id="deleteByID">
delete from t_car where
<foreach collection="ads" item="aaa" separator="or" open="(" close=")">
Id=#{aaa}
</foreach>
</delete>
7、foreach批量插入
int insertBatch(@Param("cars") List<Car> cars);
<insert id="insertBatch">
insert into t_car values
<foreach collection="cars" item="aaa" separator=",">
(null,#{aaa.carNum},#{aaa.brand},#{aaa.guidePrice},#{aaa.produceTime},#{aaa.carType})
</foreach>
</insert>
8、SQL标签和include标签
<select id="selectById" resultType="car">
select
id,
car_num as carNum,
brand,
guide_price as guidePrice,
produce_time as produceTime,
car_type as carType
from t_car where id=#{id}
</select>
等价于下面,提取公共得SQL代码:
<sql id="carColumn">
id,
car_num as carNum,
brand,
guide_price as guidePrice,
produce_time as produceTime,
car_type as carType
</sql>
<select id="selectById" resultType="car">
select
<include refid="carColumn"></include>
from t_car where id=#{id}
</select>
十三、高级映射
1、多对一,联级查询(1)
public class student {
private Integer id;
private String name;
private gradeclass gradeclass1;
}
public class gradeclass {
private Integer cid;
private String clazz;
}
public interface studentMapper {
student selectByid(Integer id);
}
t_student s left join t_gradeclass c on s.cid=c.cid左连接当且仅当on后面条件达到
2、多对一,association(2)
3、多对一,分布查询(3)
调用selectBycid进行sql查询得到cid再传给resultMap的cloum,association通过得到的cloum中cid跳到select给定的接口去查到,最后返回赋给property
注:fetchType="lazy"为懒加载模式,用到就查询,不用就不查询,提高性能
在核心配置文件中setting配置lazyloadingEnabled=ture则为全局懒加载
4、一对多,collection集合
5、一对多,延迟加载
十四、mybatis的缓存
一级Sqlseeeion缓存:通过同一个Sqlsession对象,默认开启 手动清空缓存:Sqlsession.clearCache()
二级SqlsessionFactory缓存:默认开启,SQLMapper.xml添加</cache>
,将Pojo实体类implements serializable接口
Sqlsession对象关了,一级缓存的东西才会放到二级缓存
两次查询之间出现其他增删改,任何缓存一定失效
十五、Mybatis的逆向工程
根据数据库表逆向生成实体类、SqlMapper.xml、Mapper接口等
###第一步:在pom中添加逆向工程插件
<!--定制构建过程-->
<build>
<!--可配置多个插件-->
<plugins>
<!--其中的一个插件:mybatis逆向工程插件-->
<plugin>
<!--插件的GAV坐标-->
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.1</version>
<!--允许覆盖-->
<configuration>
<overwrite>true</overwrite>
</configuration>
<!--插件的依赖-->
<dependencies>
<!--mysql驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
第二步:配置generatorConfig.xml
该文件名必须叫做:generatorConfig.xml
该文件必须放在类的根路径下。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--
targetRuntime有两个值:
MyBatis3Simple:生成的是基础版,只有基本的增删改查。
MyBatis3:生成的是增强版,除了基本的增删改查之外还有复杂的增删改查。
-->
<context id="DB2Tables" targetRuntime="MyBatis3">
<!--防止生成重复代码-->
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>
<commentGenerator>
<!--是否去掉生成日期-->
<property name="suppressDate" value="true"/>
<!--是否去除注释-->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--连接数据库信息-->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/powernode"
userId="root"
password="root">
</jdbcConnection>
<!-- 生成pojo包名和位置 -->
<javaModelGenerator targetPackage="com.powernode.mybatis.pojo" targetProject="src/main/java">
<!--是否开启子包-->
<property name="enableSubPackages" value="true"/>
<!--是否去除字段名的前后空白-->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- 生成SQL映射文件的包名和位置 -->
<sqlMapGenerator targetPackage="com.powernode.mybatis.mapper" targetProject="src/main/resources">
<!--是否开启子包-->
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- 生成Mapper接口的包名和位置 -->
<javaClientGenerator
type="xmlMapper"
targetPackage="com.powernode.mybatis.mapper"
targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 表名和对应的实体类名-->
<table tableName="t_car" domainObjectName="Car"/>
</context>
</generatorConfiguration>
第三步:启动
// 查一个
Car car = mapper.selectByPrimaryKey(89L);
System.out.println(car);
// 查所有
List<Car> cars = mapper.selectByExample(null);
cars.forEach(c -> System.out.println(c));
// 多条件查询
// QBC 风格:Query By Criteria 一种查询方式,比较面向对象,看不到sql语句。
//用.createCriteria()创造查询条件
CarExample carExample = new CarExample();
carExample.createCriteria()
.andBrandEqualTo("丰田霸道")
.andGuidePriceGreaterThan(new BigDecimal(60.0));
//or指的是上面和下面是or的关系
carExample.or().andProduceTimeBetween("2000-10-11", "2022-10-11");
mapper.selectByExample(carExample);
sqlSession.commit();
十六、MyBatis使用PageHelper
1、limit
mysql的limit后面两个数字:
● 第一个数字:startIndex(起始下标。下标从0开始。)
● 第二个数字:pageSize(每页显示的记录条数)
假设已知页码pageNum,还有每页显示的记录条数pageSize,第一个数字可以动态的获取吗?
● startIndex = (pageNum - 1) * pageSize
所以,标准通用的mysql分页SQL:
select * from tableName
limit (pageNum - 1) * pageSize, pageSize
List<Car> selectByPage(@Param("startindex")int startindex,@Param("pageside")int pageside);
<select id="selectByPage" resultType="Car">
select * from t_car limit #{startindex},#{pageside}
</select>
2、PageHelper插件
第一步:引入依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.1</version>
</dependency>
第二步:在mybatis-config.xml文件中配置插件
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
第三步:编写Java代码
List<Car> selectAll();
<select id="selectAll" resultType="Car">
select * from t_car
</select>
@Test
public void testPageHelper() throws Exception{
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
// 执行SQL之前开启分页,第2页显示3条
PageHelper.startPage(2, 3);
// 执行查询语句
List<Car> cars = mapper.selectAll();
// 获取分页信息对象,导航的卡片的数量是5
PageInfo<Car> pageInfo = new PageInfo<>(cars, 5);
System.out.println(pageInfo);
}
结果:
PageInfo{
pageNum=2, pageSize=2, size=2, startRow=3, endRow=4, total=6, pages=3,
list=Page{count=true, pageNum=2, pageSize=2, startRow=2, endRow=4, total=6, pages=3, reasonable=false, pageSizeZero=false}
[Car{id=86, carNum='1234', brand='丰田霸道', guidePrice=50.5, produceTime='2020-10-11', carType='燃油车'},
Car{id=87, carNum='1234', brand='丰田霸道', guidePrice=50.5, produceTime='2020-10-11', carType='燃油车'}],
prePage=1, nextPage=3, isFirstPage=false, isLastPage=false, hasPreviousPage=true, hasNextPage=true,
navigatePages=5, navigateFirstPage=1, navigateLastPage=3, navigatepageNums=[1, 2, 3]
}
pageInfo中有很多方法,可以得到信息返回前端显示