Mybatis运用mapper代码实现和Spring的整合(一)

引言


先前做的java项目中一直使用的EclipseLink和Hibernate,两种ORM框架,现在用Mybatis实现,当然它们之间各有各的优点,同样也有缺点,有时候,一个项目中是可以存在两种框架一起使用的,在项目中,技术选型很重要。Mybatis是一个持久层的框架,是apache下的顶级项目,mybatis让程序将主要的精力放在sql上,通过mybatis提供的映射方式,自由灵活生成。


Mybatis的主要是靠sql语句来进行实现对数据库持久化的,这就是mybatis的硬伤,当然,它也因为是靠sql语句进行实现,很灵活但不好维护。


画了一张简单的思维导图,咱们按照图进行说明:


Mybatis运用mapper代码实现和Spring的整合(一)_第1张图片


mybatis的框架:


我们现在说一个Mybatis的框架,当然能用图说明,我们尽量不要使用文字:


Mybatis运用mapper代码实现和Spring的整合(一)_第2张图片


对于图的说明:数据库链接的初期,只要使用时就会创建,不适用立刻释放,对数据库进行很频繁链接开启和关闭,造成数据库资源浪费,影响了数据库的性能。因此我们需要使用数据库连接池进行管理数据库的连接。这里我们需要使用sqlSessionFactory会话工厂进行管理。另外我们将sql语句硬编码到java代码中,如果sql语句修改,需要重新编译java代码,不利于系统维护,这里我们使用了将sql语句配置在xml配置文件中,即使sql变化,不需要对java代码进行编译了。另外,我们向proparedStatement中设置参数,对战位富豪位置和设置参数,也要放到xml文件中。从另外我们总是从resultSet中便利结果集数据,不利于系统维护,因此,我们将查询的结果集,自动映射成java对象。


简单的流程:


由于篇幅有限,我们直接在Spring整合工程中提到。


与spring的整合:


这里我们使用的是Mapper代理的形式,将我们所有的Mybatis的mapper代理放在SqlSessionFactory中进行管理,另外,将SqlSessionFactory嫁给Spring容器管理。具体:通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory,将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSessionFactoryBuilder。在需要创建SqlSessionFactory时候,只需要new一次SqlSessionFactoryBuilder即可。通过SqlSessionFactory创建sqlSession,通过单利模式管理SqlSessionFactory,交给Spring来进行管理。

我们整合的思路是,需要spring通过单例方式管理SqlSessionFactory,spring和mybatis整合生成代理对象,使用SQLSessionFactory创建SqlSession。(spring和mybatis整合自动完成)持久层的mapper需要由spring进行管理。


整合代码:

1、jar包


Mybatis运用mapper代码实现和Spring的整合(一)_第3张图片

Mybatis运用mapper代码实现和Spring的整合(一)_第4张图片


2、创建配置文件


首先看我们的目录结构:


Mybatis运用mapper代码实现和Spring的整合(一)_第5张图片


mybatis下面的配置SqlMapConfig.xml


<span style="font-size:18px;"><?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>
	<!-- 别名定义 -->
	<typeAliases>
		<!-- 批量别名定义 指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大写或小写都可以) -->
		<package name="com.tgb.ncre.po" />
	</typeAliases>
	<!-- 加载 映射文件 -->
	<mappers>
		<!--1、 可以一个一个的添加 -->
		<!--<mapper resource="sqlmap/User.xml" />  -->
		
		<!--2、建议使用, 批量加载mapper 指定mapper接口的包名,mybatis自动扫描包下边所有mapper接口进行加载 遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 
			中 上边规范的前提是:使用的是mapper代理方法 和spring整合后,使用mapper扫描器,这里不需要配置了 -->
		 <package name="com.tgb.ncre.mapper"/>  

	</mappers>

</configuration></span>

db.properties文件:


<span style="font-size:18px;">jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root</span>

添加log4j.properties文件:


<span style="font-size:18px;"># Global logging configuration
#\u5728\u5f00\u53d1\u73af\u5883\u4e0b\u65e5\u5fd7\u7ea7\u522b\u8981\u8bbe\u7f6e\u6210DEBUG\uff0c\u751f\u4ea7\u73af\u5883\u8bbe\u7f6e\u6210info\u6216error
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n</span>

sqlmap文件夹下我们暂时不用。是用dao直接注入SqlSessionFactory的时候,才用到的,我们这里用到的是在mapper中直接添加xml文件的。


下面是最重要的spring的applicationContext.xml文件,我们在这个文件下进行注入SqlSession的。


<span style="font-size:18px;"><beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
		http://www.springframework.org/schema/mvc 
		http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context-3.2.xsd 
		http://www.springframework.org/schema/aop 
		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

	<!-- 加载配置文件 -->
	<context:property-placeholder location="classpath:db.properties" />

	<!-- 数据源,使用dbcp -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<property name="driverClassName" value="${jdbc.driver}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
		<property name="maxActive" value="10" />
		<property name="maxIdle" value="5" />
	</bean>

	<!-- sqlSessinFactory -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 加载mybatis的配置文件 -->
		<property name="configLocation" value="mybatis/SqlMapConfig.xml" />
		<!-- 数据源 -->
		<property name="dataSource" ref="dataSource" />
	</bean>
	
	<!-- 原始dao接口 -->	
	 <bean id="userDao" class="com.tgb.ncre.dao.UserDaoImpl">
		<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
	</bean> 
	
	<!-- mapper配置 
	MapperFactoryBean:根据mapper接口生成代理对象
	-->
 	 <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
		<!--mapperInterface指定mapper接口 -->
		<property name="mapperInterface" value="com.tgb.ncre.mapper.UserMapper"/>
		<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
	</bean>   
	<!-- mapper批量扫描,从mapper包中扫描出mapper接口,自动创建代理对象并且在spring容器中注册 
	遵循规范:将mapper.java和mapper.xml映射文件名称保持一致,且在一个目录 中
	自动扫描出来的mapper的bean的id为mapper类名(首字母小写)
	-->
  	 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<!-- 指定扫描的包名 
		如果扫描多个包,每个包中间使用半角逗号分隔 -->
		
		<property name="basePackage" value="com.tgb.ncre.mapper"/>
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>		
	</bean>    
</beans></span>



配置文件就建好了,是这样的:


Mybatis运用mapper代码实现和Spring的整合(一)_第6张图片



我们现在创建src文件中,我们的pojo的java兑现个,和mapper代理。

我们先看src的文件目录:


Mybatis运用mapper代码实现和Spring的整合(一)_第7张图片


User类:


<span style="font-size:18px;">package cn.itcast.ssm.po;

import java.io.Serializable;
import java.util.Date;
import java.util.List;


public class User implements Serializable {
	
	//属性名和数据库表的字段对应
	private int id;
	private String username;// 用户姓名
	private String sex;// 性别
	private Date birthday;// 生日
	private String address;// 地址
	
	//用户创建的订单列表
	private List<Orders> ordersList;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", sex=" + sex
				+ ", birthday=" + birthday + ", address=" + address + "]";
	}
	public List<Orders> getOrdersList() {
		return ordersList;
	}
	public void setOrdersList(List<Orders> ordersList) {
		this.ordersList = ordersList;
	}


}
</span>

order类:


<span style="font-size:18px;">package com.tgb.ncre.po;

import java.util.Date;
import java.util.List;

public class Orders {
    private Integer id;

    private Integer userId;

    private String number;

    private Date createtime;

    private String note;
    
    //用户信息
    private User user;
    
    //订单明细
    private List<Orderdetail> orderdetails;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number == null ? null : number.trim();
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note == null ? null : note.trim();
    }

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public List<Orderdetail> getOrderdetails() {
		return orderdetails;
	}

	public void setOrderdetails(List<Orderdetail> orderdetails) {
		this.orderdetails = orderdetails;
	}
}</span>

Orderdetail类:


<span style="font-size:18px;">package com.tgb.ncre.po;

public class Orderdetail {
    private Integer id;

    private Integer ordersId;

    private Integer itemsId;

    private Integer itemsNum;
    
    //明细对应的商品信�?
    private Items items;
    

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getOrdersId() {
        return ordersId;
    }

    public void setOrdersId(Integer ordersId) {
        this.ordersId = ordersId;
    }

    public Integer getItemsId() {
        return itemsId;
    }

    public void setItemsId(Integer itemsId) {
        this.itemsId = itemsId;
    }

    public Integer getItemsNum() {
        return itemsNum;
    }

    public void setItemsNum(Integer itemsNum) {
        this.itemsNum = itemsNum;
    }

	public Items getItems() {
		return items;
	}

	public void setItems(Items items) {
		this.items = items;
	}

	@Override
	public String toString() {
		return "Orderdetail [id=" + id + ", ordersId=" + ordersId
				+ ", itemsId=" + itemsId + ", itemsNum=" + itemsNum + "]";
	}
    
}</span>

Items类:


<span style="font-size:18px;">package com.tgb.ncre.po;

import java.util.Date;

public class Items {
    private Integer id;

    private String name;

    private Float price;

    private String pic;

    private Date createtime;

    private String detail;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name == null ? null : name.trim();
    }

    public Float getPrice() {
        return price;
    }

    public void setPrice(Float price) {
        this.price = price;
    }

    public String getPic() {
        return pic;
    }

    public void setPic(String pic) {
        this.pic = pic == null ? null : pic.trim();
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail == null ? null : detail.trim();
    }
}</span>

然后,我们看com.tgb.ncre.mapper:


Usermapper.java


<span style="font-size:18px;">package com.tgb.ncre.mapper;

import static org.junit.Assert.*;
import com.tgb.ncre.po.User;

public interface UserMapper {
	//根据id查询用户信息
	public User findUserById(int id) throws Exception;

}
</span>

UserMapper.xml:


<span style="font-size:18px;"><?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">

<!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 
注意:使用mapper代理方法开发,namespace有特殊重要的作用,namespace等于mapper接口地址
-->                
<mapper namespace="com.tgb.ncre.mapper.UserMapper">
	<select id="findUserById" parameterType="int" resultType="user">
		SELECT * FROM USER WHERE id=#{value}
	</select>	
</mapper>
</span>

注意:大家一定要这里的两个mapper包中的java类和xml的名称一定要相同才行,否则,在applicationContext.xml中创建SqlSession的时候,扫描不到所有的文件。


好了,现在我们就进行test:


右击我们的UserMapper.java,选择“New”——“Others”:


Mybatis运用mapper代码实现和Spring的整合(一)_第8张图片


Mybatis运用mapper代码实现和Spring的整合(一)_第9张图片


之后,我们写代码:


<span style="font-size:18px;">package com.tgb.ncre.mapper;


import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.tgb.ncre.po.User;

public class UserMapperTest {

	private ApplicationContext applicationContext;
	
	@Before
	public void setUp() throws Exception {
		applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
	}

	@Test
	public void testFindUserById() throws Exception {
		UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper");
		User user = userMapper.findUserById(1);
		System.out.println(user);
	}
}
</span>

Ok了,运行,JunitTest:

Mybatis运用mapper代码实现和Spring的整合(一)_第10张图片


总结:


我们在研究持久层的框架的时候,要从多方面考虑,当我们学习Mybatis的时候,就要想有没有其他的ORM框架,拿出来进行比较。这样,我们才能很好地做技术选型,另外,之后,我们在学习Mybatis的时候,还要想到,如何才能一步一步优化。














你可能感兴趣的:(mybatis,数据库连接池)