二、springmvc和mybatis的整合
此部分较为繁琐
整合方式:把mybatis内的核心对象交由spring来管理。SqlSessionFactory/SqlSession/事务(aop机制实现的事务)
2.1 加入mybatis的jar、mybatis与spring进行集成的jar包、数据库驱动包、数据库连接池驱动包
2.2 创建mybatis的配置文件mybatis-config.xml,里面只保留mybatis的setting和typealieas
2.3 创建spring与mybatis集成的配置文件,spring-mybatis.xml以下bean必须配置:
dao接口的代理对象的自动创建,并交给spring管理。
不交给spring的话,service层依赖的dao对象注入失败。
DataSource(druid的数据库连接池)、
SqlSessionFactory(3个属性注入:dataSource|configLocation|mapperLocations)、
MapperScannerConfig(2个属性注入:basePackage|sqlSessionFactory)、
DataSourceTransactionManager(引入spring-jdbc.jar包)
2.4 把spring-mybatis.xml导入到spring-config.xml中
此处在上一篇spring和springmvc的整合的spring-config.xml中已经配置
spring-mybatis.xml的配置中只保留mybatis的setting和typealieas
<?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>
<!-- mybatis调优的配置 -->
<settings>
<!-- 对全局设置懒加载 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 把积极加载改为消极加载,意思只有调用对应属性才进行二次加载 -->
<setting name="aggressiveLazyLoading" value="false" />
<!-- 启用二级缓存 -->
<setting name="cacheEnabled" value="true" />
<!-- 日志输出到控制台 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!-- 加载log4j配置文件时的一些设置 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<!-- 自动扫描包下的类,把类名作为别名,前提:类名不能重复 -->
<package name="com.javasm" />
</typeAliases>
</configuration>
spring-mybatis.xml的配置较为繁琐,具体类容请看注释
<!-- spring-mybatis配置 -->
<!-- 加载jdbc文件,在src目录下新建jdbc.properties文件 -->
<context:property-placeholder
location="classpath:jdbc.properties" />
<!-- 数据源 -->
<bean id="datasource"
class="com.alibaba.druid.pool.DruidDataSource" init-method="init"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="validationQuery" value="true"></property>
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="${jdbc.initialSize}" />
<property name="minIdle" value="1" />
<property name="maxActive" value="50" />
<!-- 配置获取连接等待超时的时间 -->
<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" />
</bean>
<!-- SqlSessionFactory对象,需要数据源,需要mybatis自身的配置,需要xml映射文件的引入 -->
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 这部分为引用上面部分的DataSource数据库 -->
<property name="dataSource" ref="datasource"></property>
<!-- 嵌入mybatis自身的配置,classpath必须全为小写,此处是全放在src下,具体路径可自己改 -->
<property name="configLocation"
value="classpath:mybatis-config.xml"></property>
<!-- *表示任意的,xml文件位于com.javasm下的任何一个包下的dao包下,文件名是:任意名字.xml -->
<property name="mapperLocations">
<value>classpath:com/javasm/*/dao/*.xml</value>
</property>
<!-- 配置mybatis分页插件 -->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!-- 分页参数合理化 -->
<value>reasonable=true</value>
</property>
</bean>
</array>
</property>
</bean>
<!-- dao接口的代理对象的自动创建,并交给spring管理 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.javasm.*.dao"></property>
<!-- 不要给sqlSessionFactory设置引用的bean,即要value不能ref
否则会使context:property-placeholder标签引入的properties文件失效 -->
<property name="sqlSessionFactoryBeanName"
value="sqlSessionFactory"></property>
</bean>
<!-- 事务 -->
<!-- 事务管理对象,在spring-jdbc -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"></property>
</bean>
<!-- 1.声明式事务管理 :在service层方法上加入@Transactional -->
<tx:annotation-driven proxy-target-class="true"
transaction-manager="transactionManager" />
<!-- 2.配置事务 required则是默认开启事务,supports则是需要在方法上加@Transactional注解-->
<tx:advice id="txadvice"
transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="del*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="upd*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="get*" propagation="SUPPORTS"
read-only="true" />
<tx:method name="query*" propagation="SUPPORTS"
read-only="true" />
<tx:method name="*list" propagation="SUPPORTS"
read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 3.配置切入点,把事务织入到指定切入点 -->
<aop:config>
<aop:advisor advice-ref="txadvice"
pointcut="execution(* com.javasm.*.service.*.*(..))" />
</aop:config>
</beans>
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/0824mybatis
jdbc.username=root
jdbc.password=1234
jdbc.initialSize=2
spring中事务的使用,具体配置在上面已有
controller
@Controller
@RequestMapping("/user")
public class UserController {
@Resource
private IUserService us;
@RequestMapping("/login")
public String login(String username,String password,HttpSession session) {
us.userLogin(username, password);
return "welcome";
}
}
dao
//IUserDao.java
@Repository
public interface IUserDao {
User userLogin(@Param("username")String username,@Param("password")String password);
int adduser(User u);
}
<!-- userMapper.xml -->
<?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.javasm.user.dao.IUserDao">
<select id="userLogin" resultType="User">
select * from user where username=#{username} and password=#{password}
</select>
<update id="adduser" parameterType="User">
insert into user (username,password) values(#{username},#{password})
</update>
</mapper>
service
public interface IUserService {
public void userLogin(String username,String password);
}
@Service
public class UserServiceImpl implements IUserService{
@Resource
private IUserDao ud;
//这里本来是应该adduser,懒得写了,直接用旧的方法,里面换成了ud.adduser
@Transactional
@Override
public void userLogin(String username, String password) {
int a1 = ud.adduser(new User("aa", "bb"));
int a2 = ud.adduser(new User("bb", "aa"));
System.out.println("111");
}
}
日志输出,creating a new sqlsession ,在完成了事务之后才 releasing transactional sqlsession
mabatis的逆向工程
mybatis的自动代码生成
mybatis逆向工程:
eclipse下安装mybatis的代码生成插件
插件名:org.mybatis.generator.eclipse.site-1.3.5.201609070108.zip
下载插件解压,eclipse的dropins目录下建个文件夹,把features和plugins复制进去,重启eclipse
设置完毕后,鼠标右键generatorConfig.xml建立对应的文件
在src下建generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 数据库驱动包位置 -->
<classPathEntry
location="E:\workspace\java_frame\Demo04_ssm\WebContent\WEB-INF\lib\mysql-connector-java-5.1.40-bin.jar" />
<context id="context1" targetRuntime="MyBatis3">
<!-- 去除文档注释 -->
<commentGenerator>
<property name="suppressDate" value="true" />
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!-- 数据库连接信息 -->
<jdbcConnection
connectionURL="jdbc:mysql://localhost:3306/0824mybatis"
driverClass="com.mysql.jdbc.Driver" password="1234" userId="root" />
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- 实体类的生成配置,生成的目标位置 -->
<javaModelGenerator
targetPackage="com.javasm.goods.entity"
targetProject="Demo04_ssm/src" />
<!-- 映射文件的生成配置 -->
<sqlMapGenerator targetPackage="com.javasm.goods.dao"
targetProject="Demo04_ssm/src" />
<!-- 接口的生成配置 -->
<javaClientGenerator
targetPackage="com.javasm.goods.dao" targetProject="Demo04_ssm/src"
type="XMLMAPPER" />
<table tableName="goods" enableCountByExample="false"
enableUpdateByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false" />
</context>
</generatorConfiguration>
鼠标右键generatorConfig.xml,选择generator mybatis/ibatis Artifacts,自动根据数据库中的表信息和配置信息生成对应的dao包和entity包,dao包下有GoodsMapper.java和GoodsMapper.xml,实体类中有Goods.java
GoodsMapper.java
public interface GoodsMapper {
int deleteByPrimaryKey(Integer gid);
int insert(Goods record);
int insertSelective(Goods record);
Goods selectByPrimaryKey(Integer gid);
int updateByPrimaryKeySelective(Goods record);
int updateByPrimaryKey(Goods record);
List<Goods> getAllGoods();
}
GoodsMapper.xml
<?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.javasm.goods.dao.GoodsMapper">
<resultMap id="BaseResultMap"
type="com.javasm.goods.entity.Goods">
<id column="gid" jdbcType="INTEGER" property="gid" />
<result column="gname" jdbcType="VARCHAR" property="gname" />
<result column="gprice" jdbcType="DOUBLE" property="gprice" />
<result column="descs" jdbcType="VARCHAR" property="descs" />
</resultMap>
<sql id="Base_Column_List">
gid, gname, gprice, descs
</sql>
<select id="selectByPrimaryKey"
parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from goods
where gid = #{gid,jdbcType=INTEGER}
</select>
<select id="getAllGoods" resultType="com.javasm.goods.entity.Goods">
select * from goods
</select>
<delete id="deleteByPrimaryKey"
parameterType="java.lang.Integer">
delete from goods
where gid = #{gid,jdbcType=INTEGER}
</delete>
<insert id="insert"
parameterType="com.javasm.goods.entity.Goods">
insert into goods (gid, gname, gprice,
descs)
values
(#{gid,jdbcType=INTEGER}, #{gname,jdbcType=VARCHAR},
#{gprice,jdbcType=DOUBLE},
#{descs,jdbcType=VARCHAR})
</insert>
<insert id="insertSelective"
parameterType="com.javasm.goods.entity.Goods">
insert into goods
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="gid != null">
gid,
</if>
<if test="gname != null">
gname,
</if>
<if test="gprice != null">
gprice,
</if>
<if test="descs != null">
descs,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="gid != null">
#{gid,jdbcType=INTEGER},
</if>
<if test="gname != null">
#{gname,jdbcType=VARCHAR},
</if>
<if test="gprice != null">
#{gprice,jdbcType=DOUBLE},
</if>
<if test="descs != null">
#{descs,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective"
parameterType="com.javasm.goods.entity.Goods">
update goods
<set>
<if test="gname != null">
gname = #{gname,jdbcType=VARCHAR},
</if>
<if test="gprice != null">
gprice = #{gprice,jdbcType=DOUBLE},
</if>
<if test="descs != null">
descs = #{descs,jdbcType=VARCHAR},
</if>
</set>
where gid = #{gid,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey"
parameterType="com.javasm.goods.entity.Goods">
update goods
set gname = #{gname,jdbcType=VARCHAR},
gprice = #{gprice,jdbcType=DOUBLE},
descs = #{descs,jdbcType=VARCHAR}
where gid = #{gid,jdbcType=INTEGER}
</update>
</mapper>
Goods.java
public class Goods {
private Integer gid;
private String gname;
private Double gprice;
private String descs;
public Integer getGid() {
return gid;
}
public void setGid(Integer gid) {
this.gid = gid;
}
public String getGname() {
return gname;
}
public void setGname(String gname) {
this.gname = gname;
}
public Double getGprice() {
return gprice;
}
public void setGprice(Double gprice) {
this.gprice = gprice;
}
public String getDescs() {
return descs;
}
public void setDescs(String descs) {
this.descs = descs;
}
}
代码均是自动生成~
mybatis分页插件
2个jar包,jsqlparser.jar和PageHelper.jar
jsqlparser.jar
分页对象的jar,PageHelper、PageInfo
PageHelper.jar
sql解析的jar,对我们映射文件的需要分页的查询语句,自动追加limit 1,3,自动生成一个查询总记录数的sql语句
PageInfo对象中几个常用属性:
list 结果集
pageNum 当前页码
pageSize 每页记录数
total 总记录数
pages 总页数
prePage 上一页页码
nextPage 下一页页码
首先需要在springmxc-mybatis.xml中的SqlSessionFactory下配置标签,具体的上面已有
<!-- 配置mybatis分页插件 -->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!-- 分页参数合理化 -->
<value>reasonable=true</value>
</property>
</bean>
</array>
</property>
controller
@Controller
@RequestMapping("/goods")
public class GoodsController {
@Resource
private IGoodsService gs;
//方法是获取数据库中所有的Goods
//@RequestParam(value="pagenum",defaultValue="1")
//这是给int pagenum指定参数的注解,设置默认值为1,即从第一个开始查询
//参数中设置一个Model,用来向页面发送信息
@RequestMapping("/demo")
public String getAllGoods(@RequestParam(value="pagenum",defaultValue="1")int pagenum,Model m) {
//设置开始的页数pagenum,每一页查询3个,pagenum需要全为小写
PageHelper.startPage(pagenum, 3);
List<Goods> allGoods = gs.getAllGoods();
//拿到返回的Goods的list,作为PageInfo<>的结果集
PageInfo<Goods> page = new PageInfo<>(allGoods);
System.out.println(page);
//给Model添加Attribute
m.addAttribute("gl", page);
return "demo";
}
}
页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:forEach items="${gl.list}" var="g">
${g.gname }----${g.descs } <Br>
</c:forEach>
<div>
<a href="demo?pagenum=1" >首页</a>
<a href="demo?pagenum=${gl.prePage }" >上页</a>
<a href="demo?pagenum=${gl.nextPage }" >下页</a>
<a href="demo?pagenum=${gl.pages }" >尾页</a>
${gl.pageNum }/${gl.pages }
</div>
</body>
</html>