-
MyBatis是什么
MyBatis是一个ORM的数据库持久化框架:对象关系映射
很多人一看这个概念,一定会想:什么是ORM?什么叫数据库持久化?什么又叫框架?
MyBatis就是一个解决jdbc做数据库持久化非常麻烦问题的框架,该框架进行了sql方式映射模式orm,让我们在完成数据库持久化的时候更简单。
1.1.ORM是什么?
对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换 [1] 。从效果上说,它其实是创建了一个可在编程语言里使用的–“虚拟对象数据库”。
1.2.什么叫数据库持久化?
数据持久化就是将内存中的数据模型转换为存储模型。
常见的数据持久有:磁盘持久化和数据库持久化。
数据库持久化是数据持久化的其中一种,就是把内存中的数据保存到数据库中。
Java中最简单的就是使用jdbc来完成数据库持久化: -
MyBatis的jar包引入
-
domain的准备
private Long id;
//商品名称
private String productName;
//品牌
private String brand;
//供应商
private String supplier;
//零售价
private BigDecimal salePrice;
//进价
private BigDecimal costPrice;
//折扣
private Double cutoff;
//商品分类编号
private Long dir_id;
//下面提供get/set
domainMapper.xml (用来装domain对应的sql方法)
<?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的主要功能就是写sql
mapper:根
namespace:命令空间 (用来确定唯一) 以前这个是可以不加的,现在必需加
namespace的值,规则的:映射文件XxxMapper.xml所在的包+domain类名+Mapper
-->
<mapper namespace="cn.shuhan.mybatis.domain.ProductMapper">
<!--
select : 这里面写查询语句
id:用来确定这条sql语句的唯一
以后我们确定唯一,也就是找sql语句 : namespace +.+ id
例: cn.shuhan.mybatis.domain.ProductMapper.findOne
parameterType : 传入的参数类型 long:大Long _long:小long (具体的对应请参见文档)
resultType : 结果类型(第一条数据返回的对象类型) 自己的对象一定是全限定类名
-->
<!-- <select id="findOne" parameterType="long" resultType="cn.shuhan.mybatis.domain.Product">
select * from product where id = #{id}
</select>-->
<!--用了别名之后 使用别名-->
<!--ognl取值: # 和 $ 的区别
#是占位符 直接占位是一个?
$是拼接数据 会有sql注入问题
-->
<!--查询一个数据方法-->
<select id="findOne" parameterType="long" resultType="Product">
select * from product where id = #{id}
</select>
<!--查询所有数据方法-->
<select id="findAll" resultType="Product">
select * from product
</select>
<!--保存方法-->
<insert id="save" parameterType="Product">
insert into product (productName, dir_id, salePrice, supplier, brand, cutoff, costPrice)
values (#{productName}, #{dir_id}, #{salePrice}, #{supplier}, #{brand}, #{cutoff}, #{costPrice})
</insert>
<!--修改方法-->
<update id="update" parameterType="Product" >
update product set productName=#{productName}, dir_id=#{dir_id}, salePrice=#{salePrice},
supplier=#{supplier}, brand=#{brand}, cutoff=#{cutoff}, costPrice=#{costPrice}
</update>
<!--删除方法-->
<delete id="delete" parameterType="long">
delete from product where id =#{id}
</delete>
</mapper>
- 在resources文件夹中配置
- mybatis-config.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>
<!--
引入classpath下的db的配置文件
-->
<properties resource="db.properties">
</properties>
<!--给类型加上别名
要加在引入配置文件下 环境搭建上
type:原数据类型
alias:别名
要是不写alias 会默认是类的简单类名 首字母大小写都可以 建议大写 大写一看就知道是一个类
先配置别名再使用别名
-->
<typeAliases>
<!-- <typeAlias type="cn.shuhan.mybatis.domain.Product" alias="product"></typeAlias>-->
<typeAlias type="cn.shuhan.mybatis.domain.Product" ></typeAlias>
</typeAliases>
<!--
环境们:多个环境
development:开发
-->
<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>
<!--
引入写sql语句的mapper配置文件:
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
-->
<mapper resource="cn/shuhan/mybatis/domain/ProductMapper.xml"/>
</mappers>
</configuration>
6.db.properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///mybatis
jdbc.username=root
jdbc.password=root
7.log4j.properties配置 需要改的是log4j.logger.cn.shuhan=TRACE 路径改成自己需要生成日志的包路径
log4j.rootLogger=ERROR, stdout
#log4j.rootLogger=NONE
#trace:最详细日志
#debug:调试级别
#info:提示级别
#warnnig:警告级别
#error:错误级别
#级别最高,看到的日志最少:如果打的是TRACE:就可以看到TRACE和以上级别的日志
#如果是ERROR:就只能看到ERROR级别;
#开发测试的时候,日志最好详细点;上线的时候,日志少点,但是关键点:ERROR
#好处:System.out.println:最原始的使用调试信息:开发有很多信息,上线了不应该输出调试信息
#应该删除:很多,不好删;如果不删,会影响性能的.使用log4j:只需要修改日志级别就好了.
#cn.shuhan 是要生成日志的包
log4j.logger.cn.shuhan=TRACE
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
8.dao持久化层的impl实现
//创建log日志
private static final Logger log = LoggerFactory.getLogger(ProductDaoImpl.class);
@Override
public Product findOne(Long id) {
SqlSession sqlSession=null;
try {
//通过配置文件获得一个Reader
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//获取SqlSessionFactory 对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
//获取sqlSession
sqlSession = factory.openSession();
//调用sqlSession的api做事情
String sql = "cn.shuhan.mybatis.domain.ProductMapper.findOne";
//执行sql
return sqlSession.selectOne(sql,id);
} catch (IOException e) {
//用日志输出错误
log.error(e.getMessage());
e.printStackTrace();
return null;
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
9.这儿发现每个方法都要去拿一次sqlsession对象 而每次都去拿sqlsessionFactory对象性能很差 所以抽取一个util工具类
package cn.shuhan.mybatis.util;
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 java.io.IOException;
import java.io.Reader;
/**
* 抽取工具类
* 获取SqlSession对象来操作数据库
*/
public class MybatisUtil {
static SqlSessionFactory factory;
static {
try {
//通过配置文件获得一个Reader
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//获取SqlSessionFactory 对象
factory= new SqlSessionFactoryBuilder().build(reader);
} catch (IOException e) {
e.printStackTrace();
}
}
//提供获取sqlsession的公共方法
public static SqlSession getSqlSession(){
return factory.openSession();
}
}
10.使用了工具类之后的CURD代码如下
package cn.shuhan.mybatis.dao.impl;
import cn.shuhan.mybatis.dao.IProductDao;
import cn.shuhan.mybatis.domain.Product;
import cn.shuhan.mybatis.util.MybatisUtil;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
public class ProductDaoImpl implements IProductDao {
//创建log日志
private static final Logger log = LoggerFactory.getLogger(ProductDaoImpl.class);
//提出公共的sql语句部分 注意有一个点
private final String namespace = "cn.shuhan.mybatis.domain.ProductMapper.";
@Override
public Product findOne(Long id) {
SqlSession sqlSession=null;
try {
//通过配置文件获得一个Reader
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//获取SqlSessionFactory 对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
//获取sqlSession
sqlSession = factory.openSession();
//调用sqlSession的api做事情
String sql = "cn.shuhan.mybatis.domain.ProductMapper.findOne";
//执行sql
return sqlSession.selectOne(sql,id);
} catch (IOException e) {
//用日志输出错误
log.error(e.getMessage());
e.printStackTrace();
return null;
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
@Override
public void save(Product product) {
SqlSession sqlSession = null;
try {
//获取sqlsession对象
sqlSession = MybatisUtil.getSqlSession();
//调用方法 操作数据库
sqlSession.insert(namespace+"save", product);
//增删改都要提交事务
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭sqlsession
if (sqlSession != null) {
sqlSession.close();
}
}
}
@Override
public void del(Long id) {
SqlSession sqlSession = null;
try {
sqlSession = MybatisUtil.getSqlSession();
sqlSession.delete(namespace+"delete",id);
//增删改都要提交事务
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭sqlsession
if (sqlSession != null) {
sqlSession.close();
}
}
}
@Override
public void update(Product product) {
SqlSession sqlSession = null;
try {
sqlSession = MybatisUtil.getSqlSession();
sqlSession.update(namespace+"update",product );
//增删改都要提交事务
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭sqlsession
if (sqlSession != null) {
sqlSession.close();
}
}
}
@Override
public List<Product> findAll() {
log.debug("能不能打印一个");
log.info("能不能提示一个");
SqlSession sqlSession = null;
try {
sqlSession = MybatisUtil.getSqlSession();
return sqlSession.selectList(namespace+"findAll");
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
//关闭sqlsession
if (sqlSession != null) {
sqlSession.close();
}
}
}
}
11.接下来就是愉快的测试
package cn.shuhan.mybatis.test;
import cn.shuhan.mybatis.dao.IProductDao;
import cn.shuhan.mybatis.dao.impl.ProductDaoImpl;
import cn.shuhan.mybatis.domain.Product;
import org.junit.Test;
import java.math.BigDecimal;
public class ProductDaoImplTest {
private IProductDao productDao = new ProductDaoImpl();
@Test
public void findOne() throws Exception{
System.out.println(productDao.findOne(3L));
}
@Test
public void save() {
//准备数据
Product product = new Product();
product.setBrand("说什么");
product.setCostPrice(new BigDecimal(50));
product.setCutoff(0.8);
//执行
productDao.save(product);
}
@Test
public void del() {
System.out.println(productDao.findOne(1L));
productDao.del(1L);
System.out.println(productDao.findOne(1L));
}
@Test
public void update() {
//先查一个
Product product = productDao.findOne(2L);
System.out.println(product);
product.setCutoff(0.5);
product.setCostPrice(new BigDecimal(500));
product.setBrand("修改之后 单独");
productDao.update(product);
System.out.println(productDao.findOne(2L));;
}
@Test
public void findAll() {
System.out.println(productDao.findAll());
}
}
到这儿整个MyBatis的入门就算是ok了