zoukankan      html  css  js  c++  java
  • MyBatis入门

    1、MyBatis的介绍

      1. MyBatis 是一个支持普通SQL查询,存储过程和高级映射的优秀持久层(Dao)框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。

      2. MyBatis 消除了几乎所有的JDBC代码和手工设置参数以及结果集的检索。

      3. MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

      4. 一个MyBatis的应用程序都以一个SqlSessionFactory 对象(单例)的实例为核心;

        SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法。

      5. MyBatis是针对数据库交互的一个辅助框架,也是对jdbc做了的简单封装,以xml配置代替Java代码来管理数据库的交互细节!!

      注意:

        JPA 可以自动建表。

        MyBatis不能自动创建表,如果要建表,必须自己先准备好建表的sql语句。

     

    MyBatis三大核心对象
        1. SqlSessionFactoryBuilder
              目的是创建SqlSessionFactory  ,  用完就扔  , 写在方法内部 , 作为局部变量 , 建造者模式。
        2. SqlSessionFactory
              重量级对象 , 作用域整个应用  , 单例模式使用  , 有二级缓存。
        3. SqlSession
            轻量级的  ,  请求作用域,一个请求对应一个SqlSession对象 , 线程不安全的 , 有一级缓存。
        4. (扩展)Executor 数据库的操作都是调用的Executor接口的方法
                    update:增、删、改所用方法。
                    query:查询所用方法。

     

    MyBatis执行流程: 

      ①:我们需要核心文件(提供联系数据库的环境)

      ②:需要映射文件(提供ORM与运行的SQL语句)

      ③:拿到SqlSession对象,用于执行SQL

     

    2、MyBatis的入门使用

      注意:

        使用Mybatis的方式用两种,一种是xml配置的方式,一种是接口+注解的方式。

        这里主要是介绍xml配置方式。

     

      1.导入相应的jar包

        核心包:mybatis-3.2.1.jar

        数据库驱动包:mysql-connector-java-5.1.26-bin.jar

        依赖包:
               
    asm-3.3.1.jar
                cglib-2.2.2.jar
                commons-logging-1.1.1.jar
                javassist-3.17.1-GA.jar
                log4j-1.2.17.jar
                slf4j-api-1.7.2.jar
                slf4j-log4j12-1.7.2.jar

      2.准备相应的数据

        数据库-->新建数据库-->新建表-->插入测试数据

       3.准备domain实体类、dao和测试类

        注意:类的名称和类型都和我们的product表相对应匹配

      案例:

    domain实体类

    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;

      -----之后是get、set方法(略)
    }

     

    dao层接口

    public interface IProductDao {
        /**
         * 添加一个商品
         */
        void save(Product p);
        /**
         * 更新一个商品
         */
        void update(Product product);
        /**
         * 删除一个商品
         */
        void delete(Long id);
        /**
         * 查询一个商品
         */
        Product findOne(Long id);
        /**
         * 查询所有商品
         */
        List<Product> findAll();
    
    }

    dao层接口实现类 

      注:添加、修改、删除的时候一定要记住提交事务(配置事务、表结构支持事务)。

        JDBC的事务是自动提交的,而JPA、Hibernate、MyBatis事务都是需要手动提交的。

    package cn.wang.dao.daoImpl;
    
    import cn.wang.Utils.MyBatisUtils;
    import cn.wang.dao.IProductDao;
    import cn.wang.domain.Product;
    import org.apache.ibatis.session.SqlSession;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class ProductDaoImpl implements IProductDao {
    
        //抽取sql命名空间名字的值
        private final String NAMESPACE = "cn.wang.domain.ProductMapper.";
        //添加方法
        @Override
        public void save(Product p) {
            SqlSession sqlSession =null;
    
            try {
                //获取SqlSession对象(MyBatisUtils是为了方便专门抽取出来的工具类)
                sqlSession = MyBatisUtils.getSession();
                //第一个参数:sql命名空间名字的值+对应sql语句映射的id,第二个参数:传入的值
                sqlSession.insert(NAMESPACE+"insert",p);
                //提交事务
                sqlSession.commit();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //关闭sqlSession,释放资源(很重要,不然项目上线后会造成内存溢出)
                MyBatisUtils.colseSession(sqlSession);
            }
        }
    
        //修改方法
        @Override
        public void update(Product product) {
            SqlSession sqlSession = null;
            try {
                //获取SqlSession对象(MyBatisUtils是为了方便专门抽取出来的工具类)
                sqlSession = MyBatisUtils.getSession();
                //第一个参数:sql命名空间名字的值+对应sql语句映射的id,第二个参数:传入的值
                sqlSession.update(NAMESPACE+"update", product);
                //提交事务
                sqlSession.commit();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //关闭sqlSession,释放资源(很重要,不然项目上线后会造成内存溢出)
                MyBatisUtils.colseSession(sqlSession);
            }
        }
    
        //删除方法
        @Override
        public void delete(Long id) {
            SqlSession sqlSession=null;
    
            try {
                //获取SqlSession对象(MyBatisUtils是为了方便专门抽取出来的工具类)
                sqlSession = MyBatisUtils.getSession();
                //第一个参数是获取查询语句:sql命名空间名字的值+对应sql语句映射的id
                sqlSession.delete(NAMESPACE+"delete", id);
                //提交事务
                sqlSession.commit();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //关闭sqlSession,释放资源(很重要,不然项目上线后会造成内存溢出)
                MyBatisUtils.colseSession(sqlSession);
            }
        }
    
        //查询一条数据
        @Override
        public Product findOne(Long id) {
            SqlSession sqlSession = null;
            Product product= null;
            try {
                //获取SqlSession对象(MyBatisUtils是为了方便专门抽取出来的工具类)
                sqlSession = MyBatisUtils.getSession();
                //第一个参数是获取查询语句:sql命名空间名字的值+对应sql语句映射的id
                product = sqlSession.selectOne(NAMESPACE+"findOne", id);
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //关闭sqlSession,释放资源(很重要,不然项目上线后会造成内存溢出)
                MyBatisUtils.colseSession(sqlSession);
            }
            return product;
        }
    
        //查询所有数据
        @Override
        public List<Product> findAll() {
            SqlSession sqlSession=null;
            List<Product> list=new ArrayList<>();
    
            try {
                //获取SqlSession对象(MyBatisUtils是为了方便专门抽取出来的工具类)
                sqlSession = MyBatisUtils.getSession();
                //第一个参数是获取查询语句:sql命名空间名字的值+对应sql语句映射的id
                list=sqlSession.selectList(NAMESPACE+"findAll");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //关闭sqlSession,释放资源(很重要,不然项目上线后会造成内存溢出)
                MyBatisUtils.colseSession(sqlSession);
            }
            return list;
        }
    }

    抽取出来的MyBatisUtils工具

    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;
    
    public class MyBatisUtils {
        //保证sqlSessionFactory是单例
        private static SqlSessionFactory sqlSessionFactory;
    
        // SqlSessionFactory类似于JPA的EntityManagerFactory,Hibernate的SessionFactory
        // SqlSession 类似于JPA的EntityManager,Hibernate的Session
    
        //该类被加载的时候就执行该静态代码块
        static {
            try {
                Reader reader = Resources.getResourceAsReader("MyBatis-Config.xml");
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            } catch (Exception e) {//异常的类型要写大一些,才能够看到具体的报错
                e.printStackTrace();
            }
        }
        //提供一个外界调用的类
        public static SqlSession getSession(){
            //创建并返回SqlSession对象
            return sqlSessionFactory.openSession();
        }
        //关闭sqlSession,释放资源(很重要,不然项目上线后会造成内存溢出)
        public static void colseSession(SqlSession sqlSession){
            if(sqlSession !=null){
                sqlSession.close();
            }
        }
    }

    jdbc.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql:///数据库名称
    jdbc.username=用户名
    jdbc.password=密码

      3.MyBatis核心配置文件(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>
        <!-- environments:环境集合
            default:默认使用哪一个环境(必须对应一个环境的id)
         -->
    
        <!--引入外部的属性文件
            不写classpath的原因:resources默认到classpath中寻找资源
        -->
        <properties resource="jdbc.properties" />
    
        <!--
            配置自定义别名
            注意:别名不区分大小写。
               共两种配置方式:
                一:一个一个配置(typeAlias)
                        type 类型的完全限定名
                        alias 别名
                二:统一为某个包下的所有类起别名(package)
                        name : 包名   别名就是类名(不区分大小写)
        -->
        <typeAliases>
            <!--方法一-->
            <!--<typeAlias type="cn.wang.domain" alias="Product"/>-->
    
            <!--方法二-->
            <package name="cn.wang.domain"/>
        </typeAliases>
    
        <environments default="development">
            <!--
                environment:一个环境  id:为这个环境取唯一一个id名称
            -->
            <environment id="development">
                <!--
                    transactionManager:事务管理(共有两个值) type:JDBC(支持事务)/MANAGED(什么都不做)
                -->
                <transactionManager type="JDBC" />
                <!-- 数据源, 连接池  type(POOLED):MyBatis自带的连接池
                         type="UNPOOLED" 不使用连接池
                        type="POOLED" 使用连接池
                        type="JNDI" 容器中使用
                 -->
                <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代表的是相应的ORM映射文件 -->
        <mappers>
            <mapper resource="cn/wang/domain/ProductMapper.xml" />
        </mappers>
    
    </configuration>

      4.配置映射文件(命名方式:domain实体类名称+Mapper.xml

       注意:

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

    <?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.wang.domain.ProductMapper">
        <!--
            select : 这里面写查询语句
            id:sql语句的标识,在同一个namespace下不能重复
    
            parameterType : 传入的参数类型(原本应该用的是全限定名,这里用的是别名)  long:大Long  _long:小long (具体的对应请参见文档)
            resultType : 返回的结果类型(每一条数据返回的对象类型) 自己的对象一定是全限定类名(这里写的是别名)
         -->
        <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="insert" parameterType="product" keyProperty="id" useGeneratedKeys="true">
            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="long">
            UPDATE product set productName=#{productName} where id=#{id}
        </update>
    
        <delete id="delete" parameterType="long">
            delete FROM product where id=#{id}
        </delete>
    </mapper>

      5.最后进行测试

    public class MybatisTest {
        private IProductDao productDao=new ProductDaoImpl();
    
        @Test
        public void testFindOne(){
            Product product = productDao.findOne(1L);
            System.out.println(product);
        }
    
        @Test
        public void testFindAll(){
            List<Product> list = productDao.findAll();
            for (Product product : list) {
                System.out.println(product);
            }
        }
    
        @Test
        public void testInsert(){
            Product product = new Product();
            product.setProductName("大金刚");
            product.setDir_id(3L);
            product.setSalePrice(100.00);
            product.setSupplier("哈哈哈");
            product.setBrand("哇咔咔");
            product.setCutoff(0.66);
            product.setCostPrice(23.00);
    
            productDao.save(product);
            //获取新添加数据的主键,前提insert标签已经配置了那三个属性
            System.out.println(product.getId());
        }
    
        @Test
        public void testUpdate(){
           Product product = productDao.findOne(1L);
           product.setProductName("大罗金仙");
           productDao.update(product);
        }
        @Test
        public void testDelete(){
    
           productDao.delete(1L);
        }
    
    }

     

  • 相关阅读:
    从产品原型到交互设计的过渡——初学者心得
    谈什么是卡片式设计?
    vertical-align:middle的居中细节调整
    line-height:2和line-height:2em的区别,它们是有区别的
    css中!important的用法总结
    使用em为单位制作两列弹性布局
    如何动态修改下拉列表的默认选中项
    【转】深入浅出协议栈
    经典排序js实现
    js 数组的拷贝
  • 原文地址:https://www.cnblogs.com/wanghj-15/p/11182482.html
Copyright © 2011-2022 走看看