MyBatis简单CURD
回顾ORM的一些知识
对象关系映射的框架
对象:java domain对象 比如User Person Animal
new User
映射:数据表 一行记录
关系:表和表之间的关系 就是对象和对象关系
ORM的实现
Hibernate 早期版本 大量的配置
JPA 注解
SpringDataJPA
MyBatis也是ORM实现框架 – 主要做持久化
JDBC有优缺点
缺点:
编写比较麻烦
重复性太高
很多sql都需要写到代码,sql和代码耦合度比较高
queryAll 封装操作
没有性能控制 --缓存
优点:
操作数据库最底层
自己可以灵活操作sql
JPA的优缺点
你怎么懂的Sql 都可以操作数据库,JPA提供缓存控制(ehcache)
有些性能不好控制,比如find 默认查询所有列
MyBatis学习
Mybatis就是ORM一种实现的框架
MyBatis完成持久层框架
可以灵活的操作sql
有缓存支持
不用封装数据,避免jdbc重复性代码
Struts2SpringHibernate – SSH
SpringMVCSpringSpringJdbc
SpringMVCSpringSpringDataJPA
SpringMVCSpringMyBatis --目前而言比较流行结构
SpringBoot SpringCloud SpringMVC Spring MyBatis
MyBatis第一个入门程序
a.导入相应jar包到项目
以前导包方式
b.配置 MyBatis-Config.xml
配置环境 (连接数据库四大配置dirver url username password)
配置Mapper文件–主要写Sql文件(insert update delete select)
在主MyBatis-Config.xml里面去引用Mapper
c.写个测试类测试代码
SqlSessionFactoryBuilder- SqlSessionFactory–SqlSession
domain
package cn.itsource.myBatis.domain;
/**
* @author lee
* @create 2019-03-07-12:43
*/
public class Product {
private Long id;
//商品名称
private String productName;
//品牌
private String brand;
//供应商
private String supplier;
//零售价
private Double salePrice;
//进价
private Double costPrice;
//折扣比例
private Double cutoff;
//商品分类编号
private Long dir_id;
public Product() {
}
public Product(Long id, String productName, String brand, String supplier, Double salePrice, Double costPrice, Double cutoff, Long dir_id) {
this.id = id;
this.productName = productName;
this.brand = brand;
this.supplier = supplier;
this.salePrice = salePrice;
this.costPrice = costPrice;
this.cutoff = cutoff;
this.dir_id = dir_id;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getSupplier() {
return supplier;
}
public void setSupplier(String supplier) {
this.supplier = supplier;
}
public Double getSalePrice() {
return salePrice;
}
public void setSalePrice(Double salePrice) {
this.salePrice = salePrice;
}
public Double getCostPrice() {
return costPrice;
}
public void setCostPrice(Double costPrice) {
this.costPrice = costPrice;
}
public Double getCutoff() {
return cutoff;
}
public void setCutoff(Double cutoff) {
this.cutoff = cutoff;
}
public Long getDir_id() {
return dir_id;
}
public void setDir_id(Long dir_id) {
this.dir_id = dir_id;
}
@Override
public String toString() {
return "Product{" +
"id=" + id +
", productName='" + productName + '\'' +
", brand='" + brand + '\'' +
", supplier='" + supplier + '\'' +
", salePrice=" + salePrice +
", costPrice=" + costPrice +
", cutoff=" + cutoff +
", dir_id=" + dir_id +
'}';
}
}
dao/impl
package cn.itsource.myBatis.dao.impl;
import cn.itsource.myBatis.dao.IProductDao;
import cn.itsource.myBatis.domain.Product;
import cn.itsource.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 java.io.Reader;
import java.util.List;
/**
* @author lee
* @create 2019-03-07-12:49
*/
public class ProductDaoImpl implements IProductDao {
public static String NAMESPACE = "cn.itsource.myBatis.domain.ProductMapper.";
@Override
public void save(Product p) {
SqlSession sqlSession = MybatisUtil.getSqlSession();
sqlSession.insert(NAMESPACE + "save", p);
MybatisUtil.closeSession(sqlSession);
}
@Override
public void update(Product p) {
SqlSession sqlSession = MybatisUtil.getSqlSession();
sqlSession.update(NAMESPACE + "update", p);
//提交事务
sqlSession.commit();
MybatisUtil.closeSession(sqlSession);
}
@Override
public void delete(Long id) {
SqlSession sqlSession = MybatisUtil.getSqlSession();
sqlSession.delete(NAMESPACE + "delete", id);
MybatisUtil.closeSession(sqlSession);
}
@Override
public Product getOne(Long id) throws Exception {
SqlSession sqlSession = MybatisUtil.getSqlSession();
Product product = ((Product) sqlSession.selectOne(NAMESPACE + "getOne", id));
MybatisUtil.closeSession(sqlSession);
return product;
}
@Override
public List<Product> getAll() throws Exception {
//得到Reader
Reader reader = Resources.getResourceAsReader("MyBatis-Config.xml");
//得到SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
//得到sqlsession
SqlSession sqlSession = sqlSessionFactory.openSession();
//完成操作
List<Product> list = sqlSession.selectList(NAMESPACE + "getAll");
sqlSession.close();
reader.close();
return list;
}
@Override
public Product findProductByName(String name) throws Exception {
SqlSession sqlSession = MybatisUtil.getSqlSession();
Product product = ((Product) sqlSession.selectOne(NAMESPACE + "findProductByName", name));
MybatisUtil.closeSession(sqlSession);
return product;
}
}
使用 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>
<!-- 引入Properties文件 -->
<properties resource="db.properties"></properties>
<!-- 别名设置-->
<typeAliases>
<typeAlias type="cn.itsource.myBatis.domain.Product" alias="product"></typeAlias>
</typeAliases>
<!-- 环境配置 数据库四大配置 dirver url username password-->
<environments default="development">
<environment id="development">
<!-- 事务-->
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<!-- 根据key拿到properties中的value值 -->
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<!-- 引用mapper文件 -->
<mappers>
<mapper resource="cn/itsource/myBatis/domain/ProductMapper.xml"/>
</mappers>
</configuration>
使用MyBatis完成CRUD
<?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.itsource.myBatis.domain.ProductMapper">
<!--
select : 这里面写查询语句
id:用来确定这条sql语句的唯一
以后我们确定唯一,也就是找sql语句 : namespace +.+ id
例: cn.itsource.mybatis.day1._1_hello.ProductMapper.get
parameterType : 传入的参数类型 long:大Long _long:小long (具体的对应请参见文档)
resultType : 结果类型(第一条数据返回的对象类型) 自己的对象一定是全限定类名
-->
<!--查询所有-->
<select id="getAll" parameterType="long" resultType="cn.itsource.myBatis.domain.Product">
select * from product
</select>
<!--根据id查询一个-->
<select id="getOne" parameterType="long" resultType="product" >
select * from product WHERE id=#{id}
</select>
<!--添加-->
<insert id="save" parameterType="product" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
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}
WHERE id=#{id}
</update>
<!--删除数据-->
<delete id="delete" parameterType="long">
DELETE FROM product WHERE id=#{id}
</delete>
<!--根据产品名字查询-->
<select id="findProductByName" parameterType="string" resultType="product">
SELECT * FROM product WHERE productName=#{productName}
</select>
</mapper>
配置MybatisUtil
package cn.itsource.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;
/**
* @author lee
* @create 2019-03-07-14:53
*/
public class MybatisUtil {
private static SqlSessionFactory sqlSessionFactory = null;
static {
Reader reader = null;
try {
//得到Reader
reader = Resources.getResourceAsReader("MyBatis-Config.xml");
//得到sqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("解析配置文件出问题:" + e.getMessage());
}
}
/**
* 得到SqlSession
*
* @return
*/
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
/**
* 关流
* @param sqlSession
*/
public static void closeSession(SqlSession sqlSession) {
if (sqlSession != null) {
sqlSession.close();
}
}
}
测试
package cn.itsource.myBatis.test;
import cn.itsource.myBatis.dao.IProductDao;
import cn.itsource.myBatis.dao.impl.ProductDaoImpl;
import cn.itsource.myBatis.domain.Product;
import org.junit.Test;
import java.util.List;
/**
* @author lee
* @create 2019-03-07-12:59
*/
public class ProductTest {
IProductDao dao = new ProductDaoImpl();
@Test
public void testFindAll() throws Exception{
List<Product> productList = dao.getAll();
productList.forEach(product -> {
System.out.println(product);
});
}
@Test
public void testFindOne()throws Exception{
Product product = dao.getOne(1L);
System.out.println(product);
}
@Test
public void testSave()throws Exception{
Product product = new Product();
product.setProductName("断了的弦");
product.setBrand("藤原豆腐店");
product.setCostPrice(999.99);
product.setCutoff(0.5);
product.setDir_id(2L);
product.setSalePrice(999.99);
product.setSupplier("JAY");
dao.save(product);
System.out.println(product);
}
@Test
public void testUpdate (){
Product product = new Product();
product.setId(23L);
product.setProductName("AE86");
product.setBrand("乔克叔叔");
product.setCostPrice(999.99);
product.setCutoff(0.5);
product.setDir_id(2L);
product.setSalePrice(999.99);
product.setSupplier("漂移");
dao.update(product);
}
@Test
public void testDelete(){
dao.delete(26L);
}
@Test
public void testFindProductByName()throws Exception{
Product ae86 = dao.findProductByName("一路向北");
System.out.println(ae86);
}
}
使用注意事项
A错误:
Error querying database. Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for cn.itsource._01_hello.ProductMapper.getOne
情况一:主的配置文件里面 没有去引用mapper
情况二:还有配置文件 方法写错
错误:
The error may exist in cn.itsource.myBatis/ProductMapper.xml
正确写法:
类的全限定名不要写错
MyBatis核心对象
JPA :EntityMangerFactory EntityManager
MyBatis: SqlSessionFactory SqlSession
SqlSessionFactoryBuilder sqlSessionFactory创建者
用来创建SqlSessionFactory,一般这个对象创建出来之后,就不怎么会用到,一般只需要方法里面
SqlSessionFactory这个对象:
SqlSessionFactory 用来得到SqlSession
需不需要频发创建--不需要频繁创建,重量级的对象,和数据库关联,如果频繁创建开销很大,一般放大静态代码代码,让其他共享. 尽量保证一个单例模式, SqlSessionFactory交给Spring管理
SqlSession对象
SqlSession线程不安全的,一般不用去共享,在方法里面是使用的创建.创建不需要开销很大,可以频繁创建,不要作为静态字段,让别人共享,每次操作 ,每次去获取对象
别名设置
现在mapper文件里面 有很多全限定名。如果每次写一个方法,都去写全限定名比较麻烦
<!-- 别名设置-->
<typeAliases>
<typeAlias type="cn.itsource._01_hello.Product" alias="product"></typeAlias>
</typeAliases>
(10)列名和对象属性名不对应情况
<resultMap id="productMap" type="product">
<!--property 是对象里面属性 column 列-->
<id property="id" column="id"></id>
<!-- 数据库列和对象列名属性没有对应上面 作了映射处理-->
<result column="productName" property="name"></result>
<result column="supplier" property="supplier"></result>
</resultMap>
<!-- 查询所有数据-->
<select id="getAll" resultMap="productMap" >
select * from product
</select>