Mybatis是一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。Mybatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。Mybatis可以使用简单的XML或注解来配置和映射原生信息,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.2version>
dependency>
1.2、持久化
数据持久化就是将程序的数据持久状态和瞬时状态转化的过程
数据库和io文件(持久化)
1.3、持久层Dao层、Service层、controller层
- 完成持久化工作的代码块
- 层界限十分明显
方便
传统的jdbc代码太复杂。
帮程序员将数据存入数据库,容易上手。
二、第一个mybatis程序搭建环境–》导入mybatis–》 编写代码–》测试
2.1、搭建数据库 2.2、创建一个模块1、在resource文件下创建mybatis-config.xml导入头文件
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?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
environments>
configuration>
2、创建SqlSessionFactory(编写工具类)
package com.huang.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 {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
//获取sqlSessionFactory对象
String url="mybatis-config.xml";
InputStream io = Resources.getResourceAsStream(url);
sqlSessionFactory=new SqlSessionFactoryBuilder().build(io);
} catch (IOException e) {
e.printStackTrace();
}
}
//创建sqlsession实例
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
3、编写Sql请求
实体类package com.huang.pojo;
public class User {
private int uid;
private String u_name;
private String u_password;
public User() {
}
public User(int uid, String u_name, String u_password) {
this.uid = uid;
this.u_name = u_name;
this.u_password = u_password;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getU_name() {
return u_name;
}
public void setU_name(String u_name) {
this.u_name = u_name;
}
public String getU_password() {
return u_password;
}
public void setU_password(String u_password) {
this.u_password = u_password;
}
}
Dao接口
package com.huang.dao;
import com.huang.pojo.User;
import java.util.List;
public interface UserDao {
List<User> getAllUser();
}
接口实现类(被mapper.xml替代)
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.huang.dao.UserDao">
<select id="getAllUser" resultType="com.huang.pojo.User">
select * from mybatis.user
select>
mapper>
测试
package com.huang.dao;
import com.huang.pojo.User;
import com.huang.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserTest {
@Test
public void test01(){
//获得sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//方式一getMapper:
// UserDao mapper = sqlSession.getMapper(UserDao.class);
// List allUser = mapper.getAllUser();
//方式二:不建议使用
List<User> allUser = sqlSession.selectList("com.huang.dao.UserDao.getAllUser");
for (User user:allUser){
System.out.println(user.toString());
}
sqlSession.close();
}
}
报错:org.apache.ibatis.binding.BindingException: Type interface com.huang.dao.UserDao is not known to the MapperRegistry.
原因: 未在mybatis-config.xml中配置mapper映射
<mappers>
<mapper resource="com/huang/dao/UserMapper.xml"/>
mappers>
报错二:java.lang.ExceptionInInitializerError
at com.huang.dao.UserTest.test01(UserTest.java:14)
原因:out处文件找不到对应文件,文件未导出。
<build>
<resources>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>truefiltering>
resource>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>truefiltering>
resource>
resources>
build>
报错三:Caused by: com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: 1 字节的 UTF-8 序列的字节 1 无效。
原因:xml文件encoding 设置utf-8无法被读取
解决:
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
properties>
三、CRUD
增删改需要进行实物提交
sqlSession。commit();
注意:
写sql的标签不要写错(delete、update、insert)
模糊查询拼接后注入避免用户写入时一些问题
四、配置解析 4.1、核心配置文件(mybatis-config.xml) 4.2、环境变量(environment)mybatis的事务管理:
1、jdbc(默认)
2、managed
连接池(unpooled|pooled|jnd)
4.3、属性(properties)
可以通过properties来实现引用配置文件
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="123456"/>
properties>
<environments default="test">
<environment id="development">
<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>
<environment id="test">
<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>
<mappers>
<mapper resource="com/huang/dao/UserMapper.xml"/>
mappers>
configuration>
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=123456
配置文件读取优先级:.properties优先级高于配置文件中的properties
4.3、别名(typeAliases)别名是为了java类型设置一个短的名字。
减少类完全限定名的冗余。
第一种方式:
<typeAliases>
<typeAlias type="com.huang.pojo.User" alias="user">typeAlias>
typeAliases>
--------------------------------------------------------------------------------
<select id="getAllUser" resultType="user">
select * from user
select>
第二种:
<typeAliases>
<package name="com.huang.pojo"/>
typeAliases>
--------------------------------------------------------------------------------
------resultType的首字母小写
<select id="getAllUser" resultType="user">
select * from user
select>
建议使用第二种
第二种如果用自己DIY可以再实体类上加上注解
import org.apache.ibatis.type.Alias;
@Alias("hello")
public class User {
private int uid;
private String u_name;
private String u_password;
}
--------------------------
<select id="getAllUser" resultType="hello">
select * from user
</select>
4.4、设置
4.5、其他设置
4.6、映射器(注册绑定我的mapper文件)
可能遇到的问题:
采用class和包扫描都必须保证接口和mapper配置文件名称一致,并且在同一个包下面。
五、作用域和生命周期生命周期和作用域非常重要,错误的生命周期会导致非常严重的并发问题!!!
SqlSessionFactoryBuilder(局部变量):
1、一旦创建了SqlSessionFactoryBuilder,就不在需要他。
SqlSessionFactory(全局作用域):
1、就是数据连接池
2、一旦创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或者创建一个新的实例。
3、最简单就是使用单例模式或者静态单例模式
SqlSession:
1、连接到连接池的一个请求! --> 关闭
2、用完后需要赶紧关闭,否则资源被占用!
六、解决属性名和字段名不一致问题 6.1、结果集映射ResultMap
<resultMap id="userMapper" type="User">
<result column="uid" property="uid">result>
<result column="u_name" property="u_name">result>
<result column="u_password" property="pwd">result>
resultMap>
<select id="getAllUser" resultMap="userMapper">
select * from user
select>
将数据库中的字段和实体类属性名对应
cloumn是数据库字段,property是实体类属性名
七、日志 7.1、日志工厂(设置Setting)控制台输出日志:
7.2、log4j
1、导包
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
2、log4j.properties
#将等级为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/huang.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
3、配置xml
<settings>
<setting name="logImpl" value="LOG4J"/>
settings>
如何使用:
static Logger logger=Logger.getLogger(UserTest.class);
logger.info("进入info");
logger.debug("进入debug");
logger.error("进入error");
8、分页
8.1、limit分页
//接口
List<User> getLimitUsers(Map<String,Integer> map);
//mapper
<select id="getLimitUsers" resultMap="userMapper" parameterType="map">
select * from user limit #{startPage},#{pageSize}
</select>
//Test
@Test
public void getLimitUsers(){
SqlSession session=MybatisUtils.getSqlSession();
UserDao mapper=session.getMapper(UserDao.class);
HashMap<String,Integer> map=new HashMap<String, Integer>();
map.put("startPage",0);
map.put("pageSize",2);
List<User> limitUsers = mapper.getLimitUsers(map);
for (User user:limitUsers){
System.out.println(user.toString());
}
}
8.2、RowBounds分页(java来实现查询到的所有数据进行管理)
List<User> getUsersByRowBounds(); //接口
//mapper
<select id="getUsersByRowBounds" resultMap="userMapper">
select * from user
select>
@Test
public void getUserByRowBounds(){
SqlSession session=MybatisUtils.getSqlSession();
RowBounds rowBounds = new RowBounds(1, 2);
List<User> userList = session.selectList("com.huang.dao.UserDao.getUsersByRowBounds",null,rowBounds);
//rowbounds
for (User user:userList){
System.out.println(user.toString());
}
session.close();
}
8.3、分页插件
9、注解开发
9.1、面向接口编程
@Select("select * from user")
List<User> getAllUser();
<mappers>
<mapper class="com.huang.dao.UserDao"/>
mappers>
@Test
public void test06(){
SqlSession session=MybatisUtils.getSqlSession();
UserDao mapper = session.getMapper(UserDao.class);
List<User> allUser = mapper.getAllUser();
for (User u:allUser){
System.out.println(u.toString());
}
}
10、mybatis原理
11、使用注解开发(CRUD)
1、开启事务自动提交:
//重载方法填写true时将自动提交事务
return sqlSessionFactory.openSession(true);
2、填写接口
@Insert("insert into user (u_name,u_password) values (#{u_name},#{pwd})")
void insertUser(User user);
可以再数据类型前面加@Param(“dsad”)来最定义传值 和#{}里的值对应
3、测试
@Test
public void test06(){
SqlSession session=MybatisUtils.getSqlSession();
UserDao mapper = session.getMapper(UserDao.class);
User user=new User();
user.setUid(0);
user.setU_name("sss");
user.setU_password("123");
mapper.insertUser(user);
session.close();
}
重点#{} 和 &KaTeX parse error: Expected 'EOF', got '#' at position 7: {}的区别:#̲{}不可以sql注入,{}可以进行sql拼接
12、Lombok1、下载插件
2、导包
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.10version>
dependency>
3、使用(在类上添加注解即可)
@Data
@ToString
public class User implements Cloneable{
private int uid;
private String u_name;
private String pwd;
//java设计模式:原型模式
@Override
protected Object clone() throws CloneNotSupportedException {
try {
Object user =super.clone();
return user;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}
13、多对一
多对一实体类:
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private int uid;
private String u_name;
private String pwd;
private Teacher teacher;
//深度克隆
@Override
protected User clone() throws CloneNotSupportedException {
try {
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(bis);
return (User)objectInputStream.readObject();
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Teacher implements Serializable {
private int tid;
private String tname;
private String tage;
}
1、子查询
List<User> getUser();
<resultMap id="userMapper" type="User">
<result column="uid" property="uid">result>
<result column="u_name" property="u_name">result>
<result column="u_password" property="pwd">result>
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
resultMap>
<select id="getUser" resultMap="userMapper">
select * from user
select>
<select id="getTeacher" resultType="com.huang.pojo.Teacher">
select * from teacher where tid=2
select>
2、联表查询
List<User> getUser2();
<select id="getUser2" resultMap="userMapper2">
select u.uid as uid,u.u_name as uname,t.tname as tname
from user u, teacher t
where u.tid=t.tid
select>
<resultMap id="userMapper2" type="User">
<result property="uid" column="uid" />
<result property="u_name" column="uname"/>
<association property="teacher" javaType="Teacher">
<result property="tname" column="tname"/>
association>
resultMap>
14、一对多
一对多实体类:
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private int uid;
private String u_name;
private String pwd;
private int tid;
//深度克隆
@Override
protected User clone() throws CloneNotSupportedException {
try {
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(bis);
return (User)objectInputStream.readObject();
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Teacher implements Serializable {
private int tid;
private String tname;
private String tage;
private List<User> users;
}
1、处理结果(嵌套结果)
List<Teacher> getTeacher(@Param("tid") int tid);
<select id="getTeacher" resultMap="teacherMapper1">
select u.uid as uid,u.u_name as uname,t.tname as tname,t.tid as tid
from user u, teacher t
where u.tid=t.tid and t.tid=#{tid}
select>
<resultMap id="teacherMapper1" type="Teacher">
<result property="tid" column="tid" />
<result property="tname" column="tname"/>
<collection property="users" ofType="User">
<result property="uid" column="uid"/>
<result property="u_name" column="uname"/>
<result property="tid" column="tid" />
collection>
resultMap>
2、处理查询(嵌套查询语句)
List<Teacher> getTeacher2(@Param("tid") int tid);
<select id="getTeacher2" resultMap="teacherMapper2">
select * from teacher where tid=#{tid}
select>
<resultMap id="teacherMapper2" type="Teacher">
<result property="tid" column="tid"/>
<collection property="users" javaType="ArrayList" ofType="User" select="getUserByTid" column="tid"/>
resultMap>
<select id="getUserByTid" resultType="User">
select * from user where tid=#{tid}
select>
小结:
1、关联 associate 【多对一】
2、结合 collection【一对多】
3、javaType :用来实体类中返回属性的类型 例如集合为ArrayList ,以及其他引用类型: String …
4、ofType :用来约束泛型中的类型
面试高频:
mysql 引擎
innodb 底层原理
索引
索引优化
15、动态SQl什么是动态sql就是指,根据不同的条件生成不同的sql语句。
1、if <select id="selectBlog" parameterType="map" resultType="Blog">
select * from blog where author='hello'
<if test="title != null">
and title = #{title}
if>
select>
2、choose=switch
<select id="selectBlogChoose" parameterType="map" resultType="Blog">
select * from blog
<where>
<choose>
<when test="author !=null and views != null">
author = #{author} and views=#{views}
when>
<when test="views != null and views ==null">
and views=#{views}
when>
choose>
where>
select>
3、trim
<trim prefix="" suffix="" prefixOverrides="" suffixOverrides="">
4、where(第一个分支不要加and 其他需要)
<select id="selectBlog" parameterType="map" resultType="Blog">
select * from blog
<where>
<if test="title != null">
and title = #{title}
if>
where>
select>
5、set(最后一个条件不用加逗号)
<update id="updateBlog" parameterType="map">
update blog
<set>
<if test="title != null">
title = #{title} ,
if>
<if test="author != null">
author = #{author}
if>
where id =#{id}
set>
update>
6、forEach(list内容都不满足的情况下查询所有)
<select id="selectBlog2" parameterType="map" resultType="Blog">
select * from blog
<where>
<foreach collection="ids" item="id" open="and (" close=")" separator="or">
id=#{id}
foreach>
where>
select>
7、SQL片段(不要套where)
<sql id="select-t-a">
<if test="title != null">
title = #{title}
if>
<if test="author != null">
and author = #{author}
if>
sql>
<select id="selectBlog" parameterType="map" resultType="Blog">
select * from blog
<where>
<include refid="select-t-a">include>
where>
select>
14、缓存
1、简介
把频繁查询不经常修改的数据进行存储,提高查询效率
2、一级缓存又称本地缓存(SQlSession,只在一次会话中存在close后就消失)默认开启的(再一次session会话中 查询相同对象是同一个地址缓存)
@org.junit.Test
public void Test2(){
SqlSession session= MybatisUtils.getSqlSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
Map map=new HashMap();
// map.put("title","java");
map.put("author","hello123321");
//手动清楚缓存session.clearCache
ArrayList<Blog> blogs = mapper.selectBlog(map);
for (Blog b:blogs){
System.out.println(b.toString());
}
ArrayList<Blog> blogs2 = mapper.selectBlog(map);
System.out.println(blogs2==blogs);
session.close();
}
影响缓存的点:
1、写入 *** 作会刷新缓存,查询后的2次数据指定地址不同 返回false
2、手动开启缓存清理session.clearCache
3、查询不同的数据
3、二级缓存开启二级缓存后,首先还是把查询的数据放在一级缓存中,当一级缓存关闭后才会把数据放入二级缓存
1、开启二级缓存
<settings>
<setting name="logImpl" value="LOG4J"/>
<setting name="cacheEnabled" value="true"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
settings>
2、对应mapper.xml中配置缓存
<cache size="512" eviction="FiFo" flushInterval="60000" readOnly="true"/>
//个人定制是否是用缓存
在标签中加入 useCache="false"
3、测试
@org.junit.Test
public void Test2(){
SqlSession session= MybatisUtils.getSqlSession();
SqlSession session2= MybatisUtils.getSqlSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
BlogMapper mapper2 = session2.getMapper(BlogMapper.class);
Map map=new HashMap();
// map.put("title","java");
map.put("author","hello123321");
ArrayList<Blog> blogs = mapper.selectBlog(map);
for (Blog b:blogs){
System.out.println(b.toString());
}
session.close();
ArrayList<Blog> blogs1 = mapper2.selectBlog(map);
System.out.println(blogs==blogs1);
session2.close();
}
15、缓存原理
16、自定义缓存ehCache
1、resource 中添加ehcache.xml文件自定义缓存模式
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<diskStore path="java.io.tmpdir" />
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxElementsOnDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap" />
defaultCache>
<cache name="GoodsType"
eternal="false"
timeToIdleSeconds="2400"
timeToLiveSeconds="2400"
maxEntriesLocalHeap="10000"
maxEntriesLocalDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
overflowToDisk="false"
memoryStoreEvictionPolicy="LRU">
cache>
ehcache>
<dependency>
<groupId>org.mybatis.cachesgroupId>
<artifactId>mybatis-ehcacheartifactId>
<version>1.2.1version>
dependency>
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.huang.dao.BlogMapper">
<cache type="org.mybatis.caches.ehcache.EhcacheCache" />
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)