谈jdbcTemplate与mybatis

摘要:
为什么会出现Hibernate Mybatis这样的Dao层框架?虽然传统的jdbc执行速度快,但其开发效率很低。使用面向对象开发的设计思想,对象被持久化在面向对象编程中,并存储在关系数据库中。因为关系数据库的设计思想是数学的,所以必须将对象拆分为属性值,然后才能将其存储在数据库中;当使用传统的jdbc持久性来持久化对象时,对象的一个属性将被删除。在过去,它很麻烦,很难维护。然而,市场上的面向对象数据库

为什么会产生 Hibernate Mybatis 这类的dao层框架

传统的jdbc 虽然执行速度很快,但是开发效率很低,随着面向对象开发的设计思想,在面向对象编程中 将对象 进行持久化,存入关系型的数据库时,由于关系型数据库的设计思想是数学思维,在持久化时,必须要对象拆分各个属性值,才可存入数据库;传统的jdbc 持久化时 对象持久化时 ,取出对象的一个一个属性,过去繁琐,并且不便于维护,而市场上的面向对象的数据库还并不成熟,所以为了调节面向对象设计的开发思想与落后的关系型数据库之间持久化时繁琐的问题,产生了一种新的设计规范

ORM (Object Relation Mapping) 

对象关系映射,是一种规范,调节目前面向对象的程序设计与主流的关系型数据库之间 发展不同步的问题,
关系 到对象的映射;
让编程时 可以全身心的用面向对象的设计思想去编程,用对象映射关系数据表,在持久化时,可以直接操作对象进行持久化。
优点:
开发效率高;
可维护性高;
缺点:
高效率的开发 对应也要失去性能,处理复杂关系时,性能会变差;
 

Spring对数据库的操作在jdbc上面做了深层次的封装,也就是工具类 jdbcTemplate

先看一下jdbcTemplate的大致流程图

谈jdbcTemplate与mybatis第1张

作用:

1: 它提供了AOP式的事务管理

AOP式的事物管理:在以前的事务管理是要融合在逻辑代码中的,在逻辑代码中决定事务是否提交或者回滚,这样很容易造成代码难以维护,代码冗余
但是使用spring的声明式事务后,只需要在数据库处理方法上注解事务,就可以对操作进行管理,事务的设置和逻辑代码分开,容易维护。

不修改原有代码 重新封装现有的组件
类似于: FileWrite fw = new FileWrite();
PrintWrinter pw = new Prinwriter(fw);
2:spring 提供了统一的异常处理,框架处理了异常。
不论Dao层运用什么技术实现 出现的错误全部封装成了DatyaAccessException
如何使用 
1 引入相应spring jar包 + 数据库驱动包
2  在spring的主配置文件中配置 jdbcTemplate
<!-- 定义template组件 -->
    <bean id="template" 
        class="org.springframework.jdbc.core.JdbcTemplate">
        <!-- 注入连接信息 -->
        <property name="dataSource" ref="bonecp">
        </property>
    </bean>
 定义组件时 template需要一个数据连接池 来管理数据库连接
数据连接池 有很多种 这里用的是
com.alibaba.druid.pool.DruidDataSource
<!-- DataSource 数据源 连接池 存储管理大量的链接 流行的 dbcp c3p0,proxool -->
        <!-- 数据源配置, 使用 BoneCP 数据库连接池 -->
    <bean id="bonecp" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
        <!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        
        <!-- 基本属性 url、user、password -->
        <property name="url" value="jdbc:mysql://localhost:3306/medicine?useUnicode=true&amp;characterEncoding=utf-8" />
        <property name="username" value="root" />
        <property name="password" value="root" />
        
        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="60000" />
        
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="300000" />
        
    
        <property name="testWhileIdle" value="true" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        
        
        
        <!-- 配置监控统计拦截的filters -->
        <property name="filters" value="stat" /> 
    </bean>

下一部是根据表 编写实体类

谈jdbcTemplate与mybatis第2张

实体类

package com.mxp.jdbc.entity;

import java.io.Serializable;

public class User implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String id;
    private String userName;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    
    

}

还需要根据实体类写一个rowmapper

注意这里要继承

org.springframework.jdbc.core.RowMapper,然后重写maprow方法
package com.mxp.jdbc.entity;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

/** 
 * 每个实体类都有这个封装组件
 * 将User记录封装成 User对象
 * @author Administrator
 *
 */
public class UserRowMapper implements RowMapper<User>{

    /**
     * arg1:第几行记录 
     */
    @Override
    public User mapRow(ResultSet arg0, int arg1) throws SQLException {
        User user = new User();
        user.setId(arg0.getString("id"));
        user.setUserName(arg0.getString("user_name"));
        return user;
    }

}

 下面可以编写dao了 编写之前我们在spring的主配置文件中要把spring的扫描组件启动

<!-- spring组件扫描 -->
    <context:component-scan base-package="com.mxp">
    </context:component-scan>

dao

package com.mxp.jdbc.dao;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.mxp.jdbc.entity.User;
import com.mxp.jdbc.entity.UserRowMapper;


@Repository
public class ItinerantDAO {
    @Autowired
    private JdbcTemplate template;//注入的方式
    public void save(User user){
        String sql = "insert into test_user" +
         "(id,user_name) values (?,?)";
        Object[] params = {
                 user.getId(),user.getUserName()
        };
        template.update(sql, params);
    }
    public List<User> findAll(){
        String sql ="select * from test_user";
        UserRowMapper rowMapper = new UserRowMapper();
        List<User> list = template.query(sql, rowMapper);
        return list;
    }
 
}

那现在就可以写测试方法

package test;

import java.io.IOException;

import java.util.List;




import org.apache.ibatis.session.SqlSession;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


import com.mxp.ControllerQW;

import com.mxp.jdbc.dao.ItinerantDAO;
import com.mxp.jdbc.entity.User;
import com.mxp.mybatis.util.MybatisUtil;

public class Test {
    public static void main(String[] args) {
//spring的主配置文件名 String conf
= "spring-context.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(conf); ItinerantDAO dao = ac.getBean("itinerantDAO",ItinerantDAO.class); User user = new User(); user.setId("1455"); user.setUserName("文森特"); dao.save(user); } @org.junit.Test public void test(){
String conf
= "spring-context.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(conf); ItinerantDAO dao = ac.getBean("itinerantDAO",ItinerantDAO.class); List<User> list = dao.findAll(); for(User u:list){ System.out.println(u.getUserName()); } } }

这jdbcTemplate 见的次数很少 至今为止 还没有见到用的 

Mybatis

原来在我们使用jdbc的问题

1 对数据库的连接 使用时就创建连接,不使用就立即释放,对数据库进行频繁连接开启和关闭,造成数据库的资源浪费,影响数据库的性能;

解决办法:使用数据库连接池,管理数据库的连接。

2 将sql语句硬编码到java代码中,如果sql语句修改,需要重新编译java代码,不利于系统维护,

解决办法:把sql语句I定义到xml配置文件里;

3 在向statement中设置参数,对站位符位置和设置参数数值,硬编码到java代码中,

4 从result结果集中遍历数据时,存在硬编码,讲获取表的字段名硬编码,不便于维护,

讲结果集 自动映射成java对象

mybatis的架构

是一个持久层的项目,是阿帕奇的顶级项目,

通过 mybatis提供的映射方式,半自动的生成sql,大部分还是需要程序员编写sql

核心:输入映射:可以将statement中的输入参数自动输入到映射 通过ongl表达式,将查询的结果集灵活映射成为java对象(输出映射)

mybatis的结构
那么说一下myabtis的大致工作流程

1、  mybatis配置

SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。

mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。

2、  通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂

3、  由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。

4、  mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。

5、  Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。

6、  Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过 Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

7、  Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过 Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

谈jdbcTemplate与mybatis第3张
 
第一步主配置文件
<?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="environment">
        <environment id="environment">
            <transactionManager type="JDBC" />
            <!-- mybatis 自带连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/medicine?useUnicode=true&amp;characterEncoding=utf-8" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>
    <!-- 定义sqlMapper文件位置的 -->
    <mappers>
        <mapper resource="com/mxp/mybatis/entity/UserMapper.xml" />
    </mappers> 
</configuration>

第二步 实体类及其sqlmap映射文件

package com.mxp.mybatis.entity;

import java.io.Serializable;

public class User implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String id;
    private String userName;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    
}
<?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 namespace="com.mxp.mybatis.entity.UserMapper">
   
    <sql id="userColumns">
        a.id AS "id",
        a.user_name AS "userName"
    </sql>
    
    <select id="findAll" resultType="com.mxp.mybatis.entity.User" >
            SELECT <include refid="userColumns"/>
                FROM test_user a
    </select>
    
    <select id="findLikeName" parameterType="string" resultType="com.mxp.mybatis.entity.User" >
        SELECT <include refid="userColumns"/>
                FROM test_user a
                <where>
                    a.user_name like #{name}
                </where>
                 
    </select>
    
</mapper>

第三部 获取sqlsession

package com.mxp.mybatis.util;

import java.io.InputStream;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MybatisUtil {
    
    public static SqlSession getInsertance(){
        SqlSessionFactoryBuilder builder = 
                new SqlSessionFactoryBuilder();
        //这是读取文件后 形成一个输入流 涨知识了
        //Test 其实就是一个类型 写自己的什么类型都行 主要是为了获取到getClassLoader().getResourceAsStream
        InputStream reader = MybatisUtil.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml");
        //获取sqlsessionFactory
        SqlSessionFactory factory =  builder.build(reader);
        //获取session
        SqlSession session = factory.openSession();
        return session;
    }

}

第四部 写测试类

package test;

import java.io.IOException;

import java.util.List;




import org.apache.ibatis.session.SqlSession;
import com.mxp.mybatis.util.MybatisUtil;

public class Test {
  
    @org.junit.Test
    public void getSqllSession() throws IOException{
        
        SqlSession session = MybatisUtil.getInsertance();
        System.out.println("获取session");
        session.close();
    }
    @org.junit.Test
    public void findall(){
        SqlSession sqlsession = MybatisUtil.getInsertance();
        List<com.mxp.mybatis.entity.User> list =  sqlsession.selectList("findAll");
        for(com.mxp.mybatis.entity.User u:list){
            System.out.println(u.getUserName());
        }
        sqlsession.close();
        
        
    }
    @org.junit.Test
    public void findLike(){
        SqlSession sqlsession = MybatisUtil.getInsertance();
        List<com.mxp.mybatis.entity.User> list =  sqlsession.selectList("findLikeName","%文%");
        for(com.mxp.mybatis.entity.User u:list){
            System.out.println(u.getUserName());
        }
        sqlsession.close();
        
        
    }
}

 Mybatis的

Mapper映射器接口规则,会自动生成接口实现类。

修饰public

a.根据sqlMapper定义的id属性当接口方法名

b 根据sqlMapper定义的parameterType类型定义参数类型

c 根据sqlMapper定义的resultType的类型 定义方法的返回类型

(多行使用list<泛型(resultType的类型)>,单行使resultType的类型)

d 将sqlMapper的namespace属性指定成为 包名.接口名字,就是接口的位置,

 如何取到接口实现类呢

从sqlsession中获取

sqlsession.getMapper(接口的class对象);

mybatis替我生成实现类,在实现类中把sqlsession.select*的各种操作封装起来

 首先实现 d

<?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 namespace="com.mxp.mybatis.dao.UserDao">
   
    <sql id="userColumns">
        a.id AS "id",
        a.user_name AS "userName"
    </sql>
    
    <select id="findAll" resultType="com.mxp.mybatis.entity.User" >
            SELECT <include refid="userColumns"/>
                FROM test_user a
    </select>
    
    <select id="findLikeName" parameterType="string" resultType="com.mxp.mybatis.entity.User" >
        SELECT <include refid="userColumns"/>
                FROM test_user a
                <where>
                    a.user_name like #{name}
                </where>
                 
    </select>
    
</mapper>

 a b c

package com.mxp.mybatis.dao;

import java.util.List;



import com.mxp.mybatis.entity.User;

public interface UserDao {
 public List<User> findAll();
 public List<User> findLikeName(String name);
}

测试生成的映射器接口实现类

@org.junit.Test
    public void testMapper(){
        SqlSession sqlsession = MybatisUtil.getInsertance();
        UserDao dao = sqlsession.getMapper(UserDao.class);
        List<com.mxp.mybatis.entity.User> os = dao.findAll();
        for(com.mxp.mybatis.entity.User u:os){
            System.out.println(u.getUserName());
        }
        sqlsession.close();
        
    }

免责声明:文章转载自《谈jdbcTemplate与mybatis》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇TSQL笔记7:临时表和表变量[转]linux共享库位置配置(LD_LIBRARY_PATH环境变量 或者 更改/etc/lld.so.conf下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

MySQL 通配符学习小结

MySQL 通配符 SQL的模式匹配同意你使用“_”匹配不论什么单个字符,而“%”匹配随意数目字符(包含零个字符)。在 MySQL中,SQL的模式缺省是忽略大写和小写的。以下显示一些样例。 注意在你使用SQL模式时,你不能使用=或!=;而使用LIKE或NOT LIKE比較操作符。 为了找出以“b”开头的名字: mysql>...

使用jest进行单元测试

以前,写完一段代码我也是直接调用或者实例化一下,发现过了就把测试相关部分删了。今年的不幸与坎坷使我有很长一段时间去思考人生,不想将就了,鲁棒健壮的程序,开发和测试应该是分得很开的,于是我选择jest去做单元测试这件事。 为什么要做单元测试 在开始之前,我们先思考这样一个问题,我们为什么要做单元测试? 不扯犊子直接说吧,第一点,用数据、用茫茫多的测试用例去告...

spring-boot-route 读取配置文件的几种方式

Spring Boot提供了两种格式的配置文件,分别是properties 和 yml。Spring Boot最大的特点就是自动化配置,如果我们想修改自动化配置的默认值,就可以通过配置文件来指定自己服务器相关的参数。 配置文件集约管理了配置信息,如果把配置参数写到Java代码中,维护起来非常不方便,如果使用配置文件,我们可以统一管理,统一修改。我比较推荐使...

Sqlserver 利用时间戳 + 自增长ID 生成流水号 模拟并发请求生成重复ID 解决方法

1. 事件起因: 当在sqlserver 中利用 时间戳(22010110) + 请求终端ID (1001) + 四位流水号(开始0001) ; 四位流水号算法创建表TZD_LSH ;其中id是 自增长 ;系数1 insert into TZD_LSH (Hoisd) select @hospcode select newid = m...

上传下载后台函数以及前端脚本(webuploader) 备份

1 import java.io.BufferedOutputStream; 2 import java.io.IOException; 3 import java.io.InputStream; 4 import java.io.PrintWriter; 5 import java.io.UnsupportedEncodingExce...

照片上传(缩略图实现)

1.获取所有的提交到服务器的文件集合 HttpFileCollection fileColl= Request.Files; 2.取得一个文件(这里是一张照片)     HttpPostedFile pic = fileColl[0]; 3.判断文件是否为空     1.获取服务器存放图片的物理路径(Server.MapPath)        strin...