Mybatis简介
MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
一、环境准备
- 1、下载mybatis
mybatis-3.4.4.jar
置于 classpath 中 - 2、连接mysql的
mysql-connector-java-5.1.42-bin.jar
二、数据库结构图和项目目录结构图
三、mybatis框架执行过程
1、配置mybatis的配置文件,mybatis-config.xml(名称随意)
2、通过上面的mybatis的配置文件加载mybatis运行环境,在单元测试类中创建SqlSessionFactory数据库会话工厂,一旦被创建就应该在应用的运行期间一直存在,所以SqlSessionFactory使用单例模式创建
3、通过SqlSessionFactory创建SqlSession。SqlSession可以理解一次操作数据库的会话,线程不安全的,建议sqlSession在方法体内创建和使用
4、通过sqlSession获取接口的实现类对象去操作数据库。如果需要提交事务,需要执行SqlSession的commit()方法,或者在打开时传入true值openSession(true),表示自动提交, 可省略commit方法
5、在finally中释放资源,关闭SqlSession
四、代码实现
- 1、
dbconfig.properties
数据库等配置文件
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3333/mybatis
jdbc.username = root
jdbc.password =root
- 2、
mybatis-config.xml
文件配置(主要是数据库连接配置以及注册关联的EmployeeMapper数据库映射)
<?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>
<!-- 引入properties配置文件 -->
<properties resource="dbconfig.properties" ></properties>
<!-- Setting配置项,mapUnderscoreToCamelCase 可以将数据库的xx_yy 映射到java代码中的xxYy -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"></setting>
</settings>
<!-- typeAliases: 别名处理器 -->
<typeAliases>
<!-- type: 指定要起别名的类型的全类名;默认为小写的java类名: 如:employee
alias: 指定要设置的别名
-->
<typeAlias type="com.fc.mybatis.bean.Employee" alias="emp"></typeAlias>
<!-- package批量起别名 -->
<package name="com.fc.mybatis.bean"></package>
<!-- package批量起别名的情况下,在类中@Alias注解为某个类型起新的别名 -->
</typeAliases>
<environments default="development">
<environment id="development">
<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:注册一个sql映射
resource:引用类路径下的sql映射文件
url: 引用网络路径或磁盘下的sql映射文件
注册接口
class:引用(注册)接口
-->
<mapper class="com.fc.mybatis.dao.EmployeeMapper"/>
</mappers>
</configuration>
- 3、
EmployeeMapper.xml
配置(主要是数据库操作的映射)
- 1)、输入映射:
- parameterType:指定输入参数类型可以简单类型、pojo、hashmap。对于综合查询,建议parameterType使用包装的pojo,有利于系统扩展。
- 2)、输出映射:
- resultType:查询到的列名和resultType指定的pojo的属性名一致,才能映射成功。不能和resultMap同时使用。
- reusltMap:可以通过resultMap 完成一些高级映射。如果查询到的列名和映射的pojo的属性名不一致时,
- 通过resultMap设置列名和属性名之间的对应关系(映射关系)。可以完成映射。
- 高级映射: 将关联查询的列映射到一个pojo属性中。(一对一) 将关联查询的列映射到一个List中。(一对多)
- 1)、输入映射:
<?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.fc.mybatis.dao.EmployeeMapper">
<!--
EmployeeMapper.xml文件和EmployeeMapper.java文件的包名一致
namespace: 名称空间;指定为借口的全类名
返回值的类型resultType="com.fc.mybatis.bean.Employee"; resultType ==> bean
public Employee getEmpById(Integer id);
-->
<select id="getEmpById" resultType="com.fc.mybatis.bean.Employee">
select * from tbl_employee where id = #{id}
</select>
<!-- parameterType 指定入参的参数类型
获取自增主键的值:
mysql支持自增主键,自增主键值的获取,mybatis也是利用statement.getGenreatedKeys();
useGeneratedKeys="true";使用自增主键获取主键值策略
keyProperty;指定对应的主键属性,也就是mybatis获取到主键值以后,将这个值封装给javaBean的哪个属性
-->
<insert id="addEmp" parameterType="com.fc.mybatis.bean.Employee"
useGeneratedKeys="true" keyProperty="id">
insert into tbl_employee(last_name, email, gender) values(#{lastName}, #{email}, #{gender})
</insert>
<!--
多个参数正好是我们业务逻辑的数据模型,我们就可以直接传入pojo;#{属性名}:取出传入的pojo的属性值
-->
<update id="updateEmp">
update tbl_employee set last_name=#{lastName},email=#{email},gender=#{gender} where id=#{id}
</update>
<!--
如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,我们也可以传入map
#{key}:取出map中对应的值
#{}:是以预编译的形式,将参数设置到sql语句中;PreparedStatement;防止sql注入
${}:取出的值直接拼装在sql语句中;会有安全问题;
大多情况下,我们去参数的值都应该去使用#{};
原生jdbc不支持占位符的地方我们就可以使用${}进行取值
比如分表、排序。。。;按照年份分表拆分
select * from ${year}_salary where xxx;
select * from tbl_employee order by ${f_name} ${order}
-->
<select id="getEmpByMap" resultType="com.fc.mybatis.bean.Employee">
select * from ${tableName} where id=${id} and last_name=#{lastName}
</select>
<!--
多个参数,需要在EmployeeMapper.java的方法中,明确指定封装参数时map的key;@Param("id")
-->
<select id="getEmpByIdAndLastName" resultType="com.fc.mybatis.bean.Employee">
select * from tbl_employee where id = #{id} and last_name=#{lastName}
</select>
<delete id="deleteEmpById">
delete from tbl_employee where id=#{id}
</delete>
</mapper>
- 4、
EmployeeMapper.java
映射接口定义
package com.fc.mybatis.dao;
import java.util.Map;
import org.apache.ibatis.annotations.Param;
import com.fc.mybatis.bean.Employee;
public interface EmployeeMapper {
public Employee getEmpById(Integer id);
public void addEmp(Employee employee);
public boolean updateEmp(Employee employee);
public void deleteEmpById(Integer id);
// 多个参数要明确指定封装参数时map的key;@Param("id"), 多个参数会被封装成 一个map,才能在EmployeeMapper.xml中直接是使用
public Employee getEmpByIdAndLastName(@Param("id")Integer id,@Param("lastName")String lastName);
public Employee getEmpByMap(Map<String, Object> map);
}
- 5、
Employee.java
文件,Bean
实体类(由于引入框架原因, 一定要添加空的构造方法)
package com.fc.mybatis.bean;
import org.apache.ibatis.type.Alias;
@Alias("emp")
public class Employee {
private Integer id;
private String lastName;
private String email;
private String gender;
public Employee() {
super();
}
public Employee(Integer id, String lastName, String email, String gender) {
super();
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + "]";
}
}
- 6、
MybatisTest.java
单元测试类
package com.fc.mybatis.test;
import static org.junit.Assert.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
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 com.fc.mybatis.bean.Employee;
import com.fc.mybatis.dao.EmployeeMapper;
public class MybatisTest {
public SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
/**
* 1、根据xml配置文件(全局配置文件)创建一个SqlSessionFactory对象 有数据源运行环境信息
* 2、sql映射文件;配置每一个sql,以及sql封装规则等
* 3、将sql映射文件注册到全局配置文件中
* 4、写代码:
* 1)、根据全局配置文件得到SqlSessionFactory
* 2)、使用SqlSession工厂,获取SqlSession对象使用它来执行增删改查 一个SqlSession就是代表和数据库的一次会话,用完关闭
* 3)、使用sql的唯一标志来告诉Mybatis执行哪个sql。sql都是保存sql映射文件中
*
* @throws IOException
*/
@Test
public void test() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession session = sqlSessionFactory.openSession();
try {
// EmployeeMapper.xml中声明的命名空间 + id
Employee emp = session.selectOne("com.fc.mybatis.EmployeeMapper.getEmpById", 1);
System.out.println(emp);
} finally {
session.close();
}
}
@Test
public void test01() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession session = sqlSessionFactory.openSession();
try {
// 获取接口的实现类对象
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
System.out.println(mapper.getEmpById(1));
} finally {
session.close();
}
}
@Test
public void test02() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
// SqlSession session = sqlSessionFactory.openSession();
SqlSession session = sqlSessionFactory.openSession(true); // 设为true表示自动提交, 可省略下面的commit
try {
// 获取接口的实现类对象
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
// System.out.println(mapper.getEmpById(1));
// Employee employee = new Employee(null, "kkkk", "kkkkkk@qq.com", "W");
// mapper.addEmp(employee);
// System.out.println(employee.getId()); // 获取添加到数据后的id的值
// Employee employee = new Employee(91, "kk3", "kk3333@qq.com", "M");
// boolean isUpdateSucc = mapper.updateEmp(employee);
// System.out.println(isUpdateSucc);
// 手动提交数据
// session.commit();
// System.out.println(mapper.getEmpById(9));
// 1、测试多个参数, @Param("id")
// System.out.println(mapper.getEmpByIdAndLastName(9, "kk3"));
// 2、测试多个参数, map类型传入
Map<String, Object> map = new HashMap<>();
map.put("id", 9);
map.put("lastName", "kk3");
map.put("tableName", "tbl_employee");
System.out.println(mapper.getEmpByMap(map));
} finally {
session.close();
}
}
}