前言:
此篇仅为个人初期学习笔记,如有错误,请xd们指正 你这么好看,还。。。。
后续会更新spring、springmvc、springboot、分布式微服务等 关注我,一起学习,一起进步吧
来源:
尚硅谷视频教程
- 是一个基于Java的半自动的ORM(Object Relation Mapping)持久层框架
- iBatis提供的持久层框架包括SQL Maps和Data Access Objects(DAO)
- 支持存储过程以及高级映射
- 不需要手动写jdbc代码、不需要手动设置参数和获取结果集
- 使用简单的XML或注解用于配置和原始映射
- SQL 和 Java 编码分开,SQL语句专注于数据,java代码专注于业务逻辑
- 封装了jdbc,简化操作
<packaging>warpackaging>
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.7version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.3version>
dependency>
dependencies>
习惯命名:mybatis-config.xml
ssm整合之后可以省略不写
作用:配置连接数据库的环境以及MyBatis的全局配置信息
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://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"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="mappers/UserMapper.xml"/>
mappers>
configuration>
相关概念:
ORM(Object Relationship Mapping)对象关系映射。
映射关系
注意事项
映射文件的命名规则:
表所对应的实体类的类名+Mapper.xml
一个映射文件对应一个实体类,对应一张表的操作
MyBatis映射文件用于编写SQL,访问以及操作表中的数据
MyBatis中想要面向接口操作数据,要保证两个一致:
’
//读取MyBatis的核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new
SqlSessionFactoryBuilder();
//通过核心配置文件所对应的字节输入流创建工厂类SqlSessionFactory,生产SqlSession对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//创建SqlSession对象,此时通过SqlSession对象所操作的sql都必须手动提交或回滚事务
//SqlSession sqlSession = sqlSessionFactory.openSession();
//创建SqlSession对象,此时通过SqlSession对象所操作的sql都会自动提交
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//通过**代理模式**创建UserMapper接口的代理实现类对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用UserMapper接口中的方法,就可以根据UserMapper的全类名匹配元素文件,通过调用的方法名匹配
映射文件中的SQL标签,并执行标签中的SQL语句
int result = userMapper.insertUser();
//sqlSession.commit();'
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
### b>加入配置文件
DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS}
%m (%F:%L) \n" />
layout>
appender>
<logger name="java.sql">
<level value="debug" />
logger>
<logger name="org.apache.ibatis">
<level value="info" />
logger>
<root>
<level value="debug" />
<appender-ref ref="STDOUT" />
root>
log4j:configuration>
FATAL(致命)>ERROR(错误)>WARN(警告)>INFO(信息)>DEBUG(调试)
从左到右打印的内容越来越详细
properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,
objectWrapperFactory?,reflectorFactory?,plugins?,environments?,
databaseIdProvider?,mappers?
DOCTYPE configuration
PUBLIC "-//MyBatis.org//DTD Config 3.0//EN"
"http://MyBatis.org/dtd/MyBatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
settings>
<typeAliases>
<package name="com.atguigu.mybatis.bean"/>
typeAliases>
<environments default="mysql_test">
<environment id="mysql_test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="UserMapper.xml"/>
<package name="com.atguigu.mybatis.mapper"/>
mappers>
configuration>
<insert>
insert into t_user values(null,'admin','123456',23,'男')
<insert/>
<delete>delete from t_user where id = 7 delete>
<update>
update t_user set username='ybc',password='123' where id = 6
update>
返回单个对象
<select resultType = "com.nuesoft.mybatis.User">
SELECT * FROM EMP WHERE id = #{id}
select>
返回集合
<select>
select * from emp;
select>
查询的标签select必须设置属性resultType或resultMap,用于设置实体类和数据库表的映射关系
resultType:
自动映射,用于属性名和表中字段名一致的情况
resultMap:
自定义映射,用于一对多或多对一或字段名和属性名不一致的情况
若mapper接口中的方法需要的参数为多个时
此时可以手动创建map集合,将这些数据放在map中
只需要通过KaTeX parse error: Expected 'EOF', got '#' at position 4: {}和#̲{}访问map集合的键就可以获…{}需要手动加单引号
User getUserById(@Param("uid") uid);
<select>
select * from t_user where id = #{id}
select>
list<User> getAllUser();
<select>
select * from t_user
select>
int getAcount();
<select>
select count(*) form emp
select>
Map <String , Object> getUserToMap(@Param("id") int id);
<select>
select * from t_user where id = #{id}
select>
`/**
\* 测试模糊查询
\* @param mohu
\* @return
*/
List<User> testMohu(@Param("mohu") String mohu);
<select id="testMohu" resultType="User">
select * from t_user where username like "%"#{mohu}"%"
select>`
`/**
\* 批量删除
\* @param ids
\* @return
*/
int deleteMore(@Param("ids") String ids);
<delete id="deleteMore">
delete from t_user where id in (${ids})
delete>`
`/**
\* 动态设置表名,查询所有的用户信息
\* @param tableName
\* @return
*/
List<User> getAllUser(@Param("tableName") String tableName);
<select id="getAllUser" resultType="User">
select * from ${tableName}
select>`
t_clazz(clazz_id,clazz_name)
t_student(student_id,student_name,clazz_id)
添加班级信息
获取新添加的班级的id
为班级分配学生,即将某学的班级id修改为新添加的班级的id
`/**
\* 添加用户信息
\* @param user
\* @return
\* useGeneratedKeys:设置使用自增的主键
\* keyProperty:因为增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参
数user对象的某个属性中
*/
int insertUser(User user);
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into t_user values(null,#{username},#{password},#{age},#{sex})
insert>`
为什么需要自定义映射?
无疑,自动映射解决不了问题了,因为字段名和属性名不一致了
解决字段名和属性名不一致的情况
resultMap:设置自定义映射
属性:
id:表示自定义映射的唯一标识
type:查询的数据要映射的实体类的类型
子标签:
id:设置主键的映射关系
result:设置普通字段的映射关系
association:设置多对一的映射关系 ,在多的一方创建一的属性
collection:设置一对多的映射关系 ,在一的一方创建集合属性存储多的一方对象
属性:
若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性 名符合Java的规则(使用驼峰)
此时也可通过以下两种方式处理
查询员工信息以及员工所对应的部门信息
`<resultMap id="empDeptMap" type="Emp">
<id column="eid" property="eid">id>
<result column="ename" property="ename">result>
<result column="age" property="age">result>
<result column="sex" property="sex">result>
<result column="did" property="dept.did">result>
<result column="dname" property="dept.dname">result>
resultMap>
<select id="getEmpAndDeptByEid" resultMap="empDeptMap">
select emp.*,dept.* from t_emp emp left join t_dept dept on emp.did =
dept.did where emp.eid = #{eid}
select>`
`<resultMap id="empDeptMap" type="Emp">
<id column="eid" property="eid">id>
<result column="ename" property="ename">result>
<result column="age" property="age">result>
<result column="sex" property="sex">result>
<association property="dept" javaType="Dept">
<id column="did" property="did">id>
<result column="dname" property="dname">result>
association>
resultMap>
<select id="getEmpAndDeptByEid" resultMap="empDeptMap">
select emp.*,dept.* from t_emp emp left join t_dept dept on emp.did =
dept.did where emp.eid = #{eid}
select>`
`/**
\* 通过分步查询查询员工信息
\* @param eid
\* @return
*/
Emp getEmpByStep(@Param("eid") int eid);
<resultMap id="empDeptStepMap" type="Emp">
<id column="eid" property="eid">id>
<result column="ename" property="ename">result>
<result column="age" property="age">result>
<result column="sex" property="sex">result>
<association property="dept"
select="com.atguigu.MyBatis.mapper.DeptMapper.getEmpDeptByStep" column="did">
association>
resultMap>
<select id="getEmpByStep" resultMap="empDeptStepMap">
select * from t_emp where eid = #{eid}
select>`
2. 根据员工所对应的部门id查询部门信息
`/**
\* 分步查询的第二步:根据员工所对应的did查询部门信息
\* @param did
\* @return
*/
Dept getEmpDeptByStep(@Param("did") int did);
<select id="getEmpDeptByStep" resultType="Dept">
select * from t_dept where did = #{did}
select>`
`/**
\* 根据部门id查新部门以及部门中的员工信息
\* @param did
\* @return
*/
Dept getDeptEmpByDid(@Param("did") int did);
<resultMap id="deptEmpMap" type="Dept">
<id property="did" column="did">id>
<result property="dname" column="dname">result>
<collection property="emps" ofType="Emp">
<id property="eid" column="eid">id>
<result property="ename" column="ename">result>
<result property="age" column="age">result>
<result property="sex" column="sex">result>
collection>
resultMap>
<select id="getDeptEmpByDid" resultMap="deptEmpMap">
select dept.*,emp.* from t_dept dept left join t_emp emp on dept.did =
emp.did where dept.did = #{did}
select>`
`/**
\* 分步查询部门和部门中的员工
\* @param did
\* @return
*/
Dept getDeptByStep(@Param("did") int did);
<resultMap id="deptEmpStep" type="Dept">
<id property="did" column="did">id>
<result property="dname" column="dname">result>
<collection property="emps" fetchType="eager"
select="com.atguigu.MyBatis.mapper.EmpMapper.getEmpListByDid" column="did">
collection>
resultMap>
<select id="getDeptByStep" resultMap="deptEmpStep">
select * from t_dept where did = #{did}
select>`
2. 根据部门id查询员工信息
`/**
\* 根据部门id查询员工信息
\* @param did
\* @return
*/
List<Emp> getEmpListByDid(@Param("did") int did);
<select id="getEmpListByDid" resultType="Emp">
select * from t_emp where did = #{did}
select>`
注意事项
分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:
lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个
属性会按需加载
此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和
collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType="lazy(延迟加
载)|eager(立即加载)"
Mybatis框架的动态SQL技术(一系列标签)是一种根据特定条件动态拼装SQL语句的功能,为了解决拼接SQL语句字符串时的痛点问题。
遍历集合或者数组
属性:
eid,ename,age,sex,did
select refid=“empColumns” from t_emp
一级缓存是SqlSession级别的
通过同一个SqlSession查询的数据会被缓存
下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问
提高了查询的速度
不同的SqlSession对应不同的一级缓存
同一个SqlSession但是查询条件不同
同一个SqlSession两次查询期间执行了任何一次增删改操作-----清空缓存
同一个SqlSession两次查询期间手动清空了缓存
二级缓存是SqlSessionFactory级别
通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存
此后若再次执行相同的查询语句,结果才会从缓存中获取
- 在核心配置文件中,设置全局配置属性cacheEnabled=“true”,默认为true,不需要设置
- 在映射文件中设置标签<cache />
- 二级缓存必须在SqlSession关闭或提交之后才会生效
- 查询的数据所转换的实体类的类必须实现序列化的接口Serializable
两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
在mapper配置文件中添加的cache标签可以设置一些属性:
eviction属性:缓存回收策略
flushInterval属性:刷新间隔,单位毫秒
先查询二级缓存,因为二级缓存中有多个SqlSession的数据,更容易查询到
如果二级缓存没有命中,再查询一级缓存
如果一级缓存也没有命中,则查询数据库
SqlSession关闭之后,一级缓存中的数据会写入二级缓存
`
<dependency>
<groupId>org.mybatis.cachesgroupId>
<artifactId>mybatis-ehcacheartifactId>
<version>1.2.1version>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
<version>1.2.3version>
dependency>`
`
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore path="D:\atguigu\ehcache"/>
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
defaultCache>
ehcache>`
存在SLF4J时,作为简易日志的log4j将失效,此时我们需要借助SLF4J的具体实现logback来打印日志。
创建logback的配置文件logback.xml
`
<configuration debug="true">
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 -
->
<pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger]
[%msg]%npattern>
encoder>
appender>
<root level="DEBUG">
<appender-ref ref="STDOUT" />
root>
<logger name="com.atguigu.crowd.mapper" level="DEBUG"/>
configuration>`
```xml
`
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.7version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-maven-pluginartifactId>
<version>1.3.0version>
<dependencies>
<dependency>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-coreartifactId>
<version>1.3.2version>
dependency>
<dependency>
<groupId>com.mchangegroupId>
<artifactId>c3p0artifactId>
<version>0.9.2version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.8version>
dependency>
dependencies>
plugin>
plugins>
build>`
DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="DB2Tables" targetRuntime="MyBatis3Simple">
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis"
userId="root"
password="123456">
jdbcConnection>
<javaModelGenerator targetPackage="com.atguigu.mybatis.bean"
targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
javaModelGenerator>
<sqlMapGenerator targetPackage="com.atguigu.mybatis.mapper"
targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true" />
sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.atguigu.mybatis.mapper" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
javaClientGenerator>
<table tableName="t_emp" domainObjectName="Emp"/>
<table tableName="t_dept" domainObjectName="Dept"/>
context>
generatorConfiguration>`
`@Test
public void testMBG() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSession sqlSession = new
SqlSessionFactoryBuilder().build(is).openSession(true);
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
EmpExample empExample = new EmpExample();
//创建条件对象,通过andXxx方法为SQL添加查询添加,每个条件之间是and关系
empExample.createCriteria().andEnameLike("a").andAgeGreaterThan(20).andDidIsNot
Null();
//将之前添加的条件通过or拼接其他条件
empExample.or().andSexEqualTo("男");
List<Emp> list = mapper.selectByExample(empExample);
for (Emp emp : list) {
System.out.println(emp);
}
}
<dependency>
<groupId>\>com.github.pagehelpergroupId>
<artifactId>\>pagehelperartifactId>
<version>\>5.2.0version>
dependency>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">plugin>
plugins>
PageInfo{ pageNum=8, pageSize=4, size=2, startRow=29, endRow=30, total=30, pages=8, list=Page{count=true, pageNum=8, pageSize=4, startRow=28, endRow=32, total=30, pages=8, reasonable=false, pageSizeZero=false}, prePage=7, nextPage=0, isFirstPage=false, isLastPage=true, hasPreviousPage=true, hasNextPage=false, navigatePages=5, navigateFirstPage4, navigateLastPage8, navigatepageNums=[4, 5, 6, 7, 8] }
常用数据: