目录
MyBatis概述
- MyBatis是基于Java的持久层框架,内部对JDBC做了封装,使开发者只需要关注SQL语句,而不用关注JDBC的代码,使开发变得更加的简单。
- MyBatis通过XML或者注解的方式将要执行的各种Statement对象配置起来,通过Java对象和statement中SQL的动态参数进行映射,并最终执行SQL语句。执行SQL后,最终将结果已Java对象返回。
- 采用了ORM的思想。
ORM
ORM(对象关系映射)是一种技术,用于将对象模型和关系数据库之间进行映射。它允许开发人员使用面向对象的编程语言来操作数据库,而不需要直接编写 SQL 查询。
ORM 框架负责将应用程序中的对象转换为数据库中的表和行,并提供了一组 API 来执行常见的数据库操作,例如插入、更新、删除和查询数据。
通过使用 ORM,开发人员可以更加方便地进行数据库操作,而不需要手动编写大量的 SQL 语句。ORM 框架会自动处理对象与表之间的转换,简化了开发过程并提高了开发效率。
ORM 框架通常提供以下功能:
- 对象和表之间的映射:ORM 框架根据定义的映射规则,将对象的属性映射到数据库表的列。
- 数据库操作的抽象:ORM 框架提供了一组 API 来执行数据库操作,如插入、更新、删除和查询。
- 缓存管理:ORM 框架通常提供缓存机制,用于提高数据访问性能。
- 事务管理:ORM 框架支持事务操作,确保数据的一致性和完整性。
- 查询语言:ORM 框架通常提供一种查询语言,类似于 SQL,但是更加面向对象。
综合图解:
入门程序:
导入依赖jar包:
<!--mybatis核心包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
编写实体类
/*
用户实体类
用户表
目的:演示mybasic增删改查
*/
public class User implements Serializable{
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private Car car;
public User() {
}
public User(Integer id, String username, Date birthday, String sex, String address, Car car) {
this.id = id;
this.username = username;
this.birthday = birthday;
this.sex = sex;
this.address = address;
this.car = car;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
", car=" + car +
'}';
}
}
public class Car {
private String carName;
public Car(String carName) {
this.carName = carName;
}
public Car() {
}
public String getCarName() {
return carName;
}
public void setCarName(String carName) {
this.carName = carName;
}
@Override
public String toString() {
return "Car{" +
"carName='" + carName + '\'' +
'}';
}
}
编写持久层接口,不用写实现类
/**
* 用户的持久层接口
* 演示mybatis实现增删改查
*/
public interface UserMapper {
/**
* 查询所有的用户
* @return
*/
public List<User> findAll();
}
UserMapper.xml的配置文件
在resources目录下,创建mapper文件夹。编写UserMapper.xml的配置文件,导入约束文件。
UserMapper.xml解释:
- <mapper namespace="com.qcbyjy.mapper.UserMapper">,
叫名称空间,表明以后查找UserMapper接口中的findAll的方法。
- select id="findAll"中的id属性编写的UserMapper接口中的方法的名称,固定的。
- resultType="userMap"表明的是findAll方法的返回值类型。
<?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.qcby.mapper.UserMapper">
<select id="findAll" resultMap="userMap">
select id _id,username _username,birthday _birthday,sex _sex,address _address from user
</select>
<!--配置resultMap,用来进行数据封装 id="唯一的名称,用来被引用的" type="进行封装数据的类型"-->
<resultMap id="userMap" type="com.qcby.domain.User">
<!--
property="JavaBean中的属性"
column="数据库表中的字段"
-->
<result property="id" column="_id"/>
<result property="username" column="_username" />
<result property="birthday" column="_birthday" />
<result property="sex" column="_sex" />
<result property="address" column="_address" />
</resultMap>
</mapper>
编写主配置文件
在resources目录下创建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>
<!--用jdbc.properties连接数据库-->
<properties resource="jdbc.properties"></properties>
<!-- 配置环境们 -->
<environments default="mysql">
<!-- 配置具体的环境 -->
<environment id="mysql">
<!-- 配置事务管理类型 ,使用jdbc管理事物-->
<transactionManager type="JDBC"/>
<!-- 配置是否需要使用连接池,POOLED使用,UNPOOLED不使用 -->
<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 resource="mappers/UserMapper.xml"/>
</mappers>
</configuration>
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///mybasic_db?useSSL=false&useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root
入门程序,测试方法
/**
* 测试查询所有数据
*/
public class TestDemo01 {
@Test
/**
* 第一种方式 通过session创建UserMapper接口的代理对象 调用方法
*/
public void run () throws IOException {
// 加载主配置文件,目的是构建SqlSessionFactory的对象
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
// 创建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 使用SqlSessionFactory工厂对象创建SqlSession对象
SqlSession session = factory.openSession();
// 通过session创建UserMapper接口的代理对象
UserMapper mapper = session.getMapper(UserMapper.class);
// 调用查询所有的方法
List<User> list = mapper.findAll();
// 遍历集合
for (User user : list) {
System.out.println(user);
}
// 释放资源
session.close();
in.close();
}
@Test
/**
* 第二种方式 不用代理对象,会话直接获取方法(使用较少)
*/
public void run2() throws Exception {
// 加载配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
// 构建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取到session对象
SqlSession session = factory.openSession();
// 查询所有的数据
//不用代理对象,用会话直接获取方法
List<User> list = session.selectList("com.qcby.mapper.UserMapper.findAll");
// 变量集合
for (User user : list) {
System.out.println(user);
}
// 关闭资源
session.close();
inputStream.close();
}
入门程序完成!!!
代理Dao方式的CRUD操作
UserMapper接口代码
/**
* 用户的持久层接口
* 演示mybatis实现增删改查
*/
public interface UserMapper {
/**
* 查询所有的用户
* @return
*/
public List<User> findAll();
/**
* 通过id查询
* @param userId
* @return
*/
public User findById(Integer userId);
/**
* 新增
* @param user
*/
public void insert(User user);
/**
* 修改
* @param user
*/
public void update(User user);
/**
* 通过id删除
* @param userId
*/
public void delete(Integer userId);
/**
* 查询总数 聚合函数
* @return
*/
public Integer findByCount();
/**
* 模糊查询
* @param username
* @return
*/
public List<User> findByName(String username);
/**
* 通过汽车名字carName查询
* @param user
* @return
*/
public User findByCarName(User user);
}
UserMapper.xml的配置文件代码
<?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.qcby.mapper.UserMapper">
<select id="findAll" resultMap="userMap">
select id _id,username _username,birthday _birthday,sex _sex,address _address from user
</select>
<!--
配置resultMap,用来进行数据封装
id="唯一的名称,用来被引用的"
type="进行封装数据的类型"
-->
<resultMap id="userMap" type="com.qcby.domain.User">
<!--
property="JavaBean中的属性"
column="表中的字段"
-->
<result property="id" column="_id"/>
<result property="username" column="_username" />
<result property="birthday" column="_birthday" />
<result property="sex" column="_sex" />
<result property="address" column="_address" />
</resultMap>
<!--通过id查询-->
<!--#就和jdbc的 ?占位符一样 但#{}和${}区别很大-->
<select id="findById" parameterType="java.lang.Integer" resultType="com.qcby.domain.User">
select * from user where id=#{userId}
</select>
<!--新增数据、保存操作-->
<insert id="insert" parameterType="com.qcby.domain.User">
/*
keyProperty表示要返回的属性名称
order取值AFTER表示插入数据后的行为
resultType表示返回值的类型
*/
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select last_insert_id();
</selectKey>
insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})
</insert>
<!-- 修改 -->
<update id="update" parameterType="com.qcby.domain.User">
update user set username = #{username},birthday = #{birthday},sex = #{sex},address=#{address} where id = #{id}
</update>
<!-- 删除 -->
<delete id="delete" parameterType="java.lang.Integer">
delete from user where id = #{userId}
</delete>
<!-- 具体函数的查询 -->
<select id="findByCount" resultType="int">
select count(*) from user
</select>
<!-- 模糊查询 -->
<select id="findByName" resultType="com.qcby.domain.User" parameterType="String">
<!-- 第一种方式的SQL语句
select * from user where username like #{username}
-->
<!-- 第二章SQL语句的编写 强调:'%${value}%'不能修改,固定写法(不推荐使用)
select * from user where username like '%${value}%' -->
select * from user where username like '%${value}%'
</select>
<select id="findByCarName" parameterType="com.qcby.domain.User" resultType="com.qcby.domain.User">
select * from user where username=#{car.carName}
</select>
</mapper>
测试代码:
public class TestDemo01 {
@Test
/**
* 第一种方式 通过session创建UserMapper接口的代理对象 调用方法
*/
public void run () throws IOException {
// 加载主配置文件, 目的是构建SqlSessionFactory的对象
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
// 创建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 使用SqlSessionFactory工厂对象创建SqlSession对象
SqlSession session = factory.openSession();
// 通过session创建UserMapper接口的代理对象
UserMapper mapper = session.getMapper(UserMapper.class);
// 调用查询所有的方法
List<User> list = mapper.findAll();
// 遍历集合
for (User user : list) {
System.out.println(user);
}
// 释放资源
session.close();
in.close();
}
@Test
/**
* 第二种方式 不用代理对象,会话直接获取方法(使用较少)
*/
public void run2() throws Exception {
// 加载配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
// 构建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取到session对象
SqlSession session = factory.openSession();
// 查询所有的数据
//不用代理对象,用会话直接获取方法
List<User> list = session.selectList("com.qcby.mapper.UserMapper.findAll");
// 变量集合
for (User user : list) {
System.out.println(user);
}
// 关闭资源
session.close();
inputStream.close();
}
/**
* 测试查询单一数据 通过id查询 使用代理对象的形式
*/
@Test
public void run3() throws IOException {
//1.加载环境
// 加载主配置文件,目的是构建SqlSessionFactory的对象
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
// 创建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 使用SqlSessionFactory工厂对象创建SqlSession对象
SqlSession session = factory.openSession();
// 通过session创建UserMapper接口的代理对象
UserMapper mapper = session.getMapper(UserMapper.class);
// 调用查询所有的方法
User user1 = mapper.findById(5);
System.out.println(user1);
//关闭资源 会话关闭
session.close();
//流关闭
in.close();
}
/**
* 测试新增数据
*/
@Test
public void run4() throws IOException {
//1.加载环境
// 加载主配置文件,目的是构建SqlSessionFactory的对象
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
// 创建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 使用SqlSessionFactory工厂对象创建SqlSession对象
SqlSession session = factory.openSession();
// 通过session创建UserMapper接口的代理对象
UserMapper mapper = session.getMapper(UserMapper.class);
// 调用新增的方法
User user=new User();
user.setUsername("小王1");
user.setBirthday(new Date());
user.setSex("女");
user.setAddress("香港");
mapper.insert(user);
session.commit();
System.out.println(user.getId());
//关闭资源 会话关闭
session.close();
//流关闭
in.close();
}
/**
* 测试修改数据
*/
@Test
public void run5() throws IOException {
//1.加载环境
// 加载主配置文件,目的是构建SqlSessionFactory的对象
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
// 创建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 使用SqlSessionFactory工厂对象创建SqlSession对象
SqlSession session = factory.openSession();
// 通过session创建UserMapper接口的代理对象
UserMapper mapper = session.getMapper(UserMapper.class);
User user=new User();
user.setId(31);
user.setUsername("beautiful01");
user.setBirthday(new Date());
user.setSex("woman02");
user.setAddress("HongKong03");
mapper.update(user);
session.commit();
//关闭资源 会话关闭
session.close();
//流关闭
in.close();
}
/**
* 测试删除数据
*/
@Test
public void run6() throws IOException {
//1.加载环境
// 加载主配置文件,目的是构建SqlSessionFactory的对象
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
// 创建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 使用SqlSessionFactory工厂对象创建SqlSession对象
SqlSession session = factory.openSession();
// 通过session创建UserMapper接口的代理对象
UserMapper mapper = session.getMapper(UserMapper.class);
mapper.delete(31);
session.commit();
//关闭资源 会话关闭
session.close();
//流关闭
in.close();
}
/**
* 测试 查询数据总量
*/
@Test
public void run7() throws IOException {
//1.加载环境
// 加载主配置文件,目的是构建SqlSessionFactory的对象
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
// 创建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 使用SqlSessionFactory工厂对象创建SqlSession对象
SqlSession session = factory.openSession();
// 通过session创建UserMapper接口的代理对象
UserMapper mapper = session.getMapper(UserMapper.class);
Integer byCount = mapper.findByCount();
System.out.println(byCount);
//关闭资源 会话关闭
session.close();
//流关闭
in.close();
}
/**
* 测试 模糊查询
*/
@Test
public void run8() throws IOException {
//1.加载环境
// 加载主配置文件,目的是构建SqlSessionFactory的对象
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
// 创建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 使用SqlSessionFactory工厂对象创建SqlSession对象
SqlSession session = factory.openSession();
// 通过session创建UserMapper接口的代理对象
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> userList = mapper.findByName("张");
for (User user : userList) {
System.out.println(user);
}
//关闭资源 会话关闭
session.close();
//流关闭
in.close();
}
/**
* 测试多表查询查询 根据carname查询
*/
@Test
public void run9() throws IOException {
//1.加载环境
// 加载主配置文件,目的是构建SqlSessionFactory的对象
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
// 创建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 使用SqlSessionFactory工厂对象创建SqlSession对象
SqlSession session = factory.openSession();
// 通过session创建UserMapper接口的代理对象
UserMapper mapper = session.getMapper(UserMapper.class);
User user=new User();
Car car=new Car();
car.setCarName("张三");
user.setCar(car);
User user1 = mapper.findByCarName(user);
System.out.println(user1);
//关闭资源 会话关闭
session.close();
//流关闭
in.close();
}
}
模糊查询符号使用的区别
- 通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
- 通过$可以将传入的内容拼接在中且不进行类型转换,${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
动态sql
if标签
<select id="findByWhere" parameterType="com.example.domain.User" resultType="com.example.domain.User">
select * from user where 1 = 1
<if test="username != null and username != ''">
and username like #{username}
</if>
<if test="sex != null and sex != ''">
and sex = #{sex}
</if>
</select>
where标签
<!--使用where关键字-->
<select id="findByWhere" parameterType="com.example.domain.User" resultType="com.example.domain.User">
select * from user
<where>
<if test="username != null and username != ''">
and username like #{username}
</if>
<if test="sex != null and sex != ''">
and sex = #{sex}
</if>
</where>
</select>
foreach标签
需要将要用到的数组封装进实体类中
// 主键
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
// 定义ids属性,用来存储所有的id
private List<Integer> ids;
<!--foreach标签 select * from user where id = 1 or id = 2 or id = 3 -->
<select id="findByIds" parameterType="com.example.domain.User" resultType="com.example.domain.User">
select * from user
<where>
<foreach collection="ids" open="id = " separator="or id = " item="i">
#{i}
</foreach>
</where>
</select>
提取公用sql
<!--提取公共的SQL-->
<sql id="findAllSql">
select * from user
</sql>
<select id="findAll" resultType="com.example.domain.User">
<include refid="findAllSql" />
/*select * from user*/
</select>
返回类型封装
account中包含id,uid,money三个基本类型以及一个对象可以使用下面的方式来封装返回的数据。
<!--进行数据封装-->
<resultMap id="accountMap" type="com.example.domain.Account">
<result property="id" column="id" />
<result property="uid" column="uid"/>
<result property="money" column="money"/>
<association property="user" javaType="com.example.domain.User">
<result property="username" column="username"/>
<result property="address" column="address"/>
</association>
</resultMap>