概述
文章目录
- MyBatis简介
- 什么是MyBatis?
- JDBC编程存在的问题?MyBatis如何解决?
- MyBatis的工作原理
- MyBatis入门程序
- 准备工作
- 功能实现
- 第一个功能:insert-新增商品信息
- update-根据id更改信息
- select-通过id来查询商品信息
- 根据id来删除信息
- 查询商品列表
- 新增商品返回主键
MyBatis简介
什么是MyBatis?
MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。 MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索。 MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的 POJOs(Plan Old Java Objects,普通的 Java对象)映射成数据库中的记录
JDBC编程存在的问题?MyBatis如何解决?
1) 数据库连接的创建、释放频繁造成系统资源浪费从而影响了性能,如果使用数据库连接池就可以解决这个问题。当然JDBC同样能够使用数据源。
- 解决:在SQLMapConfig.xml中配置数据连接池,使用数据库连接池管理数据库连接。
2) SQL语句在写代码中不容易维护,事件需求中SQL变化的可能性很大,SQL变动需要改变JAVA代码。
- 解决:将SQL语句配置在mapper.xml文件中与java代码分离。
3) 向SQL语句传递参数麻烦,因为SQL语句的where条件不一定,可能多,也可能少,占位符需要和参数一一对应。
- 解决:Mybatis自动将java对象映射到sql语句。
4) 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
- 解决:Mbatis自动将SQL执行结果映射到java对象。
MyBatis的工作原理
配置文件对于MyBatis来说非常重要,MyBatis总共有两类配置文件:
-
一类用于指定数据源、事务属性以及其他一些参数配置信息(通常是一个独立的文件,可以称之为全局配置文件);
-
另一类则用于 指定数据库表和程序之间的映射信息(可能不止一个文件,我们称之为映射文件)
Mybatis大概的执行过程:
MyBatis入门程序
我们先来编写一个简单的入门程序,在编写的过程中介绍MyBatis处理问题的思路和方法。
- 需求:新增商品信息、修改商品信息、删除商品信息、查询商品列表、根据id查询单个商品信息。
准备工作
- 新建商品表:
CREATE TABLE `t_product` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255),
`code` VARCHAR(255),
`price` DOUBLE(10,0),
`count` INT(11),
`description` VARCHAR(255),
`status` INT(255),
`create_time` DATETIME,
PRIMARY KEY (`id`)
);
- 搭建MyBatis开发环境:
- 将 mybatis-x.x.x.jar 文件置于 classpath 中即可。
- 将数据库驱动jar包置于classpath中(这两个jar包通常配合使用)。
效果图:
- 添加全局配置文件mybatis-config.xml到项目src目录下。
XML 配置文件中包含了对 MyBatis 系统的核心设置,包含获取数据库连接实例的数据源(DataSource)和决定事务作用域和控制方式的事务管理器(TransactionManager)。要注意 XML 头部的声明,它用来验证 XML 文档正确性。environment 元素体中包含了事务管理和连接池的配置。mappers 元素则是包含一组映射器(mapper),这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息。下面是全局配置文件最关键的部分:
<!-- 头部声明 -->
<?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是mybatis配置文件的根标签,用来配置mybatis运行环境等信息 -->
<configuration>
<!-- environments用来配置mybatis运行环境:数据源,事务管理…… -->
<!-- 一个environment代表一种运行环境,默认是development -->
<environments default="development">
<environment id="development">
<!-- transationManager的type表示的是mybatis的事务管理采用的是JDBC数据管理 -->
<transactionManager type="JDBC"/>
<!-- mybatis所应用的数据源,type表示的是数据源采用数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/0417test"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- mappers用来配置mybatis要加载的mapper.xml文件或者mapepr接口 -->
<mappers>
<!--在这里加载映射器-->
<mapper resource="com/xx/mapper/ProductMapper.xml"/>
</mappers>
</configuration>
- 创建映射器comxxmapperProductMapper.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是mapper.xml文件的根标签,mapper标签内,编写sql语句
namespace:命名空间,区分每个mapper.xml
取值格式:mapper文件所在包的包名.mapper文件名(不带后缀)
-->
<mapper namespace="com.xx.mapper.ProductMapper">
<!-- 在这里用标签编写sql语句 -->
</mapper>
- 添加log4j.properties文件到src目录下,更改全局配置文件:
日志是应用软件中不可缺少的部分,Apache的开源项目Log4j是一个功能强大的日志组件,提供方便的日志记录。MyBatis的jar包中整合了Log4j功能,我们只需要添加配置文件然后更改全局配置文件就可以使用了:
- 在src目录下创建log4j.properties并添加:
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
- 更改mybatis-config.xml:
……
<configuration>
<settings>
<!-- 配置mybatis日志采用的是log4j -->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
……
- 创建实体类comxxentityProduct.class,与数据库中表t_product相对应:
package com.xx.entity;
import java.util.Date;
public class Product {
// CREATE TABLE `t_product` (
// `id` INT(11) NOT NULL AUTO_INCREMENT,
// `name` VARCHAR(255),
// `code` VARCHAR(255),
// `price` DOUBLE(10,0),
// `count` INT(11),
// `description` VARCHAR(255),
// `status` INT(255),
// `create_time` DATETIME,
// PRIMARY KEY (`id`)
// );
private Integer id;
private String name;
private String code;
private Double price;
private Integer count;
private String description;
private Integer status;
private Date create_time;
public Product() {
super();
// TODO Auto-generated constructor stub
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Date getCreate_time() {
return create_time;
}
public void setCreate_time(Date create_time) {
this.create_time = create_time;
}
}
至此,我们的基础工作就做好了,接下来就可以实现功能了,来看此时的项目结构:
功能实现
第一个功能:insert-新增商品信息
- 更改ProductMapper.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.xx.mapper.ProductMapper">
<!-- 新增商品信息 id:表示用来区分sql语句 -->
<!-- parameterType表示输入的参数类型,可以是java的基础数据类型和引用数据类型 -->
<insert id="insertProductInfo" parameterType="com.xx.entity.Product">
<!-- 在insert标签中写sql语句,#{}表示占位符,里面写传入参数的属性值(即product.xxx) -->
insert into t_product values(
#{id},
#{name},
#{code},
#{price},
#{count},
#{description},
#{status},
#{create_time}
);
</insert>
</mapper>
- 编写测试类comxxtestMyTest.class:
package com.xx.test;
import java.io.IOException;
import java.util.Date;
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.xx.entity.Product;
public class MyTest {
// 这里我们使用单元测试,单元测试有几个规范:
// public 无参 无返回值 方法名以test开头
// 使用单元测试需要将JUnit4添加到classpath中
@Test
public void testInsertProductInfo() throws IOException {
// 每一个 MyBatis 的应 用程序 都以一 个 SqlSessionFactory 对象的 实例为 核心。
// SqlSessionFactory 对 象 的 实 例 可以 通 过 SqlSessionFactoryBuilder 对 象 来 获得。
// SqlSessionFactoryBuilder 对象可以从 XML 配置文件
// 或从 Configuration 类的实例中构建 SqlSessionFactory 对象
// 1.获取到SqlSessionFactory对象
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
.build(Resources.getResourceAsReader("mybatis-config.xml"));
// 2.获取SqlSession对象
SqlSession session = sessionFactory.openSession();
// 3.创建product对象
Product product = new Product();
product.setName("华为手机");
product.setCode("10001");
product.setPrice(4499.00);
product.setCount(10);
product.setDescription("国产手机品牌");
product.setStatus(1);
product.setCreate_time(new Date());
// 4.插入数据insert:
// 第一个参数是要执行的sql语句(我们已经写在ProductMapper.xml中),它的取值是 namespece+id
// 第二个参数就是执行sql语句传递的参数,类型是parameterType所指定的参数类型
session.insert("com.xx.mapper.ProductMapper.insertProductInfo", product);
// 5.手动提交事务
session.commit();
// 6.释放资源
session.close();
}
}
- 执行结果:
- 控制台
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 1386767190.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@52a86356]
==> Preparing: insert into t_product values( ?, ?, ?, ?, ?, ?, ?, ? );
==> Parameters: null, 华为手机(String), 10001(String), 4499.0(Double), 10(Integer), 国产手机品牌(String), 1(Integer), 2019-04-17 22:20:32.562(Timestamp)
<== Updates: 1
Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@52a86356]
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@52a86356]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@52a86356]
Returned connection 1386767190 to pool.
- 数据库
id | name | code | price | count | description | status | create_time |
---|---|---|---|---|---|---|---|
1 | 华为手机 | 10001 | 4499 | 10 | 国产手机品牌 | 1 | 2019-04-17 22:20:32 |
我们的第一个功能:新增商品信息就完成了,接下来我们根据这个流程,依次来实现其余功能:
update-根据id更改信息
- ProductMapper.xml
……
<mapper namespace="com.xx.mapper.ProductMapper">
……
<update id="alterPriceById" parameterType="com.xx.entity.Product">
update t_product set price = #{price} where id = #{id}
</update>
</mapper>
- MyTest.class
@Test
public void testAlterPriceById() throws IOException {
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
.build(Resources.getResourceAsReader("mybatis-config.xml"));
SqlSession session = sessionFactory.openSession();
Product product = new Product();
// 更改华为手机的价格
product.setId(1);
product.setPrice(5000.00);
session.update("com.xx.mapper.ProductMapper.alterPriceById", product);
session.commit();
session.close();
}
select-通过id来查询商品信息
- ProductMapper.xml
……
<mapper namespace="com.xx.mapper.ProductMapper">
……
<!-- 有必要说明一下parameterType的值为引用类型和基础数据类型的区别 :
如果是基础数据类型、String那么#{}中可以使任何变量名,包括中文和value
如果是引用数据类型(自定义的entity),那么#{}中必须是entity所包含的属性名-->
<select id="selectInfoById" parameterType="int" resultType="com.xx.entity.Product">
select * from t_product where id = #{这里写任意变量名}
</select>
</mapper>
- MyTest.class
@Test
public void testSelectInfoById() throws IOException {
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
.build(Resources.getResourceAsReader("mybatis-config.xml"));
SqlSession session = sessionFactory.openSession();
// 查询id为1的商品信息,返回类型是Product
Product product = session.selectOne("com.xx.mapper.ProductMapper.selectInfoById", 1);
// 这里返回Product重写toString方法以便输出
// 如果我们有log4j,就没有必要输出,可以直接在控制台查看返回的信息
System.out.println(product);
session.commit();
session.close();
}
- 控制台
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 540642172.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@20398b7c]
==> Preparing: select * from t_product where id = ?
==> Parameters: 1(Integer)
<== Columns: id, name, code, price, count, description, status, create_time
<== Row: 1, 华为手机, 10001, 5000, 10, 国产手机品牌, 1, 2019-04-17 22:20:32.0
<== Total: 1
Product [id=1, name=华为手机, code=10001, price=5000.0, count=10, description=国产手机品牌, status=1, create_time=Wed Apr 17 22:20:32 CST 2019]
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@20398b7c]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@20398b7c]
Returned connection 540642172 to pool.
根据id来删除信息
- ProductMpper.mapper
……
<mapper namespace="com.xx.mapper.ProductMapper">
……
<delete id="deleteProductById" parameterType="int">
delete from t_product where id = #{id}
</delete>
</mapper>
- MyTest.class
@Test
public void testDeleteProductById() throws IOException {
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
.build(Resources.getResourceAsReader("mybatis-config.xml"));
SqlSession session = sessionFactory.openSession();
session.delete("com.xx.mapper.ProductMapper.deleteProductById", 1);
session.commit();
session.close();
}
- 控制台
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 2025864991.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@78c03f1f]
==> Preparing: delete from t_product where id = ?
==> Parameters: 1(Integer)
<== Updates: 1
Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@78c03f1f]
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@78c03f1f]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@78c03f1f]
Returned connection 2025864991 to pool.
查询商品列表
现在我们往表中多加几条信息:
id | name | code | price | count | description | status | create_time |
---|---|---|---|---|---|---|---|
2 | 华为手机 | 10001 | 4499 | 10 | 国产手机品牌 | 1 | 2019-04-18 13:56:19 |
3 | 小米手机 | 10002 | 3499 | 20 | 国产手机品牌 | 1 | 2019-04-18 14:04:56 |
4 | 一加手机 | 10003 | 3999 | 15 | 国产手机品牌 | 1 | 2019-04-18 14:06:02 |
现在我们来利用MyBatis实现查询商品列表:
- ProductMapper.mapper
……
<mapper namespace="com.xx.mapper.ProductMapper">
……
<!-- 查询所有信息不需要传参,返回的肯定是一个列表,
但是我们不需要指定resultType为list,只需要列表的数据类型就可以 -->
<select id="selectAllProduct" resultType="com.xx.entity.Product">
select * from t_product
</select>
</mapper>
- MyTest.class
@Test
public void testSelectAllProduct() throws IOException {
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
.build(Resources.getResourceAsReader("mybatis-config.xml"));
SqlSession session = sessionFactory.openSession();
// selecrList
// 返回类型是List<>类型
List<Product> list = session.selectList("com.xx.mapper.ProductMapper.selectAllProduct");
// 遍历输出一下
Iterator<Product> iterator = list.iterator();
while (iterator.hasNext()) {
Product product = (Product) iterator.next();
System.out.println(product);
}
session.commit();
session.close();
}
- 控制台
……
==> Preparing: select * from t_product
==> Parameters:
<== Columns: id, name, code, price, count, description, status, create_time
<== Row: 2, 华为手机, 10001, 4499, 10, 国产手机品牌, 1, 2019-04-18 13:56:19.0
<== Row: 3, 小米手机, 10002, 3499, 20, 国产手机品牌, 1, 2019-04-18 14:04:56.0
<== Row: 4, 一加手机, 10003, 3999, 15, 国产手机品牌, 1, 2019-04-18 14:06:02.0
<== Total: 3
Product [id=2, name=华为手机, code=10001, price=4499.0, count=10, description=国产手机品牌, status=1, create_time=Thu Apr 18 13:56:19 CST 2019]
Product [id=3, name=小米手机, code=10002, price=3499.0, count=20, description=国产手机品牌, status=1, create_time=Thu Apr 18 14:04:56 CST 2019]
Product [id=4, name=一加手机, code=10003, price=3999.0, count=15, description=国产手机品牌, status=1, create_time=Thu Apr 18 14:06:02 CST 2019]
……
新增商品返回主键
这里有必要介绍一个selectKey
标签:
selectKey在新增后返回主键值时使用,表示查询主键的值,绑定给某个列或者类的某个属性
keyProperty:新增后返回的主键值赋给类的哪个属性
order:取值为BEFORE或者AFTER,BEFORE表示在执行insert语句之前执行select,After表示在执行insert语句之后执行select
LAST_INSERT_ID()将查询到的结果绑定到keyProperty
- ProductMapper
……
<mapper namespace="com.xx.mapper.ProductMapper">
……
<insert id="insertProductReturnPK" parameterType="com.xx.entity.Product" >
<selectKey keyProperty="id" resultType="int" order="AFTER">
select LAST_INSERT_ID()
</selectKey>
insert into t_product values(
#{id},
#{name},
#{code},
#{price},
#{count},
#{description},
#{status},
#{create_time}
);
</insert>
</mapper>
- MyTest
@Test
public void testInsertProductReturnPK() throws IOException {
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
.build(Resources.getResourceAsReader("mybatis-config.xml"));
SqlSession session = sessionFactory.openSession();
Product product = new Product();
product.setName("vivo手机");
product.setCode("10006");
product.setPrice(4199.00);
product.setCount(10);
product.setDescription("国产手机品牌");
product.setStatus(1);
product.setCreate_time(new Date());
// 插入数据后返回主键pk
int pk = session.insert("com.xx.mapper.ProductMapper.insertProductReturnPK", product);
session.commit();
session.close();
}
- 控制台
……
==> Preparing: insert into t_product values( ?, ?, ?, ?, ?, ?, ?, ? );
==> Parameters: null, vivo手机(String), 10006(String), 4199.0(Double), 10(Integer), 国产手机品牌(String), 1(Integer), 2019-04-18 14:51:03.886(Timestamp)
<== Updates: 1
==> Preparing: select LAST_INSERT_ID()
==> Parameters:
<== Columns: LAST_INSERT_ID()
<== Row: 5
<== Total: 1
……
可见,新插入的这条数据的主键值是5。
以上,我们介绍了MyBatis的用途和特点,还编写了一个简单的小程序,接下来主要讲讲MyBatis的全局配置文件:
https://blog.csdn.net/qq_44238142/article/details/89380508
最后
以上就是朴实纸飞机为你收集整理的MyBatis(一)——MyBatis简介、MyBatis入门程序MyBatis简介MyBatis入门程序的全部内容,希望文章能够帮你解决MyBatis(一)——MyBatis简介、MyBatis入门程序MyBatis简介MyBatis入门程序所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复