文章目录
创建mybatis配置文件(mybatis-config.xm) 创建JavaBean Class 创建StudentDao接口 创建Sql语句映射配置文件(StudentDao.xml) 查询 增加 日志 主要类的介绍 Resource SqlSessionFactoryBuilder SqlSessionFactory(interface) SqlSession(interface)
Mybatis工具类 Mybatis动态代理 限定条件传参 单个参数 多个参数 使用对象作为参数 按位置传值 用Map存值传多个参数
#和$的区别
ResultType 定义返回值类型别名 返回值为HashMap 列名和属性名不一样(ResultMap)
Like模糊查询 在java代码中指定like的内容 在mapper文件中拼接like的内容
动态SQL
主配置文件 transactionManager dataSource
属性配置文件 指定多个mapper文件
分页查询(扩展)
创建mybatis配置文件(mybatis-config.xm)
创建JavaBean Class
package com.demo.domain;
public class Student {
private Integer id;
private String name;
private String email;
private Integer age;
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setEmail(String email) {
this.email = email;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public Integer getAge() {
return age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + ''' +
", email='" + email + ''' +
", age=" + age +
'}';
}
}
创建StudentDao接口
package com.demo.dao;
import com.demo.domain.Student;
import java.util.List;
public interface StudentDao {
public List selectStudents();
public int insertStudent(Student student);
}
创建Sql语句映射配置文件(StudentDao.xml)
<
select id,name,email,age from student;
insert into student values (#{id},#{name},#{email},#{age})
查询
package com.demo;
import com.demo.domain.Student;
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;
import java.util.List;
public class Myapp {
public static void main(String[] args) throws IOException {
//访问mybatis读取student数据
//1,定义mybatis主配置文件的名称,从类路径的根开始(target/classes)
String config="mybatis-config.xml";
//2.读取这个config表示的文件
InputStream in= Resources.getResourceAsStream(config);
//3.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
//4.创建SqlSessionFactory对象
SqlSessionFactory factory=builder.build(in);
//5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession=factory.openSession();
//6.指定要执行的sql语句的标识
//sql映射文件(xml)中的namespace+"."+标签的id值
String sqlId="com.demo.dao.StudentDao"+"."+"selectStudents";
//7.执行sql语句,通过sqlId找到语句
//即com.demo.dao.StudentDao.xml文件中
// namespace值为com.demo.dao.StudentDao
// id值为selectStudents的sql语句
//执行sql语句
List studentList=sqlSession.selectList(sqlId);
studentList.forEach(System.out::println);
//8.关闭sqlSession对象
sqlSession.close();
}
}
增加
import com.demo.domain.Student;
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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class testMybatis {
@Test
public void testInsert() throws IOException {
//访问mybatis读取student数据
//1,定义mybatis主配置文件的名称,从类路径的根开始(target/classes)
String config="mybatis-config.xml";
//2.读取这个config表示的文件
InputStream in= Resources.getResourceAsStream(config);
//3.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
//4.创建SqlSessionFactory对象
SqlSessionFactory factory=builder.build(in);
//5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession=factory.openSession();
//factory.openSession(true)则为自动提交
//6.指定要执行的sql语句的标识
//sql映射文件(xml)中的namespace+"."+标签的id值
String sqlId="com.demo.dao.StudentDao"+"."+"insertStudent";
//7.执行sql语句,通过sqlId找到语句
//即com.demo.dao.StudentDao.xml文件中
// namespace值为com.demo.dao.StudentDao
// id值为selectStudents的sql语句
Student student=new Student();
student.setId(4);
student.setName("jack");
student.setAge(20);
student.setEmail("5787@google.com");
//执行sql语句
int num=sqlSession.insert(sqlId,student);
//mybatis默认不是自动提交事务的,所以在insert,update,delete后要手工提交事务
sqlSession.commit();
System.err.println(num);
//8.关闭sqlSession对象
sqlSession.close();
}
}
日志
控制台(查询SQL语句):
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 422396878.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@192d43ce]
==> Preparing: select id,name,email,age from student;
==> Parameters:
<== Columns: id, name, email, age
<== Row: 1, mike, 5533@163.com, 24
<== Row: 2, jack, 5wd3@firefox.com, 21
<== Row: 4, jack, 5787@google.com, 20
<== Total: 3
Student{id=1, name='mike', email='5533@163.com', age=24}
Student{id=2, name='jack', email='5wd3@firefox.com', age=21}
Student{id=4, name='jack', email='5787@google.com', age=20}
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@192d43ce]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@192d43ce]
Returned connection 422396878 to pool.
进程已结束,退出代码为 0
控制台(增加SQL语句):
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 1011279482.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3c46e67a]
==> Preparing: insert into student values (?,?,?,?)
==> Parameters: 5(Integer), jack(String), 5787@google.com(String), 20(Integer)
<== Updates: 1
Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3c46e67a]
1//这是System.err.println(num);
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3c46e67a]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3c46e67a]
Returned connection 1011279482 to pool.
主要类的介绍
Resource
mybatis中的一个雷,负责读取主配置文件
InputStream in = Resource.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder
创建SqlSessionFactory对象
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
SqlSessionFactory factory=builder.build(in);
// SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(in);
SqlSessionFactory(interface)
重量级对象,程序创建一个对象耗时比较长,使用资源比较多
在整个项目中,有一个就够了
SqlSessionFactory接口的实现类:
DefaultSqlSessionFactory
SqlSessionFactory作用:
获取SqlSession对象
SqlSession sqlSession=factory.openSession();
openSession()默认为openSession(false)
openSession(false)表示非自动提交事务,表示insert,update,delete需要手动提交:sqlSession.commit()
openSession(true)表示自动提交事务,无需sqlSessio.commit()
SqlSession(interface)
定义了操作数据的方法:
eg:
selectOne(),selectList(),insert(),update(),delete(),commit(),rollBack()
SqlSession接口的实现类DefaultSqlSession
使用要求:
SqlSession对象不是线程安全的,需要在方法内部使用,在执行SQL语句之前,使用openSession()获取SqlSession对象
在执行完SQL语句后,需要关闭它,执行SqlSession.close(),这样能保证它的使用是线程安全的
Mybatis工具类
package com.demo.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=null;
static {
String config="mybatis-config.xml";
try {
InputStream in = Resources.getResourceAsStream(config);
sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
SqlSession sqlSession=null;
if(sqlSessionFactory!=null)
sqlSession=sqlSessionFactory.openSession();
return sqlSession;
}
}
Mybatis动态代理
import com.demo.dao.StudentDao;
import com.demo.domain.Student;
import com.demo.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class MybatisDynamicTest {
@Test
public void testSelectStudents(){
SqlSession sqlSession= MyBatisUtils.getSqlSession();
StudentDao dao=sqlSession.getMapper(StudentDao.class);
List studentList=dao.selectStudents();
studentList.forEach(System.out::println);
}
}
限定条件传参
单个参数
select属性值:paramterType
paramterType:dao接口中方法参数的数据类型
paramterType它的值是Java的数据类型全限定名称或者是mybatis定义的别名
例如:
paramterType="java.lang.Integer";
paramterType="int";
注意:paramterType不是强制的,mybatis通过反射机制能够发现接口参数的类型
所以可以没有.一般我们不写
使用#{}之后,mybatis执行SQL是使用Jdbc中的PreparedStatement对象
由mybatis执行下面的代码:
1.mybatis创建Connection,PreparedStatement对象
String sql="select id,name,email,age from student where id=?";
PreparedStatement ps=conn.preparedStatement(sql);
ps.setInt(1,1);
2.执行SQL封装为resultType="com.demo.domain.Student"这个对象
ResultSet rs=ps.executeQuery();
Student student=
while(rs.next()){
//从数据库取表的一行数据,存到一个Java对象属性中
student =new Student();
student.setId(rs.getInt("id"));
student.setName(rs.getString("name"));
student.setEmail(rs.getString("email"));
student.setAge(rs.getInt("age"));
}
return student;
select id,name,email,age from student where id=#{id}
select id,name,email,age from student where id=#{id}
public Student selectStudentById(Integer id);
//dao接口,参数名称id可以和#{id}不写一样的
@Test
public void testSelectStudentById(){
SqlSession sqlSession= MyBatisUtils.getSqlSession();
StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
Student student= studentDao.selectStudentById(1);
System.out.println(student.toString());
}
//junit测试代码
多个参数
使用@Param命名参数
接口public List selectMultiParam(@Param("myname") String name,@Param("myage") Integer age)
使用@Param("参数名") String name
mapper文件:
select * from student where id=#{myname} or age=#{myage}
select *
from student
where name=#{myname} or age=#{myage};
List selectMultiParam(@Param("myname") String name,@Param("myage") String age);
public void testSelectMultiParam(){
SqlSession sqlSession=MyBatisUtils.getSqlSession();
StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
List studentList=studentDao.selectMultiParam("jack","20");
studentList.forEach(System.out::println);
}
//多个参数:命名参数,在形参定义的前面加入@Param("自定义参数名称")
使用对象作为参数
package com.demo.vo;
public class QueryParam {
private String paramName;
private String paramAge;
public QueryParam(String paramName, String paramAge) {
this.paramName = paramName;
this.paramAge = paramAge;
}
public QueryParam() {
}
public String getParamName() {
return paramName;
}
public void setParamName(String paramName) {
this.paramName = paramName;
}
public String getParamAge() {
return paramAge;
}
public void setParamAge(String paramAge) {
this.paramAge = paramAge;
}
}
List selectMultiObject(QueryParam param);
select *
from student
where name=#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
or age=#{paramAge,javaType=java.lang.Integer,jdbcType=INTEGER}
上面的代码一般不用
简化版:
#{属性名},javaType和jdbcType的值mybatis反射能获取,不用提供
select *
from student
where name=#{paramName} or age=#{paramAge}
public void testselectMultiObject(){
SqlSession sqlSession=MyBatisUtils.getSqlSession();
StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
QueryParam queryParam=new QueryParam("jack","20");
List studentList= studentDao.selectMultiObject(queryParam);
studentList.forEach(System.out::println);
}
按位置传值
多个参数-简单类型的,按位置传值,相当于jdbc中按位置用参数替换SQL语句中的?
mybatis.3.4之前,使用#{0},#{1}
mybatis.3.4之后,使用#{arg0},#{arg1}
select *
from student
where name=#{arg0} or age=#{arg1}
List selectMultiPosition(QueryParam param);
public void testselectMultiPosition(){
SqlSession sqlSession=MyBatisUtils.getSqlSession();
StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
QueryParam queryParam=new QueryParam("jack","20");
List studentList= studentDao.selectMultiPosition(queryParam);
studentList.forEach(System.out::println);
}
用Map存值传多个参数
List selectMultiByMap(Map param);
select *
from student
where name=#{myname} or age=#{age}
public void testselectMultiByMap(){
SqlSession sqlSession=MyBatisUtils.getSqlSession();
StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
Map map=new HashMap<>();
map.put("myname","张三");
map.put("age",28);
List studentList= studentDao.selectMultiByMap(map);
studentList.forEach(System.out::println);
}
#和$的区别
相同之处
都是在SQL语句中进行字符串的替换,语法基本相同
不同之处
#使用的PreparedStatement对象,对?替换,不会出现SQL注入
$使用的Statement对象,会出现SQL注入
PreparedStatement是预编译的,对于批量处理可以大大提高效率.也叫JDBC存储过程
使用 Statement 对象。在对数据库只执行一次性存取的时侯,用 Statement 对象进行处理。PreparedStatement对象的开销比Statement大,对于一次性操作并不会带来额外的好处。
statement每次执行sql语句,相关数据库都要执行sql语句的编译,preparedstatement是预编译得,preparedstatement支持批处理
prepareStatement会先初始化SQL,先把这个SQL提交到数据库中进行预处理,多次使用可提高效率。
createStatement不会初始化,没有预处理,没次都是从0开始执行SQL
$在替换的时候,传参若是字符串,例如'zhangsan',则需要写成studentDao.xxxx("'zhangsan'")
即$在替换的时候抛弃最外层引号,可以用来替换表名、列名或者*
#在替换的时候保留最初为引号,可以用来作为where和having逻辑判读条件
ResultType
SQL语句执行之后的返回值类型:
1,java的基础类型及其包装类int,double和java.lang.Integer,java.lang.Double等
2,实体类,自己定义的实体类(全限定名称,若自己定义的有包名需要加包名)
3,map类型,如果使用resultMap这里可以使用自定义map,本文只介绍resultType
4,集合,即返回的时一个List集合,其中该集合的类型可以为1,2,3中提到的类型
若resultType指向的类,则SQL语句中的列名必须要和该类中成员变量的name对应,
成员变量的数量可以比SQL语句中的列名少,但名称要匹配,大小写要一致(JavaBean)
eg:计算返回的行数
int countStudent();
select count(*) from student
int count=dao.countStudent();
定义返回值类型别名
指定一个类型一个自定义别名(不建议使用,可能会出现冲突,具有歧义)
返回值为HashMap
返回Map
列名是map的key,列值是map的value(一行内数据)
只允许最多返回一行,多余一行运行报错
Map selectMapById(Integer id);
select id,name from student where id=#{id}
public void testselectMapById(){
SqlSession sqlSession=MyBatisUtils.getSqlSession();
StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
Map map= studentDao.selectMapById(1);
System.out.println(map);
}
列名和属性名不一样(ResultMap)
方式一
作用:
结果映射,指定数据库中列名和java类中属性的对应关系,并起别名
1)自定义列值复制给哪个属性
2)当你的列名和属性名不一样时,一定使用resultMap
//resultType和ResultMap不要一起用,二选一
使用resultMap
1)先定义resultMap
2)在select标签中,使用resultMap来引用1定义的
定义resultMap
id:自定义名称,表示定义的这个resultMap
type:java类型的全限定名称
property
-->
select id,name,email,age from student
List selectAllStudents();
方式二
List selectDiffColProper();
Mystudent(JavaBean)类中的属性:
stuid
stuname
stuemail
stuage
select id as stuid,name as stuname,email as stueamil,age as stuage
from student
Like模糊查询
在java代码中指定like的内容
List selectLikeOne(String name);
select id,name,email,age
from student where name like #{name}
在mapper文件中拼接like的内容
List selectLikeTwo(String name);
select id,name,email,age
from student where name like '%' #{name} '%'
动态SQL
sql的内容是变化的,可以根据条件获取到不同的sql语句
主要是where部分发生变化
动态sql的实现,实现的是mybatis提供的标签,,,
动态sql时使用java对象作为参数
是判断条件的
语法:
部分SQL语句
动态sql时使用java对象作为参数
List selectStudentIf(Student student);
select id,name,email,age from student
where 1=1
name = #{name}
and age > #{age}
用来包含多个的,当多个if有一个成立,会自动增加一个where关键字,并去掉多余的and、or关键字
语法:
....
List selectStudentWhere(Student student);
select id,name,email,age from student
name = #{name}
and age > #{age}
循环java中的数组,list集合的.主要用在sql的in语句中
eg:
select * from student id in (1001,1002,1003)
语法:
collection:表示接口中的方法参数的类型,如果是数组使用array,如果是list集合使用list
item:自定义的,表示数组和集合中每一个元素进行迭代时的别名,支持属性的点路径访问,如item.age,item.info.details,相当于for(Integer i:integer){}或for(Student stu:students){},如果是i,则直接用#{i},如果是stu,则用#{stu.id}或stu对象的其他成员变量,不考虑访问权限
open:循环开始时的字符,例如'('
close:循环结束时的字符,例如')'
separator:集合成员之间的分隔符,例如','
List selectStudentforeach(List list);
select id,name,email,age from student
where id in
#{stu.id}
代码片段
SQL代码复用
写在mapper块内,select,insert,update,delete语句外
定义SQL片段,使用id起别名
语法:
select id,name,email,age from student
调用SQL代码片段:
where id in
#{stu.id}
主配置文件
transactionManager
transactionManager:mybatis提交事务,回滚事务的方式
type:事务的处理的类型
1)JDBC 表示Mybatis底层是调用JDBC中的Connection对象的commit,rollback
2)MANAGED:把Mybatis的事务处理委托给其他的容器(可以是一个服务器软件,一个框架(Spring))
dataSource
dataSource:表示数据源,Java体系中,规定实现了javax.sql.DataSource接口的都是数据源
数据源表示Connection对象的
type:指定数据源的类型
1)POOLED:使用连接池,mybatis会创建PooledDataSource
2)UPOOLED:不使用连接池,在每次执行sql语句,先创建连接,执行sql,再关闭连接
mybatis会创建一个UnPooledDataSource,管理Connection对象的使用
3)JNDI:java命名和目录服务(Windows注册表)
属性配置文件
数据库的属性配置文件:把数据库连接信息放在一个单独的文件中,和mybatis主配置文件分开,
目的是便于修改,报错,处理多个数据库的信息
1)在resources目录中定义一个属性配置文件,xxx.properties,例如jdbc.properties
在属性配置文件中,定义数据,格式是key=value
key:一般使用.做多级目录的,可读性
例如: jdbc.mysql.driver,写法jdbc.driver和mydriver都行
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://...
jdbc.username=root
jdbc.password=123456
2)在mybatis的主配置文件,使用指定文件的位置
在需要使用值的地方
指定properties文件的位置,从类路径根开始找文件,父标签是,需要写在标签前面
使用jdbc.properties文件中的内容:
指定多个mapper文件
...
使用包名:
name:xml文件(mapper文件)所在的包名
...
com.demo.daox是包名
使用package的要求:
1)mapper文件名称需要和接口名称一样,区分大小写
2)mapper文件和到接口需要在同一目录下
分页查询(扩展)
非官方自带,是他人开发的扩展功能
maven坐标
导入maven依赖pagehelper
com.github.pagehelper
pagehelper-spring-boot-starter
5.1.10
加入plugin配置
在之前加入
查询
select * from student order by id
List selectAll();
public void testselectMapById(){
SqlSession sqlSession=MyBatisUtils.getSqlSession();
StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
//加入PageHelper的方法,分页
//pageNum:第几页,从1开始
//pageSize:一页中有多少行数据
// PageHelper.startPage(pageNum,pageSize);
PageHelper.startPage(1,3);
List students= studentDao.selectAll();
System.out.println(map);
}