百度百科:
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)
前面使用的是jdbcTemplate,不够方便,现在我们把他和mybatis整合
需要的jar
一个用来和spring无缝对接,一个是mybatis的核心包
首先需要增加配置文件
<!-- myBatis文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 自动扫描映射文件 -->
<property name="mapperLocations">
<array>
<value>classpath:mapper/*.xml</value>
</array>
</property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.bbs.dao.mapper" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
这一段是固定格式的哈, dataSource是我们的数据源也就是连接数据库用的,之前设置过来的
使用mybatis一般我们需要两个文件,一个就是mapper映射接口,一个就是xml,里面写的sql
说白了就是mybaits把xml中的sql,处理后,可以通过mapper中的接口调用
注意,接口名字就是xml中的id
所以说到这也可以明白了,上面的自动扫描映射文件的xml就是我们写sql的地方
下面的就是mapper接口对应的包,它里面写的都是mapper接口
所以你要用的话,copy过去,修改一下这两个位置就好了
还有就是要知道,对照eclipse的话,创建项目后src就是这个classpath的哈
具体的请仔细学习mybaits
配置文件可以单独配置,也可以直接写道ApplicationContext,xml的,现在我们就是写在一起的
然后就是在项目里面把文件新建一下
新建一个包,com.bbs.dao.mapper 里面新建两个接口
src下面新建一个文件夹,mapper,里面新建两个配置文件
如下图所示
配置文件设置好了之后,文件也都创建好了
就是要写sql以及接口了
sql自然是要按照人家的规则来写了
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.bbs.dao.mapper.UserMapper">
<select id="getMatchCount" parameterType="com.bbs.domain.User"
resultType="java.lang.Integer">
SELECT count(*)
FROM
t_user
WHERE
user_name=#{userName}
and password=#{password}
</select>
<select id="findUserByUserName" parameterType="com.bbs.domain.User"
resultType="com.bbs.domain.User">
SELECT
t_user.user_id as userId,
t_user.user_name as userName,
t_user.credits as credits,
t_user.password as password,
t_user.last_ip as lastIp,
t_user.last_visit as lastVisit
FROM
t_user
WHERE
user_name=#{userName}
</select>
<update id="updateLoginInfo" parameterType="com.bbs.domain.User">
UPDATE t_user
<set>
<if test="lastVisit !=null">
last_visit = #{lastVisit},
</if>
<if test="lastIp !=null and lastIp !=‘‘">
last_ip = #{lastIp},
</if>
<if test="credits !=null and credits !=‘‘">
credits = #{credits},
</if>
</set>
where user_id=#{userId}
</update>
<insert id="insertUser" parameterType="com.bbs.domain.User">
insert into t_user(
user_name,
credits,
password,
last_ip,
last_visit
)
values(
#{userName},
#{credits},
#{password},
#{lastIp},
#{lastVisit}
)
</insert>
<update id="updateUserInfo" parameterType="com.bbs.domain.User">
UPDATE t_user
<set>
<if test="lastVisit !=null">
last_visit = #{lastVisit},
</if>
<if test="lastIp !=null and lastIp !=‘‘">
last_ip = #{lastIp},
</if>
<if test="credits !=null and credits !=‘‘">
credits = #{credits},
</if>
</set>
where user_id=#{userId}
</update>
</mapper>
LoginLogMapper.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.bbs.dao.mapper.LoginLogMapper">
<insert id="insertLoginLog" parameterType="com.bbs.domain.LoginLog">
insert into t_login_log(
user_id,
ip,
login_datetime
)
values(
#{userId},
#{ip},
#{loginDate}
)
</insert>
</mapper>
说到这,说点常见的问题
1,数据库中的字段名字和java代码中的名字,要注意,如果不一样记得select的时候要as一下为代码中的,不然人家怎么知道如何映射
2,insert,update的时候,前面的是数据库的,后面的是java代码的
3.使用if判断入参条件的时候要小心
比如此处的lastVisit是数据库中datetime格式的,java代码中是Date(util)类型的,使用if的时候这个lastvisit就不能跟下面lastIp似得有一个什么and lastIp!=‘‘,因为是一个时间对象嘛,比较的时候当做字符串了,你要是用了就会报错,
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
..........
就是sql嘛,注释也都没写,毕竟是简单的例子
接着是跟xml映射的接口
UserMapper.java
package com.bbs.dao.mapper;
import com.bbs.domain.User;
public interface UserMapper {
public Integer getMatchCount(User user);
public User findUserByUserName(User user);
public void updateLoginInfo(User user);
public void insertUser(User user);
public void updateUserInfo(User user);
}
LoginLogMapper.java
package com.bbs.dao.mapper;
import com.bbs.domain.LoginLog;
public interface LoginLogMapper {
public void insertLoginLog(LoginLog loginLog);
}
这样子就可以通过mapper接口执行sql了
之前的时候我们的接口写的不怎么规范,我们现在规范一下
把原来的userService.java拆分下
拆解成
UserService.java
LoginLogService.java
这两个接口
实际使用的时候,使用他们的实现类
面向接口的编程嘛,好处自行百度
UserService.java
package com.bbs.service;
import com.bbs.domain.User;
public interface UserService {
public Boolean hasMatchUser(User user);
public User findUserByUserName(User user);
public void loginSucess(User user);
public void insertUser(User user);
public void UpdateUser(User user);
}
UserServiceImpl.java
package com.bbs.service;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bbs.dao.mapper.UserMapper;
import com.bbs.domain.LoginLog;
import com.bbs.domain.User;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private LoginLogService loginLogService;
@Override
public Boolean hasMatchUser(User user) {
Integer matchCount = userMapper.getMatchCount(user);
if(matchCount > 0){
return true;
}else{
return false;
}
}
@Override
public User findUserByUserName(User user) {
return userMapper.findUserByUserName(user);
}
@Override
public void loginSucess(User user) {
user.setCredits(5+user.getCredits());
user.setLastVisit(new Date());
LoginLog loginLog = new LoginLog();
loginLog.setUserId(user.getUserId());
loginLog.setIp(user.getLastIp());
loginLog.setLoginDate(new Date());
userMapper.updateLoginInfo(user);
loginLogService.insertLoginLog(loginLog);
}
@Override
public void insertUser(User user) {
userMapper.insertUser(user);
}
@Override
public void UpdateUser(User user) {
userMapper.updateUserInfo(user);
}
}
LoginLogService.java
package com.bbs.service;
import com.bbs.domain.LoginLog;
public interface LoginLogService {
public void insertLoginLog(LoginLog loginLog);
}
LoginLogServiceImpl.java
package com.bbs.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bbs.dao.mapper.LoginLogMapper;
import com.bbs.domain.LoginLog;
@Service
public class LoginLogServiceImpl implements LoginLogService {
@Autowired
private LoginLogMapper loginLogMapper;
@Override
public void insertLoginLog(LoginLog loginLog) {
loginLogMapper.insertLoginLog(loginLog);
}
}
这样子接口和他的实现类都写好了
要注意到,@service 和@Autowired哈
那么到现在为止,项目的逻辑就是这样子的了
spring+mybaits
配置文件中配置了数据库等信息,配置了需要自动扫描的一些包,要扫描包中的注解嘛,重要的还整合了mybatis
通过mybatis来操作数据库,mapper来直接调用
改造成了面向接口的编程
通过userService和LoginLogService来调用,实际上执行的还是实现类嘛
实现类通过组合调用mapper提供的接口,来操作数据库,来操作数据
项目的改造完成了
测试也要修改一下了..
package test.bbs.service;
import static org.junit.Assert.*;
import java.util.Date;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.bbs.domain.User;
import com.bbs.service.UserService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/applicationContext.xml"})
public class TestUserService {
@Autowired
private UserService userService;
@Test
public void hasMAtchUser(){
User user1 = new User();
User user2 = new User();
user1.setUserName("admin");
user1.setPassword("123456");
user2.setUserName("admin");
user2.setPassword("11111");
boolean b1 = userService.hasMatchUser(user1);
//boolean b2 = userService.hasMatchUser(user2);
assertTrue(b1);
//assertTrue(b2);
}
@Test
public void findUserByUserName(){
User user = new User();
user.setUserName("admin");
User user1 = userService.findUserByUserName(user);
System.out.println(user1.getUserName());
assertEquals(user1.getUserName(),"admin");
}
@Test
public void loginSucess(){
User user = new User();
user.setUserName("admin");
user= userService.findUserByUserName(user);
userService.loginSucess(user);
}
@Test
public void insertUser(){
User user = new User();
user.setUserName("user1");
user.setPassword("123456");
user.setCredits(0);
user.setLastIp("255.255.255.255");
user.setLastVisit(new Date(0) );
userService.insertUser(user);
}
@Test
public void updateUserInfo(){
User user = new User();
user.setUserId(2);
user.setLastVisit(new Date() );
user.setCredits(5+user.getCredits());
userService.UpdateUser(user);
}
}
目测都执行成功了哈
以上就是spring+mybatis的一个基本项目(后台)