mybatis 的十分详细的入门教程

一. mybatis 的十分详细的入门教程

mybatis起源?

MyBatis 本是apache的一个开源项目iBatis,
2010年这个项目由apache software foundation 迁移到了google code,
并且改名为MyBatis
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。
iBATIS提供的持久层框架包括SQL Maps(XML映射配置)和Data Access Objects(Dao)

mybati介绍

MyBatis 是一个支持普通SQL查询,存储过程( Oracle最后一天)和高级映射的优秀持久层框架。
MyBatis 消除了几乎所有的JDBC代码和手工设置参数以及结果集的检索。
MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
MyBatis不能自动创建表,如果能够自动建表,必须自己先准备好建表的sql语句。

起步

步骤
1 导包
2 建表(product)
3 domain(Product)
4 准备dao层(CRUD)
5 测试(不是必需的)
注意:我们要引哪些包?
1 一定要引入驱动包(不要忘了)
2 导入mybatis的核心包
3 导入mybatis的依赖包

jar包可以去网上下载
导入jar包

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 resource="db.properties"></properties>

    <!--别名-->
    <typeAliases>
        <package name="cn.itsource.domain"></package>
    </typeAliases>

    <!--环境们--><!--默认环境-->
    <environments default="development">
        <!--环境-->
        <environment id="development">

            <transactionManager type="JDBC"></transactionManager>
            <!--
                dataSource:数据库,连接池(配置四大金刚:driven,url,username,password)
                    type:连接池的类型  UNPOOLED|POOLED|JNDI
                        UNPOOLED: 这个数据源的实现是每次被请求时简单打开和关闭连接
                        POOLED:这是 JDBC 连接对象的数据源连接池的实现
                        JNDI:这个数据源的实现是为了使用如 Spring 或应用服务器这类的容器
            -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>

            </dataSource>
        </environment>
    </environments>
<mappers>
    <!--在核心配置文件中找到咱们的SQL映射文件-->
    <mapper resource="cn/itsource/dao/Productmaper.xml"></mapper>
</mappers>
</configuration>

properties文件

jdbc.driver=com.mysql.jdbc.Driver #数据库驱动
jdbc.url=jdbc:mysql:///mybatis    #mybatis改为你的表名
jdbc.username=root    #数据库账号
jdbc.password=123456  #数据库密码
#四大金刚

核心文件中有一个mappers,它指向了一个映射文件。映射文件在哪?

,这个xml就是咱们需要的映射文件,它就可以体现出ORM,并且在这里面,也可以愉快的写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.itsource.mybatis.day1._1_hello.ProductMapper">
	<!-- 
		select : 这里面写查询语句
		id:用来确定这条sql语句的唯一
			   以后我们确定唯一,也就是找sql语句 : namespace +.+ id
			 例: cn.itsource.mybatis.day1._1_hello.ProductMapper.get
		parameterType : 传入的参数类型  long:大Long  _long:小long (具体的对应请参见文档)
		resultType : 结果类型(第一条数据返回的对象类型) 自己的对象一定是全限定类名
	 -->
	<select id="get" parameterType="long" resultType="cn.itsource.domain.Product">
		select * from product where id = #{id}
	</select>
</mapper> 

注意事项

我们的映射文件一般情况下是和它对应的domain实体类在同一个层级
② 这个映射文件的名称一般叫做 XxxMapper.xml (Xxx代表的是实体类名称)
③ namespace的名称为了确定唯一性,请大家根据我的要求取名
如我们有一个类:
cn.itsource.domain.Product / cn.itsource.domain.Student
那这里取名应该是:
cn.itsource.domain.ProductMapper /cn.itsource.domain.StudentMapper
④ 除了MyBatis支持的类型,其它的类型都通通使用全限定名

配置完后我们需要了解几个类
2 拿到SqlSessionFactory之前需要读取核心的xml配置文件
3 需要构造者(SqlSessionFactoryBuilder)来创建它

咱们说过,需要通过它去拿到一个SqlSession对象(相当于JDBC的连接)
必需要有SqlSession这个对象,我们才可以去执行相应的Sql

这里使用一个简单的类与数据库表来测试一下

在这里插入图片描述省略getset方法与tostring

在这里插入图片描述

<!--命名空间-->
<mapper namespace="cn.itsource.dao.Productmaper">

<!--查找所有-->
    <select id="findAll" resultType="Product">
            select * from product
    </select>


写一个工具类

public class MyBatisUtil {
    private static SqlSessionFactory factory;

    /**
     * 静态代码块加载对象
     */
    static {
        try {
            //读取配置文件
            Reader resourceAsReader = Resources.getResourceAsReader("mybatis-config.xml");
            //创建工厂
            factory = new SqlSessionFactoryBuilder().build(resourceAsReader);




        } catch (Exception e) {
            e.printStackTrace();
            System.err.println(e.getMessage()+"配置文件可能出错");
        }

    }

    /**
     * 获取sqlSession对象
     * @return
     */
    public static SqlSession getSqlSessionInstance(){
        return factory.openSession();
    }

}

测试类

@Test
   public void testutil2() throws Exception {
       SqlSession sqlSessionInstance = MyBatisUtil.getSqlSessionInstance();


       List<Product> list =  sqlSessionInstance
       		.selectList("cn.itsource.dao.Productmaper.findAll");
       System.out.println(list);

   }

测试无误
在这里插入图片描述`接下来写dao层crud

接口

package cn.itsource.dao;

import cn.itsource.domain.Product;

import java.util.List;

/**
* Product  CRUD
*/
public interface IProductDao {


   void delete(Long id);

   void update(Product product);

   void add(Product product);

   List<Product> findall();

   Product findOne(Long id);


}


实现类

package cn.itsource.dao.impl;

import cn.itsource.dao.IProductDao;
import cn.itsource.domain.Product;
import cn.itsource.utils.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;

import java.util.List;

/**
* CRUD  
*/
public class ProductDaoImpl implements IProductDao {
   public static final String NAMESPACE = "cn.itsource.dao.Productmaper.";

   @Override
   public void delete(Long id) {
       SqlSession session = MyBatisUtil.getSqlSessionInstance();
       try {
           session.delete(NAMESPACE + "delete", id);
           session.commit();
       } catch (Exception e) {
           session.rollback();
           e.printStackTrace();
       } finally {
           session.close();
       }
   }

   @Override
   public void update(Product product) {
       SqlSession session = MyBatisUtil.getSqlSessionInstance();
       try {
           session.update(NAMESPACE + "update", product);
           session.commit();
       } catch (Exception e) {
           session.rollback();
           e.printStackTrace();
       } finally {
           session.close();
       }
   }

   @Override
   public void add(Product product) {
       SqlSession session = MyBatisUtil.getSqlSessionInstance();
       try {
           session.insert("cn.itsource.dao.Productmaper.add", product);
           session.commit();
       } catch (Exception e) {
           session.rollback();
           e.printStackTrace();
       }finally {
           session.close();
       }
   }

   @Override
   public List<Product> findall() {
       try {
           return MyBatisUtil.getSqlSessionInstance().selectList("cn.itsource.dao.Productmaper.findAll");
       } catch (Exception e) {
           e.printStackTrace();
       }
       return null;
   }

   @Override
   public Product findOne(Long id) {
       try {
           return MyBatisUtil.getSqlSessionInstance().selectOne("cn.itsource.dao.Productmaper.findOne", id);
       } catch (Exception e) {
           e.printStackTrace();
       }
       return null;
   }
}

在配置文件中写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 namespace="cn.itsource.dao.Productmaper">

<!--查找一个-->
    <select id="findOne" parameterType="long" resultType="cn.itsource.domain.Product">
            select * from product where id = #{id}
    </select>
<!-- 查询所有 的sql  -->
    <select id="findAll" resultType="Product">
            select * from product
    </select>
<!-- 添加sql  -->
    <!--useGeneratedKeys="true" keyColumn="id" keyProperty="id" 添加后获取主键 -->
    <insert id="add" parameterType="cn.itsource.domain.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>
<!-- 删除sql  -->
    <delete id="delete" parameterType="long">
        delete from product where id = #{id}
    </delete>
<!-- 更新sql  -->
    <update id="update" parameterType="cn.itsource.domain.Product">
        update product
          set productName = #{productName},
             dir_id = #{dir_id},
             salePrice = #{salePrice},
             supplier = #{supplier},
             brand = #{brand},
             cutoff = #{cutoff},
             costPrice = #{costPrice}
        where id = #{id}
    </update>

</mapper>
 测试类
package cn.itsource.Test;

import cn.itsource.dao.IProductDao;
import cn.itsource.dao.impl.ProductDaoImpl;
import cn.itsource.domain.Product;
import cn.itsource.utils.MyBatisUtil;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.Reader;
import java.util.List;

public class MybatisimplTest {
    @Test
    public void test() throws Exception {
        IProductDao productDao = new ProductDaoImpl();
        List<Product> findall = productDao.findall();
        findall.forEach( v -> System.out.println(v));

    }

    @Test
    public void testfindone() throws Exception {
        IProductDao productDao = new ProductDaoImpl();
        Product one = productDao.findOne(1L);
        System.out.println(one);


    }
    @Test
    public void testadd() throws Exception {
        IProductDao productDao = new ProductDaoImpl();
        Product one1 = productDao.findOne(2L);
        one1.setId(null);
        productDao.add(one1);
        System.out.println(one1);
    }
    @Test
    public void testupdate() throws Exception {
        IProductDao productDao = new ProductDaoImpl();
        Product one1 = productDao.findOne(1L);
        one1.setProductName("张扬");
        productDao.update(one1);
    }
    @Test
    public void testdelete() throws Exception {
        IProductDao productDao = new ProductDaoImpl();
        productDao.delete(1L);

    }
}

crud注意事项

下面的点都很重要,是大家在使用MyBatis的时候经常出现的点。希望大家引起重视。出现问题的时候心态放平,不要狂躁,慢慢的找。基本咱们使用MyBatis中出的错都在这里。
使用框架的时候配置信息变多,在配置里写的都是字符串,而且经常是要对应的。因为,这里希望大家要切记:写的时候细心,出现错误找字符串要耐心,
1 主配置中未配置相应的mapper(当然,这个路径也可能写错)
2 在代码中调用Sql的时候路径写错
3 Sql写错,这个应该还好找
4 当我们在配置文件中很多地方如果写错,即便是你还没有使用也可能会报错
5 写Sql的标签不需要全部一致(如添加不一定必需使用insert),但是它的属性会不同
6 在传入与返回参数时全限定类名写错
在开发的时候,要边做边测试。 在某一步出现错误后,删除新加的代码看有没有问题,如果删除部分代码后运行成功,就相应的可以缩小排错的范围。

SqlSessionFactoryBuilder

建造者模式:我们最后拿到的这个对象是非常复杂的. 用这个建造者就它先为我们把这些复杂的代码完成.
这个类可以被实例化,使用和丢弃。一旦你创建了SqlSessionFactory后,这个SqlSessionFactoryBuilder类就不需要存在了。因此SqlSessionFactoryBuilder实例的最佳范围是方法范围(也就是本地方法变量)。
你可以重用SqlSessionFactoryBuilder来创建多个SqlSessionFactory实例,但是最好的方式是
不需要保持它一直存在来保证所有XML解析资源,因为还有更重要的事情要做。
总结来说就是用完可以随意丢弃且只用一次,

SqlSessionFactory(类似于jpa的EntityMangerFactory)

一旦被创建,SqlSessionFactory应该在你的应用执行期间都存在。没有理由来处理或重新创建它。使用SqlSessionFactory的最佳实践是在应用运行期间不要重复创建多次
** 是一个重量级对象 , 我们使用静态代码块单例模式**

SqlSession

每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能被共享,也是线程不安全的。因此最佳的范围是请求或方法范围。
绝对不能将SqlSession实例的引用放在一个类的静态字段甚至是实例字段中。
也绝不能将SqlSession实例的引用放在任何类型的管理范围中,比如Serlvet架构中的HttpSession。

如果你现在正用任意的Web框架,要考虑SqlSession放在一个和HTTP请求对象相似的范围内。换句话说,基于收到的HTTP请求,你可以打开了一个SqlSession,然后返回响应,就可以关闭它了。关闭Session很重要,

列名与属性名不对应的解决方案 resultMap

大家应该有注意到,前面咱们做映射文件的时候,只做了表与对象之间的联系。并没有做列与字段之间的联系。那么它们之间是怎么联系上的呢?
由于之前咱们的列名与属性名是一样的,因此框架进行了自动的识别。
那么:如果咱们的列名与属性名不一致了(对应不上),这时候应该怎么办呢?
这时候,就需要我们开发人员告诉MyBatis,我们需要把哪些列名与属性名对应上。

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值