MyBatisCRUD的优化上

前几天我们讲了CRUD的全部测试,下面是对CRUD示例的优化:
    1,typeAliases:在示例中的UserMapper.xml文件中可以看到,凡是使用到User类型的时候,都需要写User的类的全限定名。在mybatis-config.xml中,可以使用typeAliases元素来简化这个操作:
    在mybatis-config.xml中添加:
    <typeAliases>
        <typeAlias type="cd.itcast.mybatis.domain.User" alias="User"/>
    </typeAliases>
    即为cd.itcast.mybatis.domain.User起了一个简化的名字:User,那么之后在Mapper文件中使用User就可以代替cd.itcast.mybatis.domain.User,想想hibernate的import。
    修改的UserMapper.xml文件如下:
    <mapper namespace="cd.itcast.mybatis.domain.UserMapper">
        <insert id="save" keyProperty="id" parameterType="User" useGeneratedKeys="true">
            INSERT INTO user(name,hiredate) values (#{name},#{hireDate})
        </insert>

<update id="update" parameterType="User">
            UPDATE user SET name = #{name},hiredate = #{hireDate} WHERE id = #{id}
        </update>

<delete id="delete" parameterType="int">
            DELETE FROM user WHERE id = #{id}
        </delete>

<select id="get" parameterType="int" resultType="User">
            SELECT * FROM user WHERE id = #{id}
        </select>

<select id="list" resultType="User">
            SELECT * FROM user
        </select>
    </mapper>
    简化不少。

2, properties:我们说过数据库的连接信息一般要放到一个额外的.properties文件中,mybatis允许我们这样做。
    首先,修改mybatis-config.xml文件:
    <environments default="default">
        <environment id="default">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${driverClass}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    联想spring的dataSource配置方式,不难理解。
    占位符的数据来源配置有三种方式:
    第一种使用方式:在SqlSessionFactoryBuilder的build方法中,还提供了额外传入Properties对象的方法:
    public SqlSessionFactory build(InputStream inputStream, Properties properties)
    这个方法后面的Properties对象就可以做为mybatis-config.xml中的参数来源。所以,我们可以这样来使用:
    Properties p=new Properties();
    p.load(this.getClass().getClassLoader().getResourceAsStream(“db.properties”);
    并在classpath下定义一个db.properties文件:
    driverClass=com.mysql.jdbc.Driver
    url=jdbc:mysql:///hibernate
    username=root
    password=admin

第二种使用方式:在mybatis-config.xml中有properties这样一个标签,那么我们可以在mybatis-config.xml中定义:
    <properties>
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///hibernate"/>
        <property name="username" value="root"/>
        <property name="password" value="admin"/>
    </properties>
    即可。

第三种方式:在mybatis-config.xml中的properties元素中,引入外部的properties文件:
    <properties resource="db.properties" />
    并在classpath中添加db.properties文件即可。
    第三种方式和第二种方式可以混用,即:
    <properties resource="org/mybatis/example/config.properties">
          <property name="username" value="dev_user"/>
          <property name="password" value="F2Fa3!33TYyg"/>
    </properties>

三者的优先级为:代码传入的Properties > resource加载的Properties > properties元素中定义的property。

3,MyBatisUtil的抽象:
在mybatis中,SqlSessionFactory和SqlSession的作用和地位极其类似SessionFactory和Session,包括其线程安全性。即
SqlSessionFactory是线程安全的,在整个应用中对应一个数据源只需要创建一个。
SqlSession是线程不安全的,生命周期最好是method或者线程。
所以,我们就能抽象一个MyBatisUtil来提供SqlSession的创建:
public class MyBatisUtil {
    private static SqlSessionFactory factory;

static {
        try {
            factory = new SqlSessionFactoryBuilder().build(Resources
            .getResourceAsStream("mybatis-config.xml"));
        } catch (Exception e) {
            e.printStackTrace();
            }
        }

public static SqlSession openSession() {
    return factory.openSession();
    }
}

4,Mapper接口的实现
在上面的测试用例中,在调用session的方法的时候,都会传入要调用的SQL的namespace+id名称,这不是必须的。可以只传入id即可。但
是,如果在mybatis的环境中有多个相同id的映射名称,就会报错。所以,一般情况下,调用方法最好还是使用namespace+id。但
是,namespace+id的使用方式很容易报错,因为是string类型的,没有检查。所以,mybatis提供了一种非常好的设计方式来避免这种问
题,即Mapper接口。
对照UserMapper.xml的定义,我们只需要创建一个接口,注意,接口的名字和包必须和mapper.xml定义的namespace一致,即创建一个接口:cd.itcast.mybatis.domain.UserMapper:
package cd.itcast.mybatis.domain;
public interface UserMapper {
    //对应<insert id="save" keyProperty="id" parameterType="User">
    void save(User u);

//对应<update id="update" parameterType="User">
    void update(User u);

//对应<delete id="delete" parameterType="long">
    void delete(Long id);

//对应<select id="get" parameterType="long" resultType="User">
    User get(Long id);

//对应<select id="list" resultType="User">
    List<User> list();
}
对照每一个方法的注释,应该是很好理解的。
使用Mapper接口。有了Mapper接口,并且Mapper接口放在了指定的位置之后,我们的测试就可以写成:
public class CRUDTest {
@Test
public void testSave() {
    SqlSession session = MyBatisUtil.openSession();
    try {
        User u = new User();
        u.setName("itcasT");
        u.setHireDate(new Date());
        UserMapper mapper=session.getMapper(UserMapper.class);
        mapper.save(u);
        session.commit();
    } finally {
        session.close();
    }
}

@Test
public void testGet() {
    SqlSession session = MyBatisUtil.openSession();
    try {
        UserMapper mapper=session.getMapper(UserMapper.class);
        User u=mapper.get(2l);
        System.out.println(u);
    } finally {
        session.close();
    }
}

@Test
public void testUpdate() {
    SqlSession session = MyBatisUtil.openSession();
    try {
        User u = new User();
        u.setId(1l);
        u.setName("update");
        u.setHireDate(new Date());
        UserMapper mapper=session.getMapper(UserMapper.class);
        mapper.update(u);
        session.commit();
    } finally {
        session.close();
    }
}

@Test
public void testList() {
    SqlSession session = MyBatisUtil.openSession();
    try {
        UserMapper mapper=session.getMapper(UserMapper.class);
        List<User> us= mapper.list();
        System.out.println(us);
    } finally {
        session.close();
    }
}

@Test
public void testDelete() {
    SqlSession session = MyBatisUtil.openSession();
    try {
        UserMapper mapper=session.getMapper(UserMapper.class);
        mapper.delete(2l);
        session.commit();
    } finally {
        session.close();
    }
}
}
代码变得非常清晰,并且类型都使用接口强制性的完成。
Mybatis怎么做的?
测试:
@Test
public void testMapper(){
    SqlSession session = MyBatisUtil.openSession();
    try {
        UserMapper mapper=session.getMapper(UserMapper.class);
        System.out.println(mapper.getClass().getName());
    } finally {
        session.close();
    }
}
打印结果:
$Proxy4
很简单了,mybatis为接口做了一个动态代理。在执行UserMapper接口上面的方法时,参考接口的全限定名,即可找到对应的
UserMapper.xml,在执行接口上面的每一个方法的时候,实际上就是在执行namespace+id,mybatis在根据定义的方法的元素,
选择调用合适的session的方法来执行,并传入参数可以。
使用Mapper接口的方式,在集成Spring+MyBatis也非常方便。因为我们可以直接把Mapper接口看作DOMAIN的DAO接口了。

假设现在User对象不变,但是对应USER表中的name列的名称DBA重新设计成了username,那现在再来运行一遍测试:
可以看到这次的name属性就为null。这时候就体现出mybatis在直接使用resultType的局限性,要求属性名称必须和列的名称一致(大小写可以不一致)。在这种情况下,就必须要手动来完成数据表列和对象的映射关系了。首先来修改get方法:
<select id="get" parameterType="int" resultMap="usermapping">
SELECT * FROM user WHERE id = #{id}
</select>
在这里,可以看到,去掉了resultType,因为resultType只能完成默认的对象类型的转换。在这里修改成了resultMap,其实这里叫
做resultMapping对于学习了hibernate的童鞋来说更好理解。在这里我把结果集定义到了一个名字叫做usermapping的映射上。
下面定义usermapping:
<resultMap type="User" id="usermapping">
    <id property="id" column="id"/>
    <result property="name" column="username"/>
    <result property="hireDate" column="hiredate"/>
</resultMap>
resultMap定义了一个ORM的具体映射方式。
1,type:代表O,即最终返回的对象类型
2,id:为该映射设置一个名称,这个名称就是在get或list中使用的resultMap对应的id
3,id/result:对应这属性的映射,可以参考hibernate的property。id和result的区别在于,id一般用于映射主键,可以提高速度,result一般对于普通的属性。
设置完成后,就可以将对象正常get了。
在mybatis中,其实如果仅仅只是使用了resultType,相当于mybatis自动的帮我们建立了一个resultMap,只是这个resultMap直接完成了属性和列相同名称的映射而已。所以,mybatis真正完成映射的地方就在resultMap。

到此,单对象的CRUD的Mybatis实现就完成了。可以看到,在mybatis中,大部分的控制细节仍然是交由我们自己去控制,特别是sql。所以,
待会我们看到多对象关系的时候,一定要有这个概念,mybatis不会像hibernate那样为我们考虑周全对象的CRUD,所有的SQL都应该由我们
自己去控制。所以,在完成mybaits对象关系的配置中,需要转变一些在hibernate中的固有的面向对象的思想。如果说hibernate是面向
对象为主,关系为辅,那么在mybatis中则是着重考虑的是关系模型,换句话说,如果对象模型设计的不好,就会很容易的感觉到实现的难度。

MyBatisCRUD的优化上

时间: 2024-10-17 18:47:25

MyBatisCRUD的优化上的相关文章

关于大型网站技术演进的思考(十九)--网站静态化处理—web前端优化—上(11)

网站静态化处理这个系列马上就要结束了,今天我要讲讲本系列最后一个重要的主题web前端优化.在开始谈论本主题之前,我想问大家一个问题,网站静态化处理技术到底是应该归属于web服务端的技术范畴还是应该归属于web前端的技术范畴,要回答清楚这个问题我们要明确下网站应用的本质到底是什么?网站的本质其实就是BS,这里的BS我没有带上架构二字,而就是指Browser和Server即浏览器和服务器,而网站静态化技术的作用目标就是让客户端即浏览器的用户体验更好,但是如果我们想让网站在浏览器上运行的更快,在更快的

基于大数据的用户行为预测在前端性能优化上的应用

首先,我得说,这篇文章有点标题党了,其实内容并没有标题看起来那么高大上.其次,本文只是做一个技术方案可能性的探讨,并没有提供完善的解决方案,至多给了一个Demo供参考. 目的 如需转载,请注明转自:http://www.cnblogs.com/silenttiger/p/4929841.html 前端性能优化,我觉得最主要的目的就两个:1.提升页面加载速度:2.节约服务器资源. 这里特别提一下节约服务器资源,很多人在做前端性能优化的时候,往往只考虑前端性能的问题,而完全忽视前端的性能优化对后端服

【转】关于大型网站技术演进的思考(十九)--网站静态化处理—web前端优化—上(11)

网站静态化处理这个系列马上就要结束了,今天我要讲讲本系列最后一个重要的主题web前端优化.在开始谈论本主题之前,我想问大家一个问题,网站静态化处理技术到底是应该归属于web服务端的技术范畴还是应该归属于web前端的技术范畴,要回答清楚这个问题我们要明确下网站应用的本质到底是什么?网站的本质其实就是BS,这里的BS我没有带上架构二字,而就是指Browser和Server即浏览器和服务器,而网站静态化技术的作用目标就是让客户端即浏览器的用户体验更好,但是如果我们想让网站在浏览器上运行的更快,在更快的

[Java 8] (8) Lambda表达式对递归的优化(上) - 使用尾递归 .

递归优化 很多算法都依赖于递归,典型的比如分治法(Divide-and-Conquer).但是普通的递归算法在处理规模较大的问题时,常常会出现StackOverflowError.处理这个问题,我们可以使用一种叫做尾调用(Tail-Call Optimization)的技术来对递归进行优化.同时,还可以通过暂存子问题的结果来避免对子问题的重复求解,这个优化方法叫做备忘录(Memoization). 本文首先对尾递归进行介绍,下一票文章中会对备忘录模式进行介绍. 使用尾调用优化 当递归算法应用于大

逆向课程第四讲逆向中的优化方式,除法原理,以及除法优化上

一丶为什么要熟悉除法的优化,以及除法原理 是这样的,在计算机中,除法运算对应的汇编指令分为 DIV(无符号除法指令) 以及 IDIV(有符号除法指令). 但是,除法指令的执行周期较长效率很低.所以编译器想进办法的用其它指令去代替除法指令. 比如: DIV 指令是100个周期 计算 2 / 2 那么可能在汇编中的表现形式是这样的 CDQ  符号扩展 DIV EDX,2 好,现在100个周期没有了 减法和加法指令,指令周期是4个那么上面的公式可以演化为 mov eax,2 sub eax,2 就算m

OpenFire源码学习之二十一:openfie对用户的优化(上)

用户类 优化用户主要是要解决用户的连接量.已经对用户的访问速度和吞吐量. 预初始化 在前面的带面中提出来了用户的预初始化.这里就不在贴出来了.下面将redis用户库连接池处理贴出来UserJedisPoolManager public class UserJedisPoolManager extends BasicModule{ private static final Logger log = LoggerFactory.getLogger(UserJedisPoolManager.class

H5实现图片优化上传

一,HTML部分 <input type="file" accept="images/*"> <input class="url" type="url" placeholder="url"> <div class="container"></div> <button class="submit">Submit

无助于于SEO优化上网站页面的设想准则

www.mypm.net/expert/show_question_content.asp?questionId=285573www.mypm.net/expert/show_question_content.asp?questionId=285609www.mypm.net/expert/show_question_content.asp?questionId=285650www.mypm.net/expert/show_question_content.asp?questionId=2856

SEO提议优化上网站网站关头词

mypm.net/expert/show_question_content.asp?questionId=276748mypm.net/expert/show_question_content.asp?questionId=276772mypm.net/expert/show_question_content.asp?questionId=276824mypm.net/expert/show_question_content.asp?questionId=276854mypm.net/exper