spring:
datasource:
url: jdbc:mysql://localhost:3306/product_systeam?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai
//useSSL=true开启安全连接
//useUnicode=true 使用Unicode编码
//serverTimezone=Asia/Shanghai 设置时区
2、建造mybatis工具类//如果在xml文件中使用mybatis配置(& 写法为 &)
package com.example.demo.productSysteam.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 {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
3、编写代码
实体类
package com.example.demo.productSysteam.entity;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class Customer implements Serializable {
private static final long serialVersionUID = 1L;
private String customerNumber;
private String name;
private String password;
private String phoneNumber;
private String customerType;
private String sex;
}
Dao接口
@Repository public interface CustomerMapper extends baseMapper{ public List findAll(); }
接口实现
select * from customer
测试
package com.example.demo.productSysteam.mapper;
import com.example.demo.productSysteam.entity.Customer;
import com.example.demo.productSysteam.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.jupiter.api.Test;
import java.util.List;
public class CustomerTest {
@Test
public void test(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
CustomerMapper customerMapper = sqlSession.getMapper(CustomerMapper.class);
List customerList = customerMapper.findAll();
List Customer = sqlSession.selectList("com.example.demo.productSysteam.mapper.CustomerMapper.findALL");
for (Customer customer : customerList) {
System.out.println(customer);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
}
遇到的问题
- 绑定接口出错
- 方法名不对
- 配置文件不全
- 返回类型不对
- mavan问题
- namespace 包名要与Mapper/下的接口包名保持一致
select
id 方法名名称 resultType Sql语句结果返回值 parameterType 传入参数类型
1、编写接口
public Customer getCustomerByNumber(String customer_number);
2、编写对饮的mapper中的sql语句
3、测试
@Test
public void getCustomerByNumber(){
Customer customerByNumber = customerMapper.getCustomerByNumber("111");
System.out.println(customerByNumber);
}
insert
接口
public int addCustomer(Customer customer);
编写mapper
insert into customer(customer_number,name,password,phone_number,customer_type,sex) values (#{customerNumber},#{name},#{password},#{phoneNumber},#{customerType},#{sex})
测试
@Test
public void addCustomer(){
int customerByNumber = customerMapper.addCustomer(new Customer("112","冯集贸","123456","123123123","你爹","nan"));
System.out.println(customerByNumber);
}
update
编写接口
public int updataCustomerByNumber(Customer customer);
编写mapper
update customer set name = #{name},password = #{password}, phone_number = #{phoneNumber},customer_type= #{customerType}, sex = #{sex} where customer_number = #{customerNumber}
测试
@Test
public void findCustomerByNumber(){
int int1 = customerMapper.updataCustomerByNumber(new Customer("112", "冯集贸11", "123456", "1111111", "你妈", "nan"));
Customer customerByNumber = customerMapper.getCustomerByNumber("112");
System.out.println(customerByNumber);
}
delete
编写接口
//删除用户
public int deleteCustomer(String customer_number);
编写mapper.xml文件
delete from customer where customer_number = #{customer_number}
测试
@Test
public void deleteCustomer(){
int i = customerMapper.deleteCustomer("112");
System.out.println(i);
}
mybatis想要提交修改需要提交事务
错误点
标签不要匹配错误
resource绑定mapper时,需要使用路径
程序配置文件必须符合规范
NullPointerException 没有注册到资源
假如,我们的实体,或者数据库中的表,字段或者参数过多,我们应当考虑使用Map
接口
public int addCustomer2(Mapmap);
mapper实现
insert into customer(customer_number,name,password) values (#{id},#{name},#{password})
测试
@Test
public void addCustomer2(){
Map map = new HashMap();
map.put("id",1000);
map.put("name","牛逼");
map.put("password","123123");
int customer2 = customerMapper.addCustomer2(map);
System.out.println(customer2);
}
区别
Map传递参数,直接在sql中取出key即可!
对象传递参数,直接在sql中取对象的属性
只有一个基本类型参数的情况下,sql可以直接取到
多个参数用Map,或者注解!
模糊查询
1、java代码执行的时候,传递通配符%%
Listlike = customerMapper.getCustmerLike("%张%");
2、在sql中不能写的写法 %#{value}% 在sql语句中不能使用通配符
会导致sql注入使where语句失效
例where name = %#{value}%
value值为1 or 1 = 1时会出现where子句失效。从而实现sql注入
1、核心配置文件
mybatis-config.xml
MyBatis的配置文件包含了会深深影响MyBatis行为的设置和属性信息
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
Mybatis可以配置成适应多种环境
不过要记住:尽管可以配置多个环境,但每个SqlsessionFactory实例只能选择一种环境
在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):
学会使用配置多套运行环境
Mybatis默认的事务管理器就是JDBC,连接池:POOLED
三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):属性(properties)
我们可以通过properties属性来实现引用配置文件
这些属性都是可外部配置且可动态替换的,既可以在典型的java属性文件中配置,亦可通过properties元素的子元素来传递[db.properties]
编写一个配置文件
db.properties
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/product_systeam?characterEncoding=utf8&;connectTimeout=1000&;socketTimeout=3000&;autoReconnect=true&;useUnicode=true&;useSSL=false&;serverTimezone=Asia/Shanghai username=root password=123456
在核心配置文件中引入
可直接引入外部文件
可以在其中增加一些属性配置
如果两个文件有同一个字段时,优先使用外部配置的文件
类型别名是为java类型设置一个短的名字
存在的意义仅在于用来减少类完全限定名的冗余
- 也可以指定一个包名,Mybatis会在包名下面搜索需要的Java Bean,比如:扫描实体类的包,它的默认别名就为找个类的类名,首字母小写
在实体类比较少使用第一种
如果实体类比较多则使用第二种
但第一种自由度更高
还可以在实体类上增加注解
@Alias("customers")
public class Customer implements Serializable {
设置
网址https://mybatis.net.cn/configuration.html#settings
其他配置- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
mybatis-generator-core
mybatis-plus
通用mapper
MapperRegistry: 注册绑定我们的Mapper文件
方式一:
方式二:使用class文件绑定注册
注意点:
- 接口和它的Mapper配置文件必须同盟
- 接口和他的Mapper配置文件必须在同一个包下
方式三:使用扫描包进行注入绑定
- 接口和它的Mapper配置文件必须同盟
- 接口和他的Mapper配置文件必须在同一个包下
生命周期,和作用域,是至关重要的,因为错误的使用会导致非常严重的并发问题
SqlSessionFactoryBuilder:
- 一旦创建了SqlSessionFactoryBuilder,就不需要它了
- 局部变量
SqlSessionFactory
- 说白了就是可以想象为:数据库连接池
- SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例
- 因此SqlsessionFactory的最佳作用域是应用作用域
- 最简单的就是使用单例模式或者静态单例模式
SqlSession
- 连接到连接池的一个请求
- qlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
- 用完之后需要关闭,否则资源被占用
这里面每一个Mapper都代表一个具体任务
数据库中的字段
新建一个项目,拷贝之前的,测试实体类字段不一致
private String name;
// private String password;
private String psw;
测试出现问题
类型处理器
select * from customer where customerNumber=#{customerNumber}
等价于
select customerNumber,name,psw,phoneNumber,customerType,sex
where customerNumber=#{customerNumber}
解决方法
起别名
select customer
customerNumber,name,password as psw ,phoneNumber,customerType,sex
where customerNumber=#{customerNumber}
结果集映射
resultMap元素是MyBatis中最重要最强大的元素
ResultMap的设计思想是,对于简单的语句根本不需要配置显式的结果映射,而对于复杂一点的语句只需要描述它们的关系就行了。
ResultMap最优秀的地方在于,虽然你已经对他相当了解了,但是根本就不需要显式地用到他们
- 日志工厂
如果一个数据库操作,出现异常,我们需要排错,那么日志就是最好的助手
曾今:sout、debug
现在:日志工厂
- SLF4J
- LOG4J
- LOG4J2
- JDK_LOGGING
- COMMONS_LOGGING
- STDOUT_LOGGING
- NO_LOGGING
在Mybatis中具体使用那个一日志实现,在设置中实现
STDOUT_LOGGING标准日志输出LOG4J
什么是Log4J?
- 我们也可以控制每一条日志的输出格式;
- 通过定义每一条日志信息的级别我们能够更加细致地控制日志的生成过程。
- 通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
1、先导入LOG4J包
log4j log4j 1.2.17
2、log4j.properties
### 配置根 设置日志级别###
log4j.rootLogger = DEBUG,console,file
### 设置输出sql的级别,其中logger后面的内容全部为jar包中所包含的包名 ###
log4j.logger.org.apache=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
### 配置输出到控制台 ###
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 = [%p][%d{yy-MM-dd}][%c]%m%n
### 配置输出到文件 ###
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File = logs/log.log
log4j.appender.file.MaxFileSize = 10mb
log4j.appender.file.Append = true
log4j.appender.file.Threshold = DEBUG
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
3.配置log4j为日志的实现
4、Log4j的使用,直接测试运行刚才查询
在要使用Log4j的类中,导入包 import org.apache.log4j.Logger
日志对象,参数为当前类的class
static Logger logger = Logger.getLogger(CustomerTest.class);
日志级别
logger.info("info:进入了testLog4j");
logger.debug("info:进入了testLog4j");
logger.error("info:进入了testLog4j");
分页
为什么要分页?
- 减少数据处理量
select * from customer limit 开始的位置,页的大小; select * from customer limit 2; #[0,n]
接口
ListgetCustomerByLimit(Map map);
实现mapper
select * from customer limit #{startIndex},#{pageSize}
测试
@Test
public void getCustomerByLimit(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
Map map = new HashMap();
map.put("startIndex",0);
map.put("pageSize",2);
List customerByLimit = mapper.getCustomerByLimit(map);
for (Customer customer : customerByLimit) {
System.out.println(customer);
}
sqlSession.close();
}
RowBounds分页
分页插件PageHelper
PageHelper
使用注解开发 面向接口编程
1、注解在接口上实现
@Select("select * from return_factory")
public List findAll();
需要在核心配置文件中绑定接口
测试



