Mybatis与Spring整合(二)sqlSession的方式操作SQL语句

上篇 介绍了用接口的方法极大的节省了dao层,只需通过 配置文件和接口就可以实现,这次介绍的是通过splsession来实现dao,这种方法比较灵活;

这篇文章基于Mybatis与Spring整合(一)

不同之处在于把 Mybatis与Spring整合(一)中的第五、第七、第八去掉,第六步需要去掉一点内容,保留其它几个一级目录即可再加上另外的两个一级目录

一、创建maven工程

创建一个普通的maven工程,基于web

项目目录:

 

二、创建数据库与表

DROP TABLE IF EXISTS `books`;
CREATE TABLE `books` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `title` varchar(100) NOT NULL COMMENT '书名',
  `price` double(10,2) DEFAULT NULL COMMENT '价格',
  `publishDate` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '出版日期',
  PRIMARY KEY (`id`),
  UNIQUE KEY `title` (`title`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of books
-- ----------------------------
INSERT INTO `books` VALUES ('1', 'Java编程思想', '98.50', '2005-01-02 00:00:00');
INSERT INTO `books` VALUES ('2', 'HeadFirst设计模式', '55.70', '2010-11-09 00:00:00');
INSERT INTO `books` VALUES ('3', '第一行Android代码', '69.90', '2015-06-23 00:00:00');
INSERT INTO `books` VALUES ('4', 'C++编程思想', '88.50', '2004-01-09 00:00:00');
INSERT INTO `books` VALUES ('5', 'HeadFirst Java', '55.70', '2013-12-17 00:00:00');
INSERT INTO `books` VALUES ('6', '疯狂Android', '19.50', '2014-07-31 00:00:00');

三、添加依赖包

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.wqc</groupId>
    <artifactId>BookStore</artifactId>
    <version>0.0.1</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>4.3.9.RELEASE</spring.version>
    </properties>

    <dependencies>
        <!--Spring框架核心库 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- aspectJ AOP 织入器 -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
        </dependency>
        <!--mybatis-spring适配器 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.0</version>
        </dependency>
        <!--Spring java数据库访问包,在本例中主要用于提供数据源 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--mysql数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <!--log4j日志包 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.6.1</version>
        </dependency>
        <!-- mybatis ORM框架 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.1</version>
        </dependency>
        <!-- JUnit单元测试工具 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
        <!--c3p0 连接池 -->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <!-- jstl -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>
</project>

有了c3p0为啥要spring-jdbc?这个就是连接池和数据源的区别....

四、新建POJO实体层

为了实现与数据库中的books表进行关系映射新建一个Book类

public class Book {
	
    private int id;
    private String title;
    private double price;
    private Date publishDate;

    public Book(int id, String title, double price, Date publishDate) {
        this.id = id;
        this.title = title;
        this.price = price;
        this.publishDate = publishDate;
    }
    public Book() {
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public Date getPublishDate() {
        return publishDate;
    }
    public void setPublishDate(Date publishDate) {
        this.publishDate = publishDate;
    }
    
}

五、为MyBatis ORM创建的映射文件BookMapper.xml

(命名尽量都遵循一个规则,便于扫描,这里约定以实体名+Mapper)

<?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.wqc.mapper.BookDAO">

	<!--user结果映射-->
    <resultMap id="Book" type="com.wqc.model.Book">
        <result column="id" property="id"/>
        <result column="title" property="title"/>
        <result column="price" property="price"/>
        <result column="publishDate" property="publishDate"/>
    </resultMap>
    
    <!--id应该是接口中的方法,结果类型如没有配置别名则应该使用全名称 -->
    <!--获得所有图书 -->
    <select id="getAllBooks" resultMap="Book">
        select id,title,price,publishDate from books
    </select>
    <!--获得图书对象通过编号 -->
    <select id="getBookById" resultMap="Book">
        select id,title,price,publishDate from books where id=#{id}
    </select>
    <!-- 增加 -->
    <insert id="add">
        insert into books(title,price,publishDate)
        values(#{title},#{price},#{publishDate})
    </insert>
    <!-- 删除 -->
    <delete id="delete">
        delete from books where id=#{id}
    </delete>
    <!-- 更新 -->
    <update id="update">
        update books set title=#{title},price=#{price},publishDate=#{publishDate}
        where id=#{id}
    </update>
</mapper>

六、完成Spring整合MyBatis配置

6.1、在源代码的根目录下新建 jdbc.properties文件,用于存放数据库连接信息,文件内容如下:

#mysql jdbc
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_mybatis?useUnicode=true&characterEncoding=UTF-8
jdbc.uid=root
jdbc.pwd=123456

6.2、在源代码的根目录下新建 applicationContext.xml文件,用于整合MyBatis与Spring,该文件是整个项目的控制中心,非常关键,具体的内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">


    <!--1 容器自动扫描IOC组件  -->
    <context:component-scan base-package="com.wqc"></context:component-scan>

    <!--2 引入属性文件,在配置中占位使用 -->
    <context:property-placeholder location="classpath*:jdbc.properties" />

    <!--3 配置C3P0数据源 -->
    <bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <!--驱动类名 -->
        <property name="driverClass" value="${jdbc.driver}" />
        <!-- url -->
        <property name="jdbcUrl" value="${jdbc.url}" />
        <!-- 用户名 -->
        <property name="user" value="${jdbc.uid}" />
        <!-- 密码 -->
        <property name="password" value="${jdbc.pwd}" />
        <!-- 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数  -->
        <property name="acquireIncrement" value="5"></property>
        <!-- 初始连接池大小 -->
        <property name="initialPoolSize" value="10"></property>
        <!-- 连接池中连接最小个数 -->
        <property name="minPoolSize" value="5"></property>
        <!-- 连接池中连接最大个数 -->
        <property name="maxPoolSize" value="20"></property>
    </bean>
    
    <!--4 会话工厂bean sqlSessionFactoryBean -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 数据源 -->
        <property name="dataSource" ref="datasource"></property>
        <!-- 别名 -->
        <property name="typeAliasesPackage" value="com.wqc.model"></property>
        <!-- sql映射文件路径 -->
        <property name="mapperLocations" value="classpath*:mapper/*Mapper.xml"></property>
    </bean>
    
    
    <!--6 声明式事务管理 -->
    <!--定义事物管理器,由spring管理事务 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="datasource"></property>
    </bean>
    <!--支持注解驱动的事务管理,指定事务管理器 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    <!--7 aspectj支持自动代理实现AOP功能 ,非必要 -->
    <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>

这个xml中共有7处配置,第7处配置非必要,另外关于事务管理可以选择AOP拦截式事务管理。 

七、封装sqlSession操作

QueryHepler.java

 这是是查询助手,帮助封装sqlSession的参数:

public class QueryHelper {

	private String nameSpace;
	private String methodId;
	private Object param;
	private Map<String, Object> params;

	// 设置命名空间.
	public QueryHelper setNameSpace(String nameSpace) {
		this.nameSpace = nameSpace;
		return this;
	}

	// 设置dao方法的ID.
	public QueryHelper setMethodId(String methodId) {
		this.methodId = methodId;
		return this;
	}

	// 设置一个参数.
	public QueryHelper setParam(Object param) {
		this.param = param;
		return this;
	}

	// 设置多个参数.
	public QueryHelper setParams(String key, Object value) {
		if (params == null) {
			params = new HashMap<String, Object>();
		}
		params.put(key, value);
		return this;
	}

	// 获取一个参数.
	public Object getParam() {
		return param;
	}

	// 获得多个参数.
	public Map<String, Object> getParams() {
		return params;
	}

	// 获取非空的参数.
	public Object getRealParams() {
		return param == null ? params : param;
	}

	// 得到结果.
	public String getMethod() {
		return nameSpace + "." + methodId;
	}
}

DaoSupport.java

public interface DaoSupport {

	public void insert(QueryHelper queryHelper);

    public void insert(String method,Object param);

    public void delete(QueryHelper queryHelper);

    public void delete(String method,Object o);

    public void update(QueryHelper queryHelper);

    public void update(String method,Object o);

    public<T> T select(QueryHelper queryHelper);

    public<T> T select(String method,Object o);

    public<T> List<T> selectList(QueryHelper queryHelper);

    public<T> List<T> selectList(String method,Object o);

    public<T> List<T> getPageData(int pageNum,int pageSize,QueryHelper queryHelper);

	public<T> List<T> selectWithoutParams(String method);
    
}

DaoSupportImpl.java

@Repository("daoSupport")
@Transactional //事务管理
public class DaoSupportImpl implements DaoSupport {

	@Resource
    private SqlSessionFactory sqlSessionFactory;

    private SqlSession sqlSession = null;

    /**
     * 获取sqlSession. 这里可以改进,详情见第九点
     * @return
     */
    public SqlSession getSqlSession(){
        if(sqlSession==null){
            sqlSession = sqlSessionFactory.openSession();
        }
        return sqlSession;
    }


    @Override
    public void insert(QueryHelper queryHelper) {
        getSqlSession().insert(queryHelper.getMethod(),queryHelper.getRealParams());
    }


    @Override
    public void insert(String method, Object param) {
        getSqlSession().insert(method,param);
    }

    @Override
    public void delete(QueryHelper queryHelper) {
        getSqlSession().delete(queryHelper.getMethod(),queryHelper.getRealParams());
    }

    @Override
    public void delete(String method, Object o) {
        getSqlSession().delete(method,o);
    }

    @Override
    public void update(QueryHelper queryHelper) {
        getSqlSession().update(queryHelper.getMethod(),queryHelper.getRealParams());
    }

    @Override
    public void update(String method, Object o) {
        getSqlSession().update(method,o);
    }

    @Override
    public <T> T select(QueryHelper queryHelper) {
        return getSqlSession().selectOne(queryHelper.getMethod(),queryHelper.getRealParams());
    }

    @Override
    public <T> T select(String method, Object o) {
        return getSqlSession().selectOne(method,o);
    }

    @Override
    public <T> List<T> selectList(QueryHelper queryHelper) {
        return getSqlSession().selectList(queryHelper.getMethod(),queryHelper.getRealParams());
    }

    @Override
    public <T> List<T> selectList(String method, Object o) {
        return getSqlSession().selectList(method,o);
    }

    @Override
    public <T> List<T> getPageData(int pageNum, int pageSize, QueryHelper queryHelper) {
        return null;
    }
    
    @Override
    public <T> List<T> selectWithoutParams(String method) {
        return getSqlSession().selectList(method);
    }

}

八、JUnit测试服务类

为了确保服务类中的每个方法正确,先使用JUnit进行单元测试,测试代码如下:

这里也可以采用注解的方式来测试,在测试类上加:

不过先要引入:spring-test jar包才能使用这两个注解

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/application.xml")

TestBookServiceBySqlSession.java:

public class TestBookServiceBySqlSession {
	
	private static DaoSupport daoSupport;
	
	private static SqlSessionFactory sqlSessionFactory; 
	
	@BeforeClass
    public static void before(){
        ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        daoSupport=ctx.getBean(DaoSupport.class);
        sqlSessionFactory=ctx.getBean(SqlSessionFactory.class);
    }

	// 原生的sqlSession,没有使用DaoSupport和QueryHelper
	@Test
	public void testSqlSession() {
		List<Book> bookList = sqlSessionFactory.openSession().selectList("com.wqc.mapper.BookDAO.getAllBooks", null);
		for (Book book : bookList) {
			System.out.println(book);
		}
	}
	
	@Test
	public void testGetAllBooks() {
		System.out.println("测试开始...");
		
		QueryHelper helper = new QueryHelper();
		helper.setNameSpace("com.wqc.mapper.BookDAO");
		helper.setMethodId("getAllBooks");
		List<Book> bookList = daoSupport.selectList(helper);
		for (Book book : bookList) {
			System.out.println(book);
		}
		System.out.println("测试结束...");
	}
	
}

运行测试用例,测试通过...

九、改进点

1、sqlSession的改进

可以在第六点的mybatis与spring整合配置里加上下面的内容,就可以不用再daoSupport中手动注入sqlSession了。

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> 
        <constructor-arg index="0" ref="sqlSessionFactory" /> 
    </bean>

就可以在DaoSupportImpl中直接 注解注入sqlSession

2、DaoSupportImpl的改进

可以在DaoSupportImpl的方法中try catch捕获异常,获取throws 向上一层抛出异常,让调用层知道是什么异常

例如:

try ... catch

 @Override
    public void insert(String method, Object param) {
    	try {
    		getSqlSession().insert(method,param);
		} catch (Exception e) {
			e.printStackTrace();
		}
    }

throws 

 @Override
    public void insert(String method, Object param) throws Exception{
    		getSqlSession().insert(method,param);
    }

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatisSpring整合可以通过Spring提供的MyBatis-Spring集成模块来实现,这个模块提供了对MyBatis的完全支持,包括: 1. SqlSessionFactory的管理和配置 2. SqlSession的管理和注入 3. Mapper接口的自动扫描和注入 4. 事务管理 下面我们来看一下如何使用MyBatis-Spring集成模块来实现映射器和动态SQL的使用。 一、映射器的使用 1. 创建Mapper接口 Mapper接口定义了一组操作数据库的方法,这些方法对应了SQL映射文件中定义的SQL语句。在使用Mapper接口之前,我们需要定义这个接口。例如: ```java public interface UserMapper { List<User> findAll(); User findById(int id); void addUser(User user); void updateUser(User user); void deleteUser(int id); } ``` 2. 编写SQL映射文件 MyBatis中的SQL语句都是通过XML文件来定义的,我们需要创建一个XML文件,来定义Mapper接口中的方法对应的SQL语句。例如: ```xml <mapper namespace="com.example.mapper.UserMapper"> <select id="findAll" resultType="com.example.model.User"> select * from user </select> <select id="findById" parameterType="int" resultType="com.example.model.User"> select * from user where id=#{id} </select> <insert id="addUser" parameterType="com.example.model.User"> insert into user(name, age, email) values(#{name}, #{age}, #{email}) </insert> <update id="updateUser" parameterType="com.example.model.User"> update user set name=#{name}, age=#{age}, email=#{email} where id=#{id} </update> <delete id="deleteUser" parameterType="int"> delete from user where id=#{id} </delete> </mapper> ``` 3. 配置MapperScannerConfigurer 在Spring的配置文件中,我们需要配置MapperScannerConfigurer来自动扫描Mapper接口,并将Mapper接口交给Spring容器来管理。例如: ```xml <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.example.mapper" /> </bean> ``` 4. 在代码中使用Mapper接口 在代码中我们可以通过注入Mapper接口的方式来使用它,例如: ```java @Autowired private UserMapper userMapper; public void test(){ List<User> userList = userMapper.findAll(); User user = userMapper.findById(1); user.setName("Tom"); userMapper.updateUser(user); userMapper.deleteUser(1); } ``` 、动态SQL的使用 MyBatis中的动态SQL可以根据条件来动态生成SQL语句,如果条件满足则将条件拼接到SQL语句中,否则不拼接。动态SQL包括了if、where、foreach、choose等标签。 1. if标签 if标签可以根据条件来动态生成SQL语句,例如: ```xml <select id="findByNameAndAge" resultType="com.example.model.User"> select * from user <where> <if test="name != null"> and name = #{name} </if> <if test="age != null"> and age = #{age} </if> </where> </select> ``` 2. where标签 where标签可以根据条件来动态生成SQL语句,并且会去掉第一个条件前面的and或者or,例如: ```xml <select id="findByNameAndAge" resultType="com.example.model.User"> select * from user <where> <if test="name != null"> and name = #{name} </if> <if test="age != null"> and age = #{age} </if> </where> </select> ``` 3. foreach标签 foreach标签可以遍历一个集合,并且根据集合中的元素来动态生成SQL语句,例如: ```xml <select id="findByIdList" resultType="com.example.model.User"> select * from user <where> <foreach collection="idList" item="id" separator="or"> id = #{id} </foreach> </where> </select> ``` 4. choose标签 choose标签可以根据条件来选择生成SQL语句的部分,类似于Java中的switch语句,例如: ```xml <select id="findByNameOrAge" resultType="com.example.model.User"> select * from user <where> <choose> <when test="name != null"> and name = #{name} </when> <when test="age != null"> and age = #{age} </when> <otherwise> and 1=1 </otherwise> </choose> </where> </select> ``` 以上就是MyBatisSpring集成的映射器和动态SQL的使用方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值