MyBatis入门

Mybatis入门

MyBatis是一个ORM的数据库持久化框架。它以映射sql语句orm方式来数据库持久化操作。

一、导包

在这里插入图片描述

二、准备相应的表、domain、dao、测试

在这里插入图片描述

三、简单实现

3.1 步骤分析

①获取SqlSessionFactory
1 我们需要准备一个核心的Mybatis-config.xml文件
2 拿到SqlSessionFactory之前需要读取核心的xml配置文件
3 需要构造者(SqlSessionFactoryBuilder)来创建它
②映射文件准备
③通过SqlSessionFactory获取SqlSession执行映射SQL

3.2 核心文件

核心配置文件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>
    <!--引入jdbc.propeties文件-->
    <properties resource="jdbc.properties" />
    <!--配置包-->
    <typeAliases>
        <package name="cn.itsource.domain"></package>
        <package name="cn.itsource.query"></package>
    </typeAliases>
    <!-- 可以有多个环境,default:默认使用哪一个环境(必需对应一个环境的id) -->
    <environments default="development">
        <!-- 一个环境  id:为这个环境取唯一一个id名称 -->
        <environment id="development">
            <!-- 事务管理   type:JDBC(支持事务)/MANAGED(什么都不做) -->
            <transactionManager type="JDBC" />
            <!-- 数据源, 连接池  type(POOLED):MyBatis自带的连接池 -->
            <dataSource type="POOLED">
                <!-- 连接数据库的参数 -->
                <property name="driver" value="${jdbc.driverClassName}" />
                <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/itsource/domain/UserMapper.xml" />
    </mappers>
</configuration>

3.3 映射文件

①我们的映射文件(就是我们的mapper文件)一般情况下是和它对应的domain实体类在同一个层级
② 这个映射文件的名称一般叫做 XxxMapper.xml (Xxx代表的是实体类名称)
③ 除了MyBatis支持的类型,其它的类型都通通使用全限定

<?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.dao.IUserDao">
    <!--
        select : 这里面写查询语句
        id:用来确定这条sql语句的唯一
        parameterType : 传入的参数类型  long:大Long  _long:小long (具体的对应请参见文档)
        resultType : 结果类型(第一条数据返回的对象类型) 自己的对象一定是全限定类名
     -->
    <select id="queryAll" resultType="User">
        select * from t_user
    </select>
    <select id="queryOne" parameterType="long" resultType="User">
        select * from t_user where id=#{id}
    </select>
    <!--添加-->
    <insert id="save" parameterType="User">
        insert into t_user(name) values(#{name})
    </insert>
    <!--修改-->
    <update id="update" parameterType="User">
        update t_user set name=#{name} where id=#{id}
    </update>
    <!--删除-->
    <delete id="delete" parameterType="long">
        delete from t_user where id=#{id}
    </delete>
    <!--批量删除-->
    <delete id="deleteBatch" parameterType="list">
        delete from t_user where id in
        <foreach collection="list" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>
    <!--批量添加-->
    <insert id="saveBatch" parameterType="list">
        insert into t_user(name) VALUES
        <foreach collection="list" item="user" separator=",">
            (#{user.name})
        </foreach>
    </insert>
    <!--批量修改-->
    <update id="updateBatch" parameterType="list">
        UPDATE t_user SET name="1111" WHERE id IN
        <foreach collection="list" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </update>
    <!--高级查询-->

    <select id="queryList" parameterType="userQuery" resultType="User">
        select * from t_user
        <where>
            <if test="name!=null">
                and name like #{name}
            </if>
            <if test="age!=null">
                and age = #{age}
            </if>
        </where>
    </select>
</mapper>

3.4 实现

Dao层:

public interface IUserDao {
    //查询所有数据
    List<User> queryAll() throws IOException;
    //根据ID查数据
    User queryOne(Long id);
    //添加方法
    void save(User user);
    //修改方法
    void update(User user);
    //删除方法
    void delete(Long id);
    //批量删除
    void deleteBatch(List ids);
    //批量添加
    void saveBatch(List user);
    //批量修改
    void updateBatch(List ids);
    //高级查询
    List<User> queryList(UserQuery userQuery);
}

DaoImpl实现类:

public class UserDaoImpl implements IUserDao {
    @Override
    public List<User> queryAll() throws IOException {
        //1 创建SqlSessionFactory
        Reader reader = Resources.getResourceAsReader("MyBatis-Config.xml");
        //2 获取sqlSession做操作
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession sqlSession = sessionFactory.openSession();
        //3 表示调用那句sql
        List<User> users = sqlSession.selectList("cn.itsource.dao.IUserDao.queryAll");
        return users;
    }
    @Override
    public User queryOne(Long id) {
        User user = MyBatisUtil.INSTANCE.getSqlSession().selectOne("cn.itsource.dao.IUserDao.queryOne", id);
        return user;
    }
    @Override
    public void save(User user) {
        SqlSession sqlSession = MyBatisUtil.INSTANCE.getSqlSession();
        int insert = sqlSession.insert("cn.itsource.dao.IUserDao.save", user);
        sqlSession.commit();
    }
    @Override
    public void update(User user) {
        SqlSession sqlSession = MyBatisUtil.INSTANCE.getSqlSession();
        int insert = sqlSession.update("cn.itsource.dao.IUserDao.update", user);
        sqlSession.commit();
    }
    @Override
    public void delete(Long id) {
        SqlSession sqlSession = MyBatisUtil.INSTANCE.getSqlSession();
        int insert = sqlSession.delete("cn.itsource.dao.IUserDao.delete", id);
        sqlSession.commit();
    }
    //批量删除
    @Override
    public void deleteBatch(List ids) {
        SqlSession sqlSession = MyBatisUtil.INSTANCE.getSqlSession();
        int insert = sqlSession.delete("cn.itsource.dao.IUserDao.deleteBatch", ids);
        sqlSession.commit();
    }
    //批量添加
    public void saveBatch(List user){
        SqlSession sqlSession = MyBatisUtil.INSTANCE.getSqlSession();
        int insert = sqlSession.insert("cn.itsource.dao.IUserDao.saveBatch", user);
        sqlSession.commit();
    }
    @Override
    public void updateBatch(List ids) {
        SqlSession sqlSession = MyBatisUtil.INSTANCE.getSqlSession();
        int insert = sqlSession.update("cn.itsource.dao.IUserDao.updateBatch", ids);
        sqlSession.commit();
    }
    @Override
    public List<User> queryList(UserQuery userQuery) {
        SqlSession sqlSession = MyBatisUtil.INSTANCE.getSqlSession();
        List<User> users = sqlSession.selectList("cn.itsource.dao.IUserDao.queryList", userQuery);
        return users;
    }
}

Test测试类

public class mybatisTest {
    @Test
    public void testQueryAll() throws Exception{
        List<User> users = new UserDaoImpl().queryAll();
        users.forEach(e-> System.out.println(e));
    }
    @Test
	    public void testQueryOne() throws Exception{
        User user = new UserDaoImpl().queryOne(4L);
        System.out.println(user);
    }
    @Test
    public void testsave() throws Exception{
        User user = new User();
        user.setName("暗示大家哦");
        new UserDaoImpl().save(user);
    }
    @Test
    public void testUpdate() throws Exception{
        User user = new User();
        user.setId(2L);
        user.setName("我被改变了");
        new UserDaoImpl().update(user);
    }
    @Test
    public void testdelete() throws Exception{
        new UserDaoImpl().delete(3L);
    }
    //批量删除
    @Test
    public void testdeleteBatch() throws Exception{
        //用一个list来装我们要删除数据的id
        List<Long> ids = Arrays.asList(5L);
        new UserDaoImpl().deleteBatch(ids);
    }
    //批量添加
    @Test
    public void testSaveBatch() throws Exception{
        List<User> users = Arrays.asList(new User("飞机"),new User("大炮"),new User("火箭"));
        new UserDaoImpl().saveBatch(users);
    }
    //批量修改
    @Test
    public void testUpdateBatch() throws Exception{
        List<Long> ids = Arrays.asList(9L,10L,11L);
        new UserDaoImpl().updateBatch(ids);
    }
    //高级查询
    @Test
    public void testQueryList() throws Exception{
        UserQuery query = new UserQuery();
        //query.setName("%蔡徐坤%");
        query.setAge(100);
        List<User> users = new UserDaoImpl().queryList(query);
        users.forEach(e-> System.out.println(e));
    }
}

四、抽取Mybatis CRUD-工具类

4.1抽取理论

SqlSessionFactoryBuilder
建造者模式:我们最后拿到的这个对象是非常复杂的. 用这个建造者就它先为我们把这些复杂的代码完成. 这个类可以被实例化,使用和丢弃。一旦创建了SqlSessionFactory后,这个类对象就不需要存在了。因此SqlSessionFactoryBuilder实例的最佳范围是方法范围(也就是本地方法变量)。

SqlSessionFactory
一旦被创建,SqlSessionFactory应该在你的应用执行期间都存在。没有理由来处理或重新创建它。使用SqlSessionFactory的最佳实践是在应用运行期间不要重复创建多次。这样的操作将被视为是非常糟糕的。因此SqlSessionFactory的最佳范围是应用范围。有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。然而这两种方法都不认为是最佳实践。

SqlSession
每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能被共享,也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段甚至是实例字段中。也绝不能将SqlSession实例的引用放在任何类型的管理范围中,比如Serlvet架构中的HttpSession。如果你现在正用任意的Web框架,要考虑SqlSession放在一个和HTTP请求对象相似的范围内。换句话说,基于收到的HTTP请求,你可以打开了一个SqlSession,然后返回响应,就可以关闭它了。关闭Session很重要,

4.2 抽取

public enum MyBatisUtil {
    INSTANCE;
    private static SqlSessionFactory sessionFactory;
    static {
        Reader reader =null;
        try {
            reader = Resources.getResourceAsReader("MyBatis-Config.xml");
            sessionFactory = new SqlSessionFactoryBuilder().build(reader);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("配置文件出问题了"+e.getMessage());
        }
    }
    public SqlSession getSqlSession(){
        return sessionFactory.openSession();
    }
}

五、Mybtis使用细节

5.1 添加时拿到返回的主键

	<!-- 
		parameterType:需要传入我们的对象
		useGeneratedKeys: 是否需要主键 
		keyColumn:主键所在的列
		keyProperty:对象中的属性(代表主键的那个属性)
	 -->
	<insert id="save" 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>

5.2 查看MyBatis运行日志

在使用MyBatis的很多时候,我们需要把日志打印出来,帮助我们进行分析与排错.
要在项目中打开日志,大家在资源文件根目录下创建一个log4j.properties的文件,并把下面的代码拷备到里面。

# 日志输出级别 输出到控制
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
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

5.3 在MyBatis中别名

别名就是为类取得小名,以后可以使用小名代码真实名称,在Mybatis中,别名分为内置别名和自定义别名。

5.3.1 内置别名

在这里插入图片描述

5.3.2 自定义别名
<typeAliases>
	<!-- 单个配置:练习 -->
	<typeAlias type="cn.xxxx.mybatis.crud.User" alias="User" />
	<!-- 包的配置:项目,添加了包之后,类名就是别名 -->
	<package name="cn.xxxx.mybatis.crud" />
</typeAliases>

5.4 #与$区别

5.4.1 #{OGNL表达式}

MyBatis会把这个表达式使用?(占位符)替换,作为一个sql参数使用:推荐使用
比如:
定义SQL: select * from t_user where name = #{name}
最终SQL: select * from t_user where name = ?

5.4.2 ${OGNL表达式}

MyBatis会把这个表达式的值替换到sql中,作为sql的组成部分; 把获取到值直接拼接SQL,该方式主要用于程序拼接SQL;
比如:
定义SQL: select id,name,password from t_user where name = n a m e a n d p a s s w o r d = {name} and password= nameandpassword={password}
最终SQL: select id,name,password from t_user where name=“test” or “1=1” and password=“test” 出现sql注入
除了要拼接sql结构体要用$(是直接拼接sql),其他都用#,因为用#会替换为?,最终通过prepareStament来设置参数,不会有sql注入问提。

六、常用的动态SQL

MyBatis 的一个强大的特性之一通常是它的动态 SQL 能力。如果你有使用 JDBC 或其他相似框架的经验,你就明白条件地串联 SQL 字符串在一起是多么的痛苦,确保不能忘了空格或在列表的最后省略逗号。动态 SQL 可以彻底处理这种痛苦。
具体代码在上面已经体现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值