目录
MyBatis
MyBatis
本是apache
的一个开源项目iBatis
, 2010年这个项目由apache software foundation
迁移到了google code
,并且改名为MyBatis
。
MyBatis
解决的主要问题:减轻JDBC
的复杂性,不用编写重复的创建Connection
、Statement
,不用编写关闭资源代码。
MyBatis
可以完成:
- 注册数据库的驱动
- 创建
JDBC
中必须使用的对象 - 从
xml
中获取sql
,并执行sql
语句,把ResultSet
结果转化成Java
对象
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>xxx</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
<build>
<!-- 资源插件,处理src/main/Java目录中的xml -->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.proterties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
MyBatis简介和配置
MyBatis的XML配置
mapper
是根标签。namespace
:命名空间, 必须有值,不能为空。唯一值。推荐使用Dao
接口的全限定名称,作用:参与识别sql
语句的作用。- 在
mapper
里面可以写<insert>
,<update>
,<delete>
,<select>
等标签。<insert>
里面是insert
语句,<update>
里面是update
语句,<delete>
里面是delete
语句,<select>
表示执行的是select
操作。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper">
<!--查询一个学生Student
<select>:表示查询操作,里 面是select语句
id:要 执行的sql语句的唯一标识,是一 一个自定义字符串。
推荐使用dao接口中的方法名称
resultType:告诉mybatis,执行sql语句, 把数据赋值给那个类型的java对象。
resultType的值现在使用的java对象的全限定名称
-->
<select id="com.bjpowernode.dao.StudentDao" resultType="com.bjpowernode.domain.Student">
select id, name, email, age from Student where id=1001
</select>
</mapper>
MyBatis
主文件配置,XML
配置文件中包含了对MyBatis
系统的核心设置,包括获取数据库连接实例的数据源(DataSource)
以及决定事务作用域和控制方式的事务管理器。
<?xml version="1.0" encoding="UTF-8" ?>
<!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"/>
<!-- 配置数据源,创建connect对象 -->
<dataSource type="POOLED">
<!--驱动的内容-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!--连接数据库的url-->
<property name="url" value="jdbc:mysql://81.68.246.231:3306/ssm"/>
<!--账号-->
<property name="username" value="test"/>
<!--密码-->
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--指定其他mapper文件位置-->
<mappers>
<!-- <mapper resource="org/mybatis/example/BlogMapper.xml"/>-->
<mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
</mappers>
</configuration>
这个配置文件有何用?
占位符
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bjpowernode.dao.StudentDao">
<select id="selectStudentById" resultType="com.bjpowernode.domain.Student">
select id, name, email, age from Student where id=# {studentid}
</select>
</mapper>
// <T> T selectOne(String var1, Object var2);
Student st = session.selectOne(sqlid, 1001);
MyBatis日志
Mybatis
通过使用内置的日志工厂提供日志功能。内置日志工厂将会把日志工作委托给下面的实现之一:
SLF4J
Apache Commons Logging
Log4j 2
Log4j (deprecated since 3.5.9)
JDK logging
在主xml
文件中
<configuration>
<settings>
...
<setting name="logImpl" value="LOG4J"/>
...
</settings>
</configuration>
logImpl
可选的值有:SLF4J
、LOG4J
、LOG4J2
、JDK_LOGGING
、COMMONS_LOGGING
、STDOUT_LOGGING
、NO_LOGGING
;value
指的是日志模块名。
MyBatis基础
MyBatis对象分析
Resources
:mybatis
框架中的对象,一个作用读取主配置信息。
SqlSessionFactoryBuilder
:负责创建SqISessionFactory
对象。
SqlSessionFactory
:重要对象
SqlSessionFactory
是重量级对象:创建此对象需要使用更多的资源和时间。在项目 中有一个就可以了。SqlSessionFactory
接口:作用是SqlSession
的工厂,就是创建SqlSession
对象。DefaultSqlSessionFactory
实现类
SqlSession
对象是通过SqlSessionFactory
获取的。SqlSession
本身是接口,DefaultSqlSession
:实现类
工具类和模板
创建模板,mapper
文件模板和mybatis
主文件模板,此处略过
因为SqlSessionFactory
创建较为耗时,因此创建工具类对象,来持久化运行
package com.bjpowernode.utils;
/**
* 工具类 创建sqlsession对象
*/
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MyBatisUtil {
private static SqlSessionFactory factory = null;
static {
String config = "mybatis.xml";
try {
InputStream inputStream = Resources.getResourceAsStream(config);
factory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession() {
SqlSession session = null;
if (factory != null) {
session = factory.openSession(true);
}
return session;
}
}
实现接口和实现类的组合
前面都是SqlSession
配合接口与.xml
的配置来进行数据库的操作,此时我们采用第二种模式,接口和实现类的组合,去体现面向对象的特性
接口实现类
package com.bjpowernode.dao;
import com.bjpowernode.domain.Student;
import com.bjpowernode.utils.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class StudentDaoImpl implements StudentDao {
@Override
public Student selectById(Integer id) {
SqlSession session = MyBatisUtil.getSqlSession();
String sqlid = "com.bjpowernode.dao.StudentDao.selectById";
Student st = session.selectOne(sqlid, id);
session.close();
return st;
}
@Override
public List<Student> selectList() {
SqlSession session = MyBatisUtil.getSqlSession();
String sqlid = "com.bjpowernode.dao.StudentDao" + "." + "selectList";
List<Student> st = session.selectList(sqlid);
session.close();
return st;
}
}
测试代码
package com.bjpowernode;
import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.dao.StudentDaoImpl;
import com.bjpowernode.domain.Student;
import com.bjpowernode.utils.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class MyTest {
@Test
public void Test() {
StudentDao sd = new StudentDaoImpl();
List<Student> sa = sd.selectList();
for (Student s: sa) {
System.out.println(s);
}
System.out.println("====================");
Student sp = sd.selectById(1001);
System.out.println(sp);
}
}
输出如下
com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 com.bjpowernode.MyTest
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 68326648.
==> Preparing: select id, name, email, age from Student
==> Parameters:
<== Columns: id, name, email, age
<== Row: 2, liuhao, 2226958871@qq.com, 34
<== Row: 1, liuhao, 22234, 34
<== Row: 1001, liuhao, 22234, 34
<== Row: 123, lasd, qwe, 234
<== Total: 4
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@41294f8]
Returned connection 68326648 to pool.
Student{id=2, name='liuhao', email='2226958871@qq.com', age=34}
Student{id=1, name='liuhao', email='22234', age=34}
Student{id=1001, name='liuhao', email='22234', age=34}
Student{id=123, name='lasd', email='qwe', age=234}
====================
Opening JDBC Connection
Checked out connection 68326648 from pool.
==> Preparing: select id, name, email, age from Student where id=?
==> Parameters: 1001(Integer)
<== Columns: id, name, email, age
<== Row: 1001, liuhao, 22234, 34
<== Total: 1
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@41294f8]
Returned connection 68326648 to pool.
Student{id=1001, name='liuhao', email='22234', age=34}
Process finished with exit code 0
进一步进行清除冗余
MyBatis代理
使用代理的要求
在.xml
文件中
namespace
必须是接口的全限定名称id
必须是接口中的方法
MyBatis代理实现方式
使用SqlSession
对象的方法getMapper(dap.class)
package com.bjpowernode;
import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.domain.Student;
import com.bjpowernode.utils.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class MyTest {
@Test
public void Test() {
SqlSession session = MyBatisUtil.getSqlSession();
// 动态代理
StudentDao dao = session.getMapper(StudentDao.class);
Student st = dao.selectById(1001);
System.out.println(st);
session.close();
}
@Test
public void myT() {
SqlSession session = MyBatisUtil.getSqlSession();
StudentDao dao = session.getMapper(StudentDao.class);
List<Student> ss = dao.selectList();
session.close();
}
}
深入理解参数
通过java
程序把数据传入到mapper
文件中的sql
语句
parameterType
指定dao
接口形参的类型这个属性的值可以使用java
类型的全限定名称或者mybatis
定义的别名
<!--第一种用法 Java类型的全限定类型名称-->
<select id="selectById" parameterType="java.lang.Integer" resultType="com.bjpowernode.domain.Student">
select id, name, email, age from Student where id=#{studentId}
</select>
<!--mybatis内建的别名-->
<select id="selectById" parameterType="int" resultType="com.bjpowernode.domain.Student">
select id, name, email, age from Student where id=#{studentId}
</select>
<!--可不写,mybatis可以通过反射获得-->
<select id="selectById" resultType="com.bjpowernode.domain.Student">
select id, name, email, age from Student where id=#{studentId}
</select>
单个简单参数
即简单数据类型
<!-- #{xxx} -->
多个简单参数
第一种实现方式
@Param
:在方法的形参前面使用的,定义参数名。这个名称可以用在mapper
文件中。
List<T> getInfo(@Param("mya")String a, @Param("myb")Integer b);
<!-- 使用@Param中的mybatis命名参数 -->
<select id="selectById" resultType="com.bjpowernode.domain.Student">
select id, name, email, age from Student where id=#{mya} or age=#{myb}
</select>
第二种实现方式
方法的形参是一个对象,表示多个参数,使用对象的属性值作为参数使用
class Student {
private String name;
private Integer age;
}
<!-- 参数名和对象属性名一致 -->
<select id="selectById" resultType="com.bjpowernode.domain.Student">
select id, name, email, age from Student where id=#{age} or age=#{name}
</select>
按位置传递参数(仅做了解,不做概述)
使用Map
传递参数
Student selectById(Map<String, Object> map);
Map<String, Object> map = new HashMap<>();
map.put("myname", "liuhao");
map.put("myage", 23);
<!-- map的key作为xml传入名称 -->
<select id="selectById" resultType="com.bjpowernode.domain.Student">
select id, name, email, age from Student where id=#{myage} or age=#{myname}
</select>
占位符#
和$
#{}
特点:
- 使用的
PrepareStatement
对象,执行sql
语句, 效率高。 - 使用的
PrepareStatement
对象, 能避免sql
语句,sql
语句执行更安全。 #{}
常常作为列值使用的,位于等号的右侧,#{}
位置的值和数据类型有关的。
${字符}
特点:mybatis
执行${}
占位符的sql
语句
${}
表示字符串连接,把sq1
语句的其他内容和,${}
内容使用字符串(+)
连接的方式连在一起${}
占位符的值,使用的字符串连接方式,有sql
注 入的风险。有代码安全的问题- 使用
Statement
对象,执行sql
语句,效率低 ${}
数据是原样使用的,不会区分数据类型。