关于mybatis使用的几个小问题


最近学习web框架做了一些小项目,因为经验不足找bug浪费的时间还是很多的,下面我总结下我遇到的问题,让大家避免踩到同样的坑。
一.框架简述
想到哪写到哪吧。mybatis一共四个核心组件,SQLSessionFactoryBuilder,SqlSessionFactory,SqlSession,和SQL Mapper,我们最常使用的是后两个,对于获取到,SqlSession,如果不用sping整合,我建议写一个工具类,这样测试什么的都比较方便,下面是我写的工具类

public class MybatisUtil {
public static SqlSession getSession(){
//mybatis配置文件
    String resource = "sqlMapConfig.xml";
    InputStream inputStream = null;
    SqlSession sqlSession = null;
    try {
    //以流的方式读入
        inputStream = Resources.getResourceAsStream(resource);
        //构建factory,这里采取的是建造者模式
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //工厂类得到sqlsession
        sqlSession =  sqlSessionFactory.openSession();
    } catch (IOException e) {

        e.printStackTrace();
    }
    return sqlSession;
}

}
这就是固定的模式,所有获取sqlSession都是这么写的,当然,关于构建的过程,还是用到一些设计模式比较复杂的,今天先不说这个。对于mybatis的总配置文件,要注意,mybatis的configuration标签提供大量的可以自定义的配置方式,但是一般情况下用默认的就好,数据库的连接,和mapper这两个一定要自己配置的,如果忘了,会出错。

//数据库连接配置
 <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            //采用内部提供的连接池的方式
                <dataSource type="POOLED">
                    <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
                    <property name="url" value="jdbc:oracle:thin:@localhost:1521:LOVE"/>
                    <property name="username" value="scott"/>
                    <property name="password" value="tiger"/>                   
                </dataSource>
        </environment>
    </environments>
    //mapper包的导入
    <mappers>
        <package name="com.easy.Mapper"/>
    </mappers>

其他的还可以定义一些别名神马额特殊功能,如果有特殊需求,可以参照官方API。
二.一些细节问题
1.数据表名和类名对应,字段名和类的字段名最好相同
对于这个问题,我是强烈建议都写成一样的,其实,按道理来讲怎么写都行,但是当表字段等一多,放个比较复杂的查询,如果你不用mybatis提供的自动映射的方式,自己写mapper,那么我跟你说,这是极其浪费时间的,而且很容易出错。记得前几天我因为这个问题浪费了一晚上时间,所以尽量减少这种冗余的配置代码。
2.传递参数方式的选择
根据我的体会,如果不是基本数据类型,那么就采用javabean的方式,这样符合面向对象的思想,又可以通过这种方式传递多个参数。但是有一种情况

int deletePL(@Param("i") int[] ids);
<delete id="deletePL" parameterType>
        delete from book where id in
        <foreach collection="i" open="(" close=")" separator="," item="id">
            #{id}
        </foreach>
    </delete>

这个我做练习图书管理的批量删除部分代码,像这种要传递一个数组,就要用@Param注解了,因为mybatis没有提供数组类型的parameterType类型,但是用注解这种形式,就不用声明类型,Mybatis会自动扫描typeHandler,关于typehandler我之后再说。mybatis还提供了一种map方式传参的方式,本人不太喜欢。javabean的形式是推荐使用的。
3.model类的所有属性必须提供getter,setter方法
mybatis映射结果集,数据库中插入数据,就是调用的getter,setter方法,然后根据typehandler进行。
4.包名写全

<typeAliases>
    <package name="com.easy.model"/>
</typeAliases> 

在mybatis配置文件中插入这段代码,在写mapper时可以省略包名,但是我真的不建议这么做,有的时候回莫名奇妙的出现类型找不到的问题,那么在检查代码时,又要考虑是不是类所在的包路径不对?包名冲突?况且这样写,当类包变得多时,维护起来很麻烦。所以,包名写全。
5.sql要数量,在sqldeveloper调试好
因为sql是以字符串的形式存在的,如果在mybatis中测试,那么出错的可能性很大,而且这种问题找起来很浪费时间,所以建议在熟练使用sql的情况下,在数据库客户端调试好。

6.sql问题

<select id="selectAllBooks" resultType="com.easy.model.Book">
    select id,name,author,press,pressdate from(
     select rownum r,id,name,author,press,pressdate 
     from book ) 
    where r >=#{begin} and r &lt;=#{end} 
</select>

也是截取我项目中的一个例子,在XML中,’<’符号后被读成标签的结束符号,这里需要用XML提供的<代替<。
还有一个问题,Oracle数据库跟mysql数据库在sql上有一些区别,在做分页时,Oracle会稍微复杂一些,关于sql和分页的总结,我整理完,分享给大家。
7.级联问题
这个我要说的是,在实践前要把表的结构设计好,级联的数量不要抄过三级。如果级联的数量过多,配置会非常复杂,容易出错,而且性能也会变得非常低。
下面说几个标签

<association></association>:
取一个我项目中的部分:
 <resultMap type="com.easy.model.Book" id="c">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="author" property="author"/>
        <result column="press" property="press"/>
        <result column="pressdate" property="pressdate"/>
        <association property="store" javaType="com.easy.model.Store">
            <id column="store_id" property="store_id"/>
            <result column="name" property="name"/>
            <result column="address" property="address"/>   
        </association>
    </resultMap>

这个是配置级联的关键标签,这里我建议将要配置的属性都写出来,而用他提供的select标签,会引发N+1问题,我不喜欢用,用这种方式,看着也比较清晰

<collection></collection>这个是配置集合用的标签,注意元素类型用的是oftype

<disciminator></discriminator>mybatis提供的鉴别器,个人觉得挺好用

8.动态sql
mybatis相对于前几年流行的hibernate,提供强大的动态sql的功能。
8.1 where,if 标签:

<select id="selectAll" resultType="com.easy.model.Book" parameterType="com.easy.model.Book">
                select book_id,book_name,authorfrom book 
                    <where>
                        <if test="book_name != null and book_name != ''">
                             book_name like #{book_name}
                        </if>
                        <if test="author != null and author != ''">
                              and author like #{author}
                        </if>
                    </where> 


            </select>

这里举了个例子,这个标签是非常重要的,我建议尽量都写成动态sql的这种形式,我记得我开始因为没用动态sql进行判断,插入数据时一直报错,说javaType类型找不到,我废了好长时间,最后看底层原理最终才明白,实际上,每当插入数据时,mybatis会根据插入的数据自动找到合适的TypeHandler进行java类型和sql类型转换,而如果插入null,那么mybatis就会找不到对应的TypeHandler,那么当然报类型找不到的错啦,所以,为了防止这种事情发生,就用动态sql判断。另外,where这个标签还会自动的将第一个and去掉,非常方便。
8.2 自定义主键
selectKey标签:

 <insert id="add" parameterType="com.easy.model.Book">
        <selectKey order="BEFORE" keyProperty="book_id" >
            select seq_bookid.nextval from dual
        </selectKey>

            INSERT INTO BOOK(BOOK_ID,BOOK_NAME,AUTHOR,PUBLISHER) 
            VALUES(#{book_id},#{book_name},#{author},#{publisher})
    </insert>
这个标签用来处理自定义主键,要注意,在Oracle中,主键不默认自增,与mysql不同,他提供了序列这样一个对象,相信大家都很熟悉了。

8.3 foreach标签

<delete id="deletePL">
            delete from book where book_id in 
                <foreach collection="i" open="(" close=")" separator="," item="id">
                        #{id}
                </foreach>
        </delete>
这个就是用来遍历集合或数组的,上面已经介绍过了

9.日期处理
日期处理在开发中很常见,以前用Date类型转来转去很容易出错,我觉得这样处理比较好。

    <update id="update" parameterType="Book">
            update book set book_name=#{book_name},
            author=#{author},
            publisher=#{publisher},
            pubdate=to_date(#{pubdate},'yyyy-mm-dd')
            where book_id=#{book_id}
    </update>

如上所示,sql中提供了一个to_Date(,’yyyy-mm-dd’)函数,第一个参数是字符串类型,第二个参数是格式,可以自己指定。这个函数可以将字符串类型转换为Sql中的Date类型,我建议将所有的日期都写成String,然后用这个函数,sql中还提供了to_String()hans函数,但是我测试直接使用select也没出错,应该是自动转换成String类型。
持续更新…

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值