MyBatis框架入门

1 概述

1.1 简介

开源免费框架,原名叫iBatis,2010年google code,2013年迁移到github,其是数据层访问框架,本质上是对JDBC的封装;

其优点是不需要写实现类,只需要写需要执行的sql命令即可。

1.2 环境搭建

1.2.1 Jar包

需要的Jar包:

在这里插入图片描述

1.2.2 全局配置文件
<?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="default">
		<!-- 声明可以使用的环境 -->
		<environment id="default">
			<!-- 使用原生的JDBC事务 -->
			<transactionManager type="JDBC"></transactionManager>
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver"/>
				<property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
				<property name="username" value="root"/>
				<property name="password" value="hiatmp"/>
			</dataSource>
		</environment>
	</environments>
	
	<mappers>
		<mapper resource="com/ruanshubin/mapper/Flower.xml"/>
	</mappers>
</configuration>
  • 没有名称和地址要求;

  • 在全局配置文件中引入DTD或者Schema

如果导入dtd后没有提示:

Window–>preference–>XML–>XML catalog–>add 按钮

  • 全局属性

(1) 事务管理 transactionManager

事务Type的取值有:

JDBC: 事务管理使用JDBC原生事务管理模式
MANAGED: 事务管理转交给其他容器

(2)数据源 database

数据源Type的属性为:

POOLED: 使用数据库连接池
UNPOOLED: 不使用数据库连接池,和直接使用JDBC一样
JNDI: Java命名目录接口技术

在高频率访问数据库时,使用数据库连接池可以降低服务器系统压力,提升程序运行效率。

1.2.3 测试数据
create database ssm default character set utf8;

use ssm;

create table flower (
	id int(10) primary key auto_increment comment 'ID',
  name varchar(30) not null comment '花名',
  price float not null comment '价格',
  production varchar(30) not null comment '产地'
);

insert into flower values(default, '矮牵牛', 2.5, '南美阿根廷');
insert into flower values(default, '百日草', 5.0, '墨西哥');
insert into flower values(default, '半枝莲', 4.3, '巴西');

1.3 路径

1.3.1 路径分类

相对路径:从当前资源出发找到其他资源的过程;
绝对路径:从根目录(服务器根目录或项目根目录)出发找其他资源的过程,只要是/开头的都是绝对路径;

1.3.2 绝对路径
  • 请求转发

/表示项目根目录(WebContent)

  • 请求重定向

/表示的是服务器根目录(tomcat/webapps文件夹),故请求转发转为重定向时,需要加上项目前缀。

2 初探

2.1 pojo类

package com.ruanshubin.pojo;

public class Flower {
	private int id;
	private String name;
	private double price;
	private String production;
	
	public Flower(int id, String name, double price, String production) {
		super();
		this.id = id;
		this.name = name;
		this.price = price;
		this.production = production;
	}

	public Flower() {
		super();
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	public String getProduction() {
		return production;
	}

	public void setProduction(String production) {
		this.production = production;
	}

	@Override
	public String toString() {
		return "Flower [id=" + id + ", name=" + name + ", price=" + price + ", production=" + production + "]";
	}
	
}

2.2 mapper类

<!-- namesapce:理解成实现类的全路径(包名+类名) -->
<mapper namespace="a.b" >
	<!-- id:方法名 
		parameterType:定义参数类型
		resultType:返回值类型.
		
		如果方法返回值是list,在resultType中写List的泛型,因为mybatis
		对jdbc封装,一行一行读取数据
	-->
	<!-- 查询全部 -->
	<select id="selAll" resultType="com.ruanshubin.pojo.Flower">
		select * from flower
	</select>
	
	<!-- 查询数据总数 -->
	<select id="selCount" resultType="int">
		select count(*) from flower
	</select>
	
	<select id="selById" parameterType="int" resultType="com.ruanshubin.pojo.Flower">
		select * from flower where id=#{0}
	</select>
	
	<select id="c" resultType="com.ruanshubin.pojo.Flower">
		select * from flower
	</select>
</mapper>

2.3 test类

package com.ruanshubin.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
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 com.ruanshubin.pojo.Flower;

public class Test {
	public static void main(String[] args) throws IOException {
		InputStream is = Resources.getResourceAsStream("mybatis.xml");
		// 使用工厂设计模式
		SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
		// 创建Session
		SqlSession session = factory.openSession();
		// 查询所有
		List<Flower> list = session.selectList("a.b.selAll");
		
		for(Flower flower: list) {
			System.out.println(flower);
		}
		// 查询数据条数
		int total = session.selectOne("a.b.selCount");
		System.out.println(total);
		// 根据ID选择
		Flower flower = session.selectOne("a.b.selById", 1);
		System.out.println(flower);
		
		// Map
		Map<Object, Object> map = session.selectMap("a.b.c", "name");
		System.out.println(map);
		
		session.close();
	}
}

2.4 3种查询方式

  • selectList()

适用于查询结果都需要遍历的需求。

  • selectOne()

适用于返回结果只是变量或单行数据。

  • selectMap

适用于需要在查询结果中通过某列的值取到这行数据的需求。

3 进阶

use ssm;
create table people(
	id int(10) primary key auto_increment comment '编号',
	name varchar(20) comment '姓名',
	age int(3) comment '年龄'
) comment '人员信息表';

insert into people values(default, '张三', 21);
insert into people values(default, '李四', 22);

3.1 全局配置

3.1.1 在mybatis.xml中开启log4j

(1) 必须保证有log4j.jar;
(2) 在src下有log4j.properties

log4j.rootCategory=ERROR, CONSOLE ,LOGFILE

log4j.logger.a.b=DEBUG

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%C %p  %m %n

log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=E:/my.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%C %m %L %n

在MyBatis配置文件中添加:

<settings>
	<setting name="logImpl" value="LOG4J"/>
</settings>
3.1.2 类别名

typeAliases:

  • 系统内置别名:把类型全小写

  • 某个类别名

alias=“自定义”:

<typeAliases>
	<typeAlias type="com.ruanshubin.test.PeopleTest" alias="peo"/>
</typeAliases>
  • 直接给某个包下所有类起别名,不区分大小写

3.2 实现增(insert)、删(delete)、改(update)、查(select)

  • PeopleMapper.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="a.j">
	<select id="selById" resultType="com.ruanshubin.pojo.People" parameterType="map">
		select * from people where id=${id} and name='${name}'
	</select>
	
	<select id="test" resultType="people" parameterType="int">
		<![CDATA[ select * from people where id<#{0}]]>
	</select>
	
	<select id="page" parameterType="map" resultType="com.ruanshubin.pojo.People">
		select * from people limit #{pageStart}, #{pageSize}
	</select>
	
	<insert id="ins" parameterType="com.ruanshubin.pojo.People">
		insert into people values(default, #{name}, #{age})
	</insert>
	
	<update id="upd" parameterType="com.ruanshubin.pojo.People">
		update people set name = #{name} where id = #{id}
	</update>
	
	<delete id="del" parameterType="int">
		delete from people where id = #{0}
	</delete>
</mapper>
  • PeopleTest.java
public class PeopleTest {
	public static void main(String[] args) throws IOException {
		InputStream is = Resources.getResourceAsStream("mybatis.xml");
		// 使用工厂设计模式
		SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
		// 创建Session
		SqlSession session = factory.openSession();
		
		/*HashMap<String, Object> map = new HashMap<>();
		map.put("id", 1);
		map.put("name", "张三");
		People people = session.selectOne("a.j.selById", map);
		System.out.println(people);
		
		List<People> list = session.selectList("a.j.test", 3);
		for(People people1:list) {
			System.out.println(people1);
		}*/
		
		/*HashMap<String, Object> map1 = new HashMap<>();
		map1.put("pageStart", 1);
		map1.put("pageSize", 5);
		List<People> list = session.selectList("a.j.page", map1);
		for(People people:list) {
			System.out.println(people);
		}*/
		
		// 插入数据
		/*People people = new People();
		people.setName("郭靖");
		people.setAge(26);
		try {
			int index = session.insert("a.j.ins", people);
			if(index>0) {
				System.out.println("插入数据成功");
			}else {
				System.out.println("插入数据失败");
			}
		} catch (Exception e) {
			e.printStackTrace();
			session.rollback();
		}
		session.commit();*/
		
		// 更新数据
		/*People people = new People();
		people.setId(8);
		people.setName("黄蓉");
		int index = session.update("a.j.upd", people);
		if(index>0) {
			System.out.println("更新数据成功");
		}else {
			System.out.println("更新数据失败");
		}
		session.commit();*/
		
		// 删除数据
		/*int index = session.delete("a.j.del", 8);
		if(index>0) {
			System.out.println("删除数据成功");
		}else {
			System.out.println("删除数据失败");
		}	
		session.commit();*/
	}
}
  • 自动提交

MyBatis默认是关闭了JDBC的自动提交事务的功能,需要主动调用:

session.commit()

或者:

openSession(True);
  • 增、删、改

(1)JDBC中executeUpdate()执行新增、删除、修改的SQL,其返回值为int,表示受影响的行数;

(2)mybatis中insert、delete、update标签没有resultType属性,认为返回值均是int。

  • 事务回滚

在openSession()时MyBatis会创建SqlSession时同时创建一个Transaction(事务对象),同时autoCommit均为false,如果出现异常,执行session.rollback()回滚事务。

3.2 接口绑定方案及多参数传递

3.2.1 作用

(1)实现创建接口后把mapper.xml由mybatis生成接口的实现类,通过调用接口对象就可以获取mapper.xml中编写的sql;

(2)MyBatis和Spring整合时使用的是这个方案。

3.2.2 实现步骤
  • 创建接口

接口包名和接口名与mapper.xml中的namespace相同;

接口中方法名和mapper.xml标签的id属性相同。

  • 扫描接口

在MyBatis.xml中使用package进行扫描接口和mapper.xml

3.2.3 代码实现
  1. 在mybatis.xml中使用package
<!-- 注册 -->
<mappers>
	<package name="com.ruanshubin.mapper"/>
</mappers>
  1. 编写接口类
public interface PeopleMapper {
	List<People> selAll();
}
  1. 在com.ruanshubin.mapper下新建PeopleMapper.xml
<mapper namespace="com.ruanshubin.mapper.PeopleMapper">
	<select id="selAll" resultType="people">
		select * from people
	</select>
</mapper>

(1) namespace必须和接口全限定路径一致;

(2) id值必须和接口中方法名相同;

(3) 如果接口中方法为多个参数,可以省略parameterType。

  1. 接口绑定
PeopleMapper mapper = session.getMapper(PeopleMapper.class);
		
List<People> list = mapper.selAll();
3.2.4 多参数
  • PeopleMapper.xml
<select id="selById" resultType="people">
	select * from people where id=#{0} or name=#{1}
</select>
  • PeopleMapper.java
// 多参数查询
List<People> selById(Integer id, String name);
  • PeopleTest.java
// 多参数查询
List<People> list = mapper.selById(1, "李四");
for(People people:list) {
	System.out.println(people);
}
3.2.5 多参数(注解)
  • PeopleMapper.xml
<select id="selById" resultType="people">
	select * from people where id=#{id} or name=#{name}
</select>
  • PeopleMapper.java
// 多参数查询
List<People> selById(@Param("id") int id, @Param("name") String name);

3.3 动态SQL

根据不同的条件需要执行不同的SQL命令,称为动态SQL。

3.3.1 if语句
<select id="selById" resultType="people">
	select * from people where 1=1
	<if test="id!=null and id!=0">
		and id = #{id}
	</if>
	<if test="name!=null and name!=''">
		or name=#{name}
	</if>
</select>
3.3.2 where语句

比直接使用if少写where 1=1

<select id="selById2" resultType="people">
	select * from people 
	<where>
		<if test="id!=null and id!=0">
			or id = #{id}
		</if>
		<if test="name!=null and name!=''">
			or name=#{name}
		</if>
	</where>
</select>
3.3.3 choose语句

只要有一个成立,其他就不执行。

choose–>when otherwise

<where>
	<choose>
		<when test="id!=0">
			and id=#{id}
		</when>
		<when test="name!=null and name!=''">
			and name=#{name}
		</when>
	</choose>
</where>
3.3.4 set语句
<update id="setName">
	update people
	<set>
		id=#{id},
		<if test="name!=null and name!=''">
			name=#{name},
		</if>
	</set>
	where id=#{id}
</update>

防止set中没有内容,引起语法错误。

3.3.5 trim语句
  • prefix 在前面添加内容
  • prefixOverrides 去掉前面内容
  • suffix 在后面添加内容
  • suffixOverrides 去掉后面内容
3.3.6 foreach语句
<select id="selIn" parameterType="list" resultType="people">
	select * from people where id in 
	<foreach collection="list" item="abc" open="(" close=")" separator=",">
		#{abc}
	</foreach>
</select>
3.3.7 sql和include

(1) 某些Sql片段如果希望服用,可以使用sql定义片段;

(2) 在select、delete、update、insert中使用include引用。

<select id="selAll1" resultType="people">
	select <include refid="sql"></include> from people
</select>

<sql id="sql">
	name, age
</sql>
3.3.8 bind语句

给参数重新赋值,适用的场景为:

  • 模糊查询
  • 在原内容前或后添加内容
<select id="selLike" parameterType="string" resultType="people">
	<bind name="preName" value="'%' + preName + '%'"/>
	select * from people where name like #{preName}
</select>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值