java框架学习之Mybaits(1)

             简介:

Mybatis是什么?

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。

MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码

Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

Mybatis框架原理(核心)

                                                        

  1. mybatis配置文件,包括Mybatis全局配置文件和Mybatis映射文件,其中全局配置文件配置了数据源、事务等信息;映射文件配置了SQL执行相关的 信息。
  2. mybatis通过读取配置文件信息(全局配置文件和映射文件),构造出SqlSessionFactory即会话工厂。
  3. 通过SqlSessionFactory,可以创建SqlSession即会话。Mybatis是通过SqlSession来操作数据库的。
  4. SqlSession本身不能直接操作数据库,它是通过底层的Executor执行器接口来操作数据库的。Executor接口有两个实现类,一个是普通执行器,一个是缓存执行器(默认)
  5. Executor执行器要处理的SQL信息是封装到一个底层对象MappedStatement中。该对象包括:SQL语句、输入参数映射信息、输出结果集映射信息。其中输入参数和输出结果的映射类型包括java的简单类型、HashMap集合对象、POJO对象类型。

操作测试

环境搭建

下载mybaits包:https://github.com/mybatis/mybatis-3/releases

解压后的mybaits目录:

 

工程搭建(三步)

第一步:创建java工程

用eclipse创建一个java工程,jdk使用1.8+,并创建3个source folder,src用来放源码,config用来放全局的配置文件,test用来测试:

第二步:在项目下创建lib目录,加入jar包

加入以下四部分jar包,其中junit的jar包,是非必须的。

Mybatis核心包

 

Mybatis依赖包

 

MySQL驱动包

Junit单元测试包(单元测试需要的包)

添加之后的lib包目录:

 

第三步:添加log4j.properties文件

Mybatis使用的日志包是log4j的,所以需要添加log4j.properties。

文件内容可以从mybatis目录中的pdf中拷贝

在classpath下创建log4j.properties如下: 

 

日志级别在开发阶段设置成DEBUG,在生产阶段设置成INFO或者ERROR

数据库环境搭建:

/*Table structure for table `user` */

CREATE TABLE `user` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `username` VARCHAR(32) NOT NULL COMMENT '用户名称',
  `birthday` DATE DEFAULT NULL COMMENT '生日',
  `sex` CHAR(1) DEFAULT NULL COMMENT '性别',
  `address` VARCHAR(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;


/*Table structure for table `items` */

CREATE TABLE `items` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,/*自增主键*/
  `name` VARCHAR(32) NOT NULL COMMENT '商品名称',
  `price` FLOAT(10,1) NOT NULL COMMENT '商品定价',
  `detail` TEXT COMMENT '商品描述',
  `pic` VARCHAR(64) DEFAULT NULL COMMENT '商品图片',
  `createtime` DATETIME NOT NULL COMMENT '生产日期',
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;



/*Table structure for table `orders` */

CREATE TABLE `orders` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `user_id` INT(11) NOT NULL COMMENT '下单用户id',
  `number` VARCHAR(32) NOT NULL COMMENT '订单号',
  `createtime` DATETIME NOT NULL COMMENT '创建订单时间',
  `note` VARCHAR(100) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`),
  KEY `FK_orders_1` (`user_id`),
  CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=INNODB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

/*Table structure for table `orderdetail` */

CREATE TABLE `orderdetail` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `orders_id` INT(11) NOT NULL COMMENT '订单id',
  `items_id` INT(11) NOT NULL COMMENT '商品id',
  `items_num` INT(11) DEFAULT NULL COMMENT '商品购买数量',
  PRIMARY KEY (`id`),
  KEY `FK_orderdetail_1` (`orders_id`),
  KEY `FK_orderdetail_2` (`items_id`),
  CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=INNODB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

插入数据:

/*Data for the table `user` */

insert  into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (1,'王五',NULL,'2',NULL),(10,'张三','2014-07-10','1','北京市'),(16,'张小明',NULL,'1','河南郑州'),(22,'陈小明',NULL,'1','河南郑州'),(24,'张三丰',NULL,'1','河南郑州'),(25,'陈小明',NULL,'1','河南郑州'),(26,'王五',NULL,NULL,NULL);


/*Data for the table `items` */

insert  into `items`(`id`,`name`,`price`,`detail`,`pic`,`createtime`) values (1,'台式机',3000.0,'该电脑质量非常好!!!!',NULL,'2015-02-03 13:22:53'),(2,'笔记本',6000.0,'笔记本性能好,质量好!!!!!',NULL,'2015-02-09 13:22:57'),(3,'背包',200.0,'名牌背包,容量大质量好!!!!',NULL,'2015-02-06 13:23:02');


/*Data for the table `orders` */

insert  into `orders`(`id`,`user_id`,`number`,`createtime`,`note`) values (3,1,'1000010','2015-02-04 13:22:35',NULL),(4,1,'1000011','2015-02-03 13:22:41',NULL),(5,10,'1000012','2015-02-12 16:13:23',NULL);


/*Data for the table `orderdetail` */

insert  into `orderdetail`(`id`,`orders_id`,`items_id`,`items_num`) values (1,3,1,1),(2,3,2,3),(3,4,3,4),(4,4,2,3);

表关系如下:

 

 

创建全局配置文件

在config目录下,创建SqlMapConfig.xml文件,该名称不是固定不变的。

内容可以从pdf中复制

 

 

在config目录下创建db.properties文件,然后配置好数据库连接信息,并在SqlMapConfig.xml中添加properties标签加载数据库配置文件:

 

 

基础测试:

实现用户的增删改查功能

在config下创建类映射文件User.xml:

 

根据id查询用户 :

 

 

 创建pojo类(每个字段都私有,并且有标准的get,set方法):

package mybaits_test.po;

import java.util.Date;

public class User {
	private int id;
	private String username;
	private Date birthday;
	private char sex;
	private String address;
	public int getId() {
		return id;
	}
	public void setId(int 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 char getSex() {
		return sex;
	}
	public void setSex(char sex) {
		this.sex = sex;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", birthday=" + birthday + ", sex=" + sex + ", address="
				+ address + "]";
	}
	
}

 

 测试代码:

输出结果:

 User [id=10, username=张三, birthday=Thu Jul 10 00:00:00 CST 2014, sex=1, address=北京市]

可以看到名成相同的字段被自动赋值

添加用户,删除用户,修改用户信息

映射文件:

User.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="test">
	<select id="findUserById" parameterType="int" resultType="mybaits_test.po.User">
		SELECT * FROM USER WHERE id=#{id}
	</select>
	<insert id="insertUser" parameterType="mybaits_test.po.User" >
		INSERT INTO USER (username,sex,address) VALUE(#{username},#{sex},#{address})
	</insert>
	<update id="updateUser" parameterType="int">
		UPDATE USER SET username='yan' where id=#{id}
	</update>
	<delete id="deleteUser" parameterType="int">
		DELETE FROM USER WHERE id=#{id}
	</delete>
</mapper>

测试代码:

package mybaits_test;

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;
import org.junit.jupiter.api.Test;

import mybaits_test.po.User;

public class Test01 {
	@Test
	public void testFindUserById() throws IOException {
		//获取SqlSession
		String sqlMapConfigPath="SqlMapConfig.xml";
		InputStream in=Resources.getResourceAsStream(sqlMapConfigPath);
		SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
		SqlSessionFactory sqlSessionFactory=builder.build(in);
		SqlSession sqlSession=sqlSessionFactory.openSession();
		int id=10;
		User user = sqlSession.selectOne("test.findUserById", id);
		System.out.println(user);
		
	}
	
	@Test
	public void testInsertUser() throws IOException {
		//获取SqlSession
		String sqlMapConfigPath="SqlMapConfig.xml";
		InputStream in=Resources.getResourceAsStream(sqlMapConfigPath);
		SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
		SqlSessionFactory sqlSessionFactory=builder.build(in);
		SqlSession sqlSession=sqlSessionFactory.openSession();
		User user=new User();
		user.setUsername("闫绍帅");
		user.setSex('2');
		user.setAddress("合肥长丰");
		sqlSession.insert("test.insertUser", user);
		sqlSession.commit();
		
	}
	@Test
	public void testUpdateUser() throws IOException {
		//获取SqlSession
		String sqlMapConfigPath="SqlMapConfig.xml";
		InputStream in=Resources.getResourceAsStream(sqlMapConfigPath);
		SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
		SqlSessionFactory sqlSessionFactory=builder.build(in);
		SqlSession sqlSession=sqlSessionFactory.openSession();
		sqlSession.update("test.updateUser", 29);

		sqlSession.commit();
		
	}
	
	@Test
	public void testDeleteUser() throws IOException {
		//获取SqlSession
		String sqlMapConfigPath="SqlMapConfig.xml";
		InputStream in=Resources.getResourceAsStream(sqlMapConfigPath);
		SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
		SqlSessionFactory sqlSessionFactory=builder.build(in);
		SqlSession sqlSession=sqlSessionFactory.openSession();
		sqlSession.delete("test.deleteUser", 29);
		
		sqlSession.commit();
		
	}
}

 模糊查询

#{}和${}区别

#{}表示占位符?,#{}接收简单类型的参数时,里面的名称可以任意(这里如果用'%#{}%',就相当于'%?%',是不对的)

${}表示拼接符,${}接收简单类型的参数时,里面的名称必须是value

${}里面的值会原样输出,不加解析(如果该参数值是字符串,不会添加引号)

${}存在sql注入的风险,但是有些场景下必须使用,比如排序后面会动态传入排序的列名

插入之主键返回:

mysql

(1)利用自增主键则使用 SELECT LAST_INSERT_ID()函数查询

public void testInsertUserRTId() throws IOException {
		//获取SqlSession
		String sqlMapConfigPath="SqlMapConfig.xml";
		InputStream in=Resources.getResourceAsStream(sqlMapConfigPath);
		SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
		SqlSessionFactory sqlSessionFactory=builder.build(in);
		SqlSession sqlSession=sqlSessionFactory.openSession();
		User user=new User();
		user.setUsername("闫绍帅");
		user.setSex('2');
		user.setAddress("合肥长丰");
		
		sqlSession.insert("test.insertUserRTId", user);
		System.out.println("id="+user.getId());
		sqlSession.commit();
		
	}

 (2)使用mysql随机主键则使用SELECT UUID()

 

 Oracle

序列也就是sequence,它是Oracle的主键生成策略

 

Mapper代理的开发dao

即开发mapper接口(相当于代理dao接口)

Mapper代理使用的是jdk的代理策略。

Mapper代理的开发规范

  1. mapper接口的全限定名要和mapper映射文件的namespace值一致。
  2. mapper接口的方法名称要和mapper映射文件的statement的id一致。
  3. mapper接口的方法参数类型要和mapper映射文件的statement的parameterType的值一致,而且它的参数是一个。
  4. mapper接口的方法返回值类型要和mapper映射文件的statement的resultType的值一致。

src下新建dao包,下面新建一个UserDao接口,添加若干方法

config下新建UserMapper.xml文件,各个对应关系如下,在SqlMapConfig.xml中添加User Mapper.xml文件的映射

各个对应关系如下:

接口:

映射文件:

测试代码:

还可以这样写

在全局配置文件中加载mapper文件的写法:

<mapper resource=""/>的写法:
使用相对于类路径的资源,用于加载单个的配置文件
如:<mapper resource="sqlmap/User.xml" />

<mapper url=""/>
使用完全限定路径
如:<mapper url="file:///D:\workspace_spingmvc\mybatis_01\config\sqlmap\User.xml" />
 

<mapper class=""/>
使用mapper接口的全限定名
如:<mapper class="cn.itcast.mybatis.mapper.UserMapper"/>

注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下
 

<package name=""/>(推荐)
注册指定包下的所有映射文件,
如:<package name="cn.itcast.mybatis.mapper"/>

注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下

改用推荐方式加载映射文件:

映射文件UserMapper.xml:

映射接口:

目录结构:

 

加载映射文件:

测试代码:

 

全局配置文件

概览

SqlMapConfig.xml的配置内容和顺序如下(顺序不能乱):

Properties(属性)

Settings(全局参数设置)

typeAliases(类型别名)

typeHandlers(类型处理器)

objectFactory(对象工厂)

plugins(插件)

environments(环境信息集合)

         environment(单个环境信息)

                   transactionManager(事物)

                   dataSource(数据源)

mappers(映射器)

 

常用配置

Properties

Db.properties

 

SqlMapConfig.xml

 

 

加载的顺序

  1. 先加载properties中property标签声明的属性
  2. 再加载properties标签引入的java配置文件中的属性
  3. parameterType的值会和properties的属性值发生冲突。

settings

mybatis全局配置参数,全局参数将会影响mybatis的运行行为。

 

 

 

typeAliases

对po类进行别名的定义

mybatis支持的别名

别名

映射的类型

_byte

byte

_long

long

_short

short

_int

int

_integer

int

_double

double

_float

float

_boolean

boolean

string

String

byte

Byte

long

Long

short

Short

int

Integer

integer

Integer

double

Double

float

Float

boolean

Boolean

date

Date

decimal

BigDecimal

bigdecimal

BigDecimal

 

自定义别名

 映射文件:

输入映射:

1.简单类型

 

2.po类映射

3.嵌套po类映射

 

Map

同传递POJO对象一样,mapkey相当于pojo的属性名,值相当于属性值

 

resultType

使用要求

使用resultType进行结果映射时,需要查询出的列名和映射的对象的属性名一致,才能映射成功。

如果查询的列名和对象的属性名全部不一致,那么映射的对象为空。

如果查询的列名和对象的属性名有一个一致,那么映射的对象不为空,但是只有映射正确那一个属性才有值。

如果查询的sql的列名有别名,那么这个别名就是和属性映射的列名(即根据别名去匹配)。

简单类型

注意,对简单类型的结果映射也是有要求的,查询的列必须是一列,才能映射为简单类型。

查询用户总数:

配置文件

测试

接口

 

 

Pojo对象和pojo列表

查询所有用户列表:

resultMap

使用要求

使用resultMap进行结果映射时,不需要查询的列名和映射的属性名必须一致。但是需要声明一个resultMap,来对列名和属性名进行映射。

 

动态sql

在mybatis中,它提供了一些动态sql标签,可以让程序员更快的进行mybatis的开发,这些动态sql可以通过sql的可重用性。。

常用的动态sql标签:if标签、where标签、sql片段、foreach标签

If标签/where标签

 
 

 

Sql片段

Sql片段可以让代码有更高的可重用性

Sql片段需要先定义后使用

 

Foreach标签

可以循环传入参数值

根据用户ID集合进行查询

SELECT * FROM USER WHERE id IN (?,?,?)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值