MyBatis入门

1 mybatis基本认识

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
MyBatis 是一个支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。
MyBatis 消除了几乎所有的JDBC代码和手工设置参数以及结果集的检索

mybatis相较于jdbc的优点

把sql语句从java代码中抽取出来,方便维护。并且修改sql时不用修改java代码
不用手动设置参数和对结果集的处理-让我们操作数据库更加简单

2 初识mybatis

2.1 导包

mybatis核心包mybatis/mybatis-3.2.1.jar
mybatis的依赖包 mybatis/lib/*.jar
jdbc驱动包 mysql-connector-java-5.1.26-bin.jar

2.2 基础准备(数据库表,domain层)

创建数据库表product
创建domain类Product

public class Product {
    private Long id;
    //品牌名称
    private String productName;
    //成本价
    private double costPrice;
    //销售价
    private double salePrice;
    //供应商
    private String supplier;
    //品牌
    private String brand;
    //折扣
    private double cutoff;
    //品牌类型
    private Long dir_id;
    get()/set()方法
}

2.3 创建配置文件

2.3.1 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:配置(xml的根)-->
<configuration>
    <!--引入jdbc.properties文件-->
    <properties resource="jdbc.properties" />
    <!--
        environments:环境(多个环境)
        default:代表多个环境中 用的哪一个环境
    -->
    <environments default="development">
        <!--
            environment:某一个环境
            id:这个环境的名称
        -->
        <environment id="development">
            <!--
                transactionManager:事务管理
                type:类型
                type=”[JDBC|MANAGED]”)
                    JDBC:简单JDBC事物
                    MANAGED:啥都不做
            -->
            <transactionManager type="JDBC"/>
            <!--
                dataSource:数据源(连接池)
                POOLED:mybatis内置的连接池
           -->
            <dataSource type="POOLED">
                <!--
                    driver:驱动
                    driver:地址
                -->
                <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的xml-->
        <mapper resource="cn/itsource/dao/ProductMapper.xml"/>
    </mappers>
</configuration>
2.3.2 数据库的参数:jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///mybatis
jdbc.username=root
jdbc.password=123456
2.3.3 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:根(每个xml都得有,不用管它的含义)
    namespace:命名空间(随便取个名称)
-->
<mapper namespace="cn.itsource.dao.ProductMapper">
    <!--
        select:代表这是一个查询语句
            id:代表这个查询语句的唯一命名
                以后你要找到这条SQL: namespace+id
                例:cn.itsource.dao.ProductMapper.getOne
            parameterType:参数类型
                long -> Long  _long -> long
            resultType:返回的每一条结果的类型
                注:返回类型的全限定名
    -->
    <select id="getOne" parameterType="long" resultType="cn.itsource.domain.Product">
        select * from product where id = #{id}
    </select>
</mapper>

2.4 完成测试

  1. 搞到配置文件 mybatis-config.xml
  2. 拿到核心对象 SqlSession
  3. SqlSession就可以CRUD
public class MyBatisTest {
    /**
     * 1、搞到配置文件 mybatis-config.xml
     * 2、拿到核心对象 SqlSession
     * 3、SqlSession就可以CRUD
     */
    //查询单条数据
    @Test
    public void testHello()throws Exception{
        //1、搞到配置文件 mybatis-config.xml
        Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
        //2、获取 SqlSessionFactory 对象
        //SqlSessionFactoryBuilder --> SqlSessionFactory -> SqlSession
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(reader);
        //拿到核心对象 SqlSession
        SqlSession session = factory.openSession();

        //3、获取到一个对象
        Product product = session.selectOne("cn.itsource.dao.ProductMapper.getOne", 1L);
        System.out.println(product);

        //关闭session
        session.close();
    }
}

3 抽取工具类&CRUD

  1. SqlSessionFactoryBuilder:只用于创建factory,用完就可以扔掉
  2. SqlSessionFactory:重级量对象,创建后不要随便销毁(一个项目一个这个对象即可)
  3. SqlSession :用于完成咱们的CRUD

3.1 MyBatisUtil类

/**
 * MyBatis的工具类
 */
public class MyBatisUtil {
    //定义一个SqlSessionFactory对象
    private static SqlSessionFactory factory = null;

    static {
        try {
            factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("mybatis-config.xml"));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public static SqlSession openSession(){
        return factory.openSession();
    }
}

3.2 完成CRUD

3.2.1 productMapper.xml配置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">
<!--namespace:命名空间-->
<mapper namespace="cn.itsource.dao.ProductMapper">
    <!--
        select:代表这是一个查询语句
        id:代表这个查询语句的唯一命名
            (以后要找到这条sql:通过namespace + id)
            例:cn.itsource.dao.ProductMapper.getOne
        parameterType:参数类型
             long -> Long   _long -> long
        resultType:返回的每一条结果的类型
            注:返回类型的全限定名
    -->
    <select id="getOne" parameterType="long" resultType="product">
        select *
        from product
        where id = #{id}
    </select>
    <!--
        #和$的区别:
            获取值的区别
                $: 拿到的是传过来的对象的某一个属性
                #:既可以单独那对象,还可以拿传过来的对象的某一个属性
            对SQL的影响
                #是预编译的方案(防sql注入,安全性更高,性能也会更强一些)
            结论:
                能使用#就使用#(优先使用#)
    -->
    <select id="queryOne" parameterType="productQuery" resultType="product">
        select *
        from product
        where id = ${id}
    </select>

    <select id="getAll" resultType="product">
        select *
        from product
    </select>

    <delete id="delete" parameterType="long">
        delete
        from product
        where id = #{id}
    </delete>

    <!--
        useGeneratedKeys="true"  是否要主键
        keyColumn="id"  在数据库中叫什么名字
        keyProperty="id" 在类中叫什么名字
    -->
    <insert id="save" parameterType="product" useGeneratedKeys="true" keyColumn="id"
            keyProperty="id">
        insert into product (productName, costPrice, salePrice, supplier, brand, cutoff, dir_id) VALUE (#{productName},
                                                                                                        #{costPrice},
                                                                                                        #{salePrice},
                                                                                                        #{supplier},
                                                                                                        #{brand},
                                                                                                        #{cutoff},
                                                                                                        #{dir_id})
    </insert>

    <update id="update" parameterType="product">
        update product
        set productName=#{productName},
            costPrice=#{costPrice},
            salePrice=#{salePrice},
            supplier=#{supplier},
            brand=#{brand},
            cutoff=#{cutoff},
            dir_id=#{dir_id}
        where id = #{id}
    </update>
</mapper>
3.2.2 ProductDaoImpl实现层完成相应功能
package cn.itsource.dao.impl;
import cn.itsource.dao.IProductDao;
import cn.itsource.domain.Product;
import cn.itsource.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import java.util.List;

public class ProductDaoImpl implements IProductDao {
    private final String NAMESOACE = "cn.itsource.dao.ProductMapper.";

    //添加
    @Override
    public void save(Product product) {
        SqlSession session = null;
        try {
            session = MyBatisUtil.openSession();
            session.insert(NAMESOACE+"save",product);
            //提交事物
            session.commit();
        }catch (Exception e){
            //回滚事物
            session.rollback();
            e.printStackTrace();
        }finally {
            session.close();
        }
    }

    //修改
    @Override
    public void update(Product product) {
        SqlSession session = null;
        try {
            session = MyBatisUtil.openSession();
            session.update(NAMESOACE+"update",product);
            //提交事物
            session.commit();
        }catch (Exception e){
            //回滚事物
            session.rollback();
            e.printStackTrace();
        }finally {
            session.close();
        }
    }

    //删除
    @Override
    public void delete(Long id) {
        SqlSession session = null;
        try {
            session = MyBatisUtil.openSession();
            session.delete(NAMESOACE+"delete",id);
            //提交事物
            session.commit();
        }catch (Exception e){
            //回滚事物
            session.rollback();
            e.printStackTrace();
        }finally {
            session.close();
        }
    }

    //查询单条数据
    @Override
    public Product findOne(Long id) {
        SqlSession session = null;
        try {
            session = MyBatisUtil.openSession();
            return session.selectOne(NAMESOACE+"getOne", id);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            session.close();
        }
        return null;
    }

    //查询所有数据
    @Override
    public List<Product> findAll() {
        SqlSession session = null;
        try {
            session = MyBatisUtil.openSession();
            return session.selectList(NAMESOACE+"getAll");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            session.close();
        }
        return null;
    }
}

4 mybatis细节

4.1 添加的对象的时候返回id

<!--
        useGeneratedKeys="true"  是否要主键
        keyColumn="id"  在数据库中叫什么名字
        keyProperty="id" 在类中叫什么名字
    -->
<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>

4.2 自定义别名配置

  1. 内置别名(int,long,…)/自定义别名(自己的类)
  2. 别名不区分大小写
  3. 自定义别名的配置
  4. 每个对象单独配置别名 <typeAlias type="cn.itsource.domain.Product" alias="Product" />
  5. 扫描包(这个包的对象都会取别名) <package name="cn.itsource.domain" />
<!--
       定义别名
       typeAliases:配置别名
       type:类型
       alias:别名
   -->
<typeAliases>
    <!--<typeAlias type="cn.itsource.domain.Product" alias="product" />-->
    <!--为这个包下面所有的类都取别名-->
    <package name="cn.itsource.domain" />
    <package name="cn.itsource.query" />
</typeAliases>

4.3 日志的处理

在资源根目录创建一个log4j.properties

# ERROR错误的日志 WARN:警告 INFO:普通信息  DEBUG:调试日志  TRACE:日志
log4j.rootLogger=ERROR, stdout
#log4j.rootLogger=NONE
#把左边包名改成你自己的包名
log4j.logger.cn.itsource=TRACE
# 日志打印到控制台中
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
# 日志打印的一种格式(可以灵活地指定布局模式)
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# 日志打印的格式是什么样子的  %d:日期 %p:优先级 %c:类的全名  %m:输出的结果 %n:换行
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

4.4 #与$的区别

#和$的区别:
获取值的区别
$: 拿到的是传过来的对象的某一个属性
#:既可以单独那对象,还可以拿传过来的对象的某一个属性
对SQL的影响
#是预编译的方案(防sql注入,安全性更高,性能也会更强一些)
结论:
能使用#就使用#(优先使用#)

5 批量操作&动态修改

5.1 批量添加

sql: insert into 表名 (列名,列名) values (?,?),(?,?),...
xml配置

<!--
    foreach:循环
     collection:遍历的集合
     item:每次遍历拿到的对象
     separator:分隔符(每个值都使用,隔开)
-->
<insert id="batchSave" parameterType="list">
    insert into employee (name, age, sex) values
    <foreach collection="list" item="e" separator=",">
        (#{e.name}, #{e.age}, #{e.sex})
    </foreach>
</insert>

代码实现

//批量添加
@Test
public void testBatchSave()throws Exception{
    List<Employee> list = new ArrayList<>();
    for (int i = 1; i <= 20 ; i++) {
        Employee employee = new Employee();
        employee.setName("皮皮虾"+i);
        employee.setAge(18+i);
        employee.setSex(true);
        list.add(employee);
    }
    SqlSession session = MyBatisUtil.openSession();
    session.insert("cn.itsource.dao.EmployeeMapper.batchSave",list);
    session.commit();
    session.close();
}

5.2 批量删除

xml配置

<!--
     foreach:循环
     collection:遍历的集合
     item:每次遍历拿到的对象
     separator:分隔符(每个值都使用,隔开)
     open:以什么开头
     close:以什么结尾
     index:遍历的索引
-->
<delete id="batchDelete" parameterType="list">
    delete from employee where id in
    <foreach collection="list" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
</delete>

代码实现

//批量删除
@Test
public void testBatchDelete()throws Exception{
    List<Long> ids = Arrays.asList(12L,14L);
    SqlSession session = MyBatisUtil.openSession();
    session.delete("cn.itsource.dao.EmployeeMapper.batchDelete",ids);
    session.commit();
    session.close();
}

5.3 动态修改

  1. 解决以前数据丢失问题
  2. 对象中没有值就不做修改
    xml配置
<!--动态修改 只改有值的数据-->
<update id="dynamicUpdate" parameterType="employee">
    update employee
    <set>
        <if test="name !=null">
            name=#{name},
        </if>
        <if test="age !=null">
            age=#{age},
        </if>
        <if test="sex !=null">
            sex=#{sex},
        </if>
    </set>
    where id = #{id}
</update>

代码实现

//动态修改
@Test
public void testDynamicUpdate()throws Exception{
    Employee employee = new Employee();
    employee.setId(5L);
    employee.setName("皮皮怪啊啊啊啊啊");
    employee.setSex(false);
    SqlSession session = MyBatisUtil.openSession();
    session.delete("cn.itsource.dao.EmployeeMapper.dynamicUpdate",employee);
    session.commit();
    session.close();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值