mybatis介绍
MyBatis 是一个可以自定义SQL、存储过程和高级映射的持久层框架。MyBatis 摒除了大部分的JDBC代码、手工设置参数和结果集重获。MyBatis 只使用简单的XML 和注解来配置和映射基本数据类型、Map 接口和POJO 到数据库记录。相对Hibernate和Apache OJB等“一站式”ORM解决方案而言,Mybatis 是一种“半自动化”的ORM实现。
mybatis架构
1、 mybatis配置
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
2、 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
3、 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
4、 mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
6、 Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
7、 Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
mybatis实现crud
一、准备工作
1、创建maven项目导入jar包
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.43</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
2、数据库创建用户表t_user
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL,
`password` varchar(32) NOT NULL,
`birthday` date DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
3、创建实体类,属性名需要与表的列名一致
public class User implements Serializable {
private Integer id;
private String username;
private String password;
private Date birthday;
private String address;
public User() {
}
public User(String username, String password, Date birthday, String address) {
this.username = username;
this.password = password;
this.birthday = birthday;
this.address = address;
}
get、set、toString方法
}
4、加入mybatis配置文件SqlMapConfig.xml
<?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">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis2?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
</configuration>
5、添加User实体类的sql映射文件user.xml在User类所在包下
<?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">
<!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 -->
<!-- 写sql语句 -->
<mapper namespace="test">
</mapper>
6、在SqlMapConfig.xml中指定sql映射文件User.xml文件所在位置。
<mappers>
<mapper resource="com/scu/mybatis/entity/User.xml"/>
</mappers>
二、增删改查实现
1、添加用户信息
映射文件User.xml中
<!-- 插入数据 -->
<insert id="save" parameterType="com.scu.mybatis.entity.User">
<!-- 返回主键 -->
<selectKey keyProperty="id" order="AFTER" resultType="int">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO t_user (username,password,birthday,address) VALUES(#{username},#{password},#{birthday},#{address})
</insert>
测试:
public class UserTest {
InputStream inputStream;
SqlSession session;
@Before
public void init() throws Exception{
String resource = "sqlMapConfig.xml";
inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = ssfb.build(inputStream);
session = sqlSessionFactory.openSession();
}
@After
public void destroy() throws Exception{
inputStream.close();
session.close();
}
@Test
/*
* session.insert():保存对象,返回主键
* test.save 分别表示SqlMapConfig.xml中的namespace和id
*/
public void testSave(){
User user = new User("张三", "123456", new Date(), "安徽合亳州市");
session.insert("test.save", user);
System.out.println(user.getId());
session.commit();
}
}
控制台输出:1
2、根据id查询用户信息
映射文件User.xml中
<!-- 根据id查询数据 -->
<select id="findById" parameterType="int" resultType="com.scu.mybatis.entity.User">
SELECT * FROM t_user u WHERE u.id=#{id}
</select>
测试:
@Test
/*
* session.selectOne():获取单个对象
*/
public void testFindById(){
User user = (User)session.selectOne("test.findById", 1);
System.out.println(user);
}
控制台输出:
User [id=1, username=张三, password=123456, birthday=Fri Sep 01 00:00:00 CST 2017, address=安徽合亳州市]
3、查询用户列表
映射文件User.xml中
<!-- 查询所有用户信息 -->
<select id="findList" resultType="com.scu.mybatis.entity.User">
SELECT * FROM t_user
</select>
测试:
@Test
/*
* session.selectList():获取对象集合
*/
public void testFindList(){
List<User> list = session.selectList("test.findList");
for (User user : list) {
System.out.println(user);
}
}
控制台输出:
User [id=1, username=张三, password=123456, birthday=Fri Sep 01 00:00:00 CST 2017, address=安徽合亳州市]
4、根据用户名模糊查询
映射文件User.xml中
<!-- 根据用户名模糊查询,一定要写成value不能写成username -->
<select id="findByName" resultType="com.scu.mybatis.entity.User" parameterType="string">
SELECT * FROM t_user u WHERE u.username LIKE '%${value}%'
</select>
测试:
@Test
/*
* 模糊查询
*/
public void testFindByName(){
User user = (User)session.selectOne("test.findByName", "张");
System.out.println(user);
}
控制台输出:
User [id=1, username=张三, password=123456, birthday=Fri Sep 01 00:00:00 CST 2017, address=安徽合亳州市]
5、修改用户信息
映射文件User.xml中
<!-- 修改用户信息 -->
<update id="updateById" parameterType="com.scu.mybatis.entity.User">
UPDATE t_user u SET u.username=#{username},u.password=#{password},
u.birthday=#{birthday},u.address=#{address}
WHERE u.id=#{id}
</update>
测试:
@Test
/*
* session.update():修改用户信息
*/
public void testUpdate(){
User user = (User)session.selectOne("test.findById", 1);
user.setUsername("诺克");
user.setAddress("四川省成都市武侯区");
session.update("test.updateById", user);
session.commit();
}
查看t_user表
用户名跟住址已经成功修改
6、删除用户信息
映射文件User.xml中
<!-- 删除 -->
<delete id="delete" parameterType="int">
DELETE FROM t_user WHERE id=#{id}
</delete>
@Test
/*
* session.delete():删除用户信息
*/
public void testDelete(){
session.delete("test.delete",1);
session.commit();
}
查看t_user表仅存的一条数据也被删除了
3、总结
1、#{}和${}
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换,${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
2、parameterType和resultType
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器List中。
3、selectOne和selectList
selectOne查询一条记录,selectList可以查询一条或多条记录。
4、如果主键自增,添加时如何获取主键
selectKey 标签实现主键返回
keyColumn:主键对应的表中的哪一列
keyProperty:主键对应的pojo中的哪一个属性
order:设置在执行insert语句前执行查询id的sql,在执行 insert语句之后执行查询id的sql
resultType:设置返回的id的类型
LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。
<selectKey keyColumn="id" keyProperty="id" order="AFTER" resultType="int">
SELECT LAST_INSERT_ID()
</selectKey>
注:如果主键用的uuid,那么需要指定order值为”BEFORE”。
5、SqlMapConfig
SqlMapConfig.xml是mybatis核心配置文件,配置文件内容为数据源、事务管理。
SqlMapConfig.xml中配置的内容和顺序如下:
properties(属性):比如引入数据库连接池
属性配置文件中jdbc.properties:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis2?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
然后引入
<properties resource="jdbc.properties"></properties>
接下来就可以用外部数据源实现注入了
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
...
</dataSource>
</environment>
typeAliases(类型别名)
<typeAliases>
<!-- <typeAlias type="com.itheima.mybatis.pojo.User" alias="User"/> -->
<!-- 批量别名定义,扫描整个包下的类,头字母大小写都行 -->
<package name="com.scu.mybatis.entity"/>
</typeAliases>
这样的话,在映射文件中就不需要写实体类的完整名了,比如原先的
返回类型和参数类型为com.scu.mybatis.entity.User的可以写成user/User
plugins(插件)(比如引入mybatis分页插件)
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库-->
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
mapper配置有三种方法
1)、使用相对于类路径的资源,上面使用的就这种方式
<mappers>
<mapper resource="com/itheima/mybatis/pojo/User.xml"/>
</mappers>
2)、使用mapper接口完整名称
<mappers>
<!-- 此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中 -->
<mapper class="com.itheima.mybatis.mapper.UserMapper"/>
3)、注册指定包下的所有mapper接口
<mappers>
<!-- 此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中
-->
<package name="com.itheima.mybatis.mapper"/>
</mappers>
第一、第二种方式都需要一个一个给列出来,当映射文件(mapper接口)太多的时候会显得不方便,第三种方式会相对好用多了。
6、SqlSession
SqlSession是一个面向用户的接口,sqlSession中定义了数据库操作方法,如:查询、插入、更新、删除等。
SqlSession通过SqlSessionFactory创建。
SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建。
每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。