之所以使用MyBatis这个持久层框架,就是因为MyBatis的Mapper映射,你会发现通过使用Mapper的映射语句,是你减少了95%以上的代码量,当然,这些是相对于同等功能的JDBC语句来说的。
现在,我们将正式开始学习关于Mapper映射的相关内容。
我们将通过一系列的实例来展示Mapper的SQL映射。
先来了解一下关于Mapper的一些元素:
cache:配置给定命名空间的缓存。
cache-ref:从其他命名空间引用缓存配置。
resultMap:最复杂的标签,Mapper的核心标签,更深层次的会在之后讲解。
sql:可以重用的SQL块,减少代码量是非常方便的。
insert、update、delete、select这四个标签恐怕我们不需要说也知道它的作用了吧。
为了更充分的体验MyBatis,我们通过一个连贯的实例来使用这些标签。
我们在前一个测试项目的基础上进行改动:
mybatis-config.xml的配置为:
<?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>
<properties resource="jdbc.properties"></properties>
<settings>
<setting name="cacheEnabled" value="true" />
<setting name="lazyLoadingEnabled" value="true" />
<setting name="multipleResultSetsEnabled" value="true" />
<setting name="useColumnLabel" value="true" />
<setting name="useGeneratedKeys" value="false" />
<setting name="autoMappingBehavior" value="PARTIAL" />
<setting name="defaultExecutorType" value="SIMPLE" />
<setting name="defaultStatementTimeout" value="25" />
<setting name="safeRowBoundsEnabled" value="false" />
<setting name="mapUnderscoreToCamelCase" value="false" />
<setting name="localCacheScope" value="SESSION" />
<setting name="jdbcTypeForNull" value="OTHER" />
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString" />
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
</configuration>
jdbc.properties的配置为:
driver=com.mysql.jdbc.Driver
url=jdbc\:mysql\://localhost\:3306/mybatis2
username=root
password=88308887
因为是测试项目,也不需要一些web之类的,所以上面是一个很普通的java项目,我们现在要做的是一个登录程序,通过这个登录程序,我们可以进行登录操作。而通过这个首页,我们可以添加,修改,查询,删除用户(不包括我们现在使用的这个用户)。而通过这个例子,相信所有需要用到的标签都很容易掌握:
我们先进行数据库的设计,因为我们所有的操作都是可以通过一张用户表进行的。所以,我们可以设计这么一张用户表,它包括用户ID,用户密码,用户姓名。
drop database if exists mybatis2;
create database if not exists mybatis2;
use mybatis2;
drop table if exists user;
create table if not exists user(
userid varchar(100) primary key not null,
username varchar(100) not null,
password varchar(100) not null
);
insert into user values('admin','test','123456');
insert into user values('guest','guest','123456');
insert into user values('costomer','costomer','123456');
将该sql执行,我们mysql中就有了这个表,并且有了一些数据。
之后,我们修改User:
package net.mybatis.model;
import org.apache.ibatis.type.Alias;
@Alias("User")
public class User {
private String userid;
private String username;
private String password;
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return this.getClass().getName() + ":[userid:" + this.userid
+ ",username:" + this.username + ",password:" + this.password
+ "]";
}
}
我们先做登录功能:
登录需要的操作是验证用户名和密码。
在IUserDao接口类中,添加一个验证用户名密码的抽象方法:
package net.mybatis.dao;
import net.mybatis.model.User;
public interface IUserDao {
public boolean login(User user);
}
在UserDaoImpl实现该方法:
package net.mybatis.dao.impl;
import org.apache.ibatis.session.SqlSession;
import net.mybatis.dao.IUserDao;
import net.mybatis.model.User;
public class UserDaoImpl implements IUserDao{
private SqlSession session;
public UserDaoImpl(SqlSession sqlSession){
this.session = sqlSession;
}
@Override
public boolean login(User user) {
user = this.session.selectOne("net.mybatis.mapper.UserMapper.login", user);
System.out.println(user);
if(user.getUsername()!=null&&(!user.getUsername().equals(""))){
return true;
}else{
return false;
}
}
}
在mybatis-config.xml中添加mapper的映射:
<mappers>
<mapper resource="net/mybatis/mapper/user.mapper.xml"/>
</mappers>
在user.mapper.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="net.mybatis.mapper.UserMapper">
<select id="login" parameterType="net.mybatis.model.User" resultType="net.mybatis.model.User">
select * from user where userid=#{userid} and password=#{password}
</select>
</mapper>
修改IuserService这个接口类的实现类:UserServiceImpl:
package net.mybatis.service.impl;
import org.apache.ibatis.session.SqlSession;
import net.mybatis.dao.IUserDao;
import net.mybatis.dao.impl.UserDaoImpl;
import net.mybatis.model.User;
import net.mybatis.service.IUserService;
public class UserServiceImpl implements IUserService{
private IUserDao dao;
public UserServiceImpl(SqlSession sqlSession){
this.dao = new UserDaoImpl(sqlSession);
}
@Override
public boolean login(User user) {
return this.dao.login(user);
}
}
修改UserProxy代理类为:
package net.mybatis.proxy;
import java.io.IOException;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import net.mybatis.manager.SessionManager;
import net.mybatis.model.User;
import net.mybatis.service.IUserService;
import net.mybatis.service.impl.UserServiceImpl;
public class UserProxy {
private SqlSessionFactory sqlSessionFactory;
private SqlSession sqlSession;
private IUserService service;
public UserProxy(){
try {
this.sqlSessionFactory = SessionManager.getFactory();
} catch (IOException e) {
e.printStackTrace();
}
this.sqlSession = this.sqlSessionFactory.openSession();
this.service = new UserServiceImpl(this.sqlSession);
}
public boolean login(String userid,String password) throws Exception{
boolean flag = false;
User user = new User();
user.setUserid(userid);
user.setPassword(password);
try{
flag = this.service.login(user);
}catch(Exception e){
throw e;
}finally{
this.sqlSession.close();
}
return flag;
}
}
修改测试类Test:
package net.mybatis.test;
import java.util.Scanner;
import net.mybatis.proxy.UserProxy;
public class Test {
public static void main(String []args) throws Exception{
Scanner input = new Scanner(System.in);
UserProxy proxy = new UserProxy();
String userid = input.next();
String password = input.next();
System.out.println(proxy.login(userid, password));
}
}
运行JAVA程序:
输入用户名和密码,可以很容易的发现我们的程序运行成功,输入正确,会在控制台中显示true。
通过上述的例子,我们可以大概的了解到MyBatis中的select用法。
下面列出select元素所能包好的一些属性:
属性 | 描述 |
id | 唯一标识符,用来引用该条语句的凭证 |
parameterType | 将会传入参数的完全限定名或别名 |
resultType | 返回的完全限定名或别名。注意:集合的时候返回的是集合包含的类型,而不是集合本身的类型 |
resultMap | 引用外部的Map,可以构造许多复杂的类型,譬如多表查询和限定列查询。注意:resultType和resultMap不能同时使用 |
flushCache | 不管语句什么时候被调用,都会清空缓存 |
useCache | 使语句的结果缓存 |
timeout | 设置驱动的最长等待时间,并抛出时间异常,默认不处理 |
fetchSize | 每次返回结果行数 |
statementType | STATEMENT,PREPARED或CALLBLE中的一种。选择执行语句的使用的是statement,PreparedStatement还是CallableStatemtn? |
resultSetType | FORWARD_ONLY,SCROLL_SENSITIVE,SCROLL_INSENSITIVE |
databaseId | 如果存在配置的dabaseIdProvider,MyBatis将会加载所有匹配当前databaseIdProvider的不存在databaseId和存在databaseId属性的语句。如果发现两个相同的语句,一个存在databaseId,另一个不存在,那么后者将被抛弃。 |
resultOrdered | 这个只是用于嵌套语句,这个属性的值为真的时候: |
通过以下的标签添加功能:
<select id="getAllUsers" parameterType="net.mybatis.model.User" resultType="net.mybatis.model.User" >
select * from user where userid != #{userid}
</select>
<insert id="addUser" parameterType="net.mybatis.model.User">
insert into user(userid,username,password) values(#{userid},#{username},#{password})
</insert>
<delete id="deleteUser" parameterType="net.mybatis.model.User">
delete from user where userid = #{userid}
</delete>
<update id="modifyUser" parameterType="net.mybatis.model.User">
update user set username = #{username}, password = #{password} where userid = #{userid}
</update>
<select id="searchUser" parameterType="string" resultType="net.mybatis.model.User">
select * from user where userid = '${_parameter}' and username = '{_parameter}'
</select>
上述需要说的是以下几条:
1)传入为类的话(这个类必须要是用户自己定义的,而不是
MyBatis提供的基本类型中的譬如Sring的类),参数名必须要和类的属性名保持一致,如果没有一致,那么可能会发生无法找到列的错误。
2)传入为基本类型的时候,需要注意的是,参数只能有一个,多个参数会使得后面的参数无法做变更,而且,这个参数必须为#{_parameter}的形式,不管它参数名为什么。而且,这个基本类型为String的时候,在#{_parameter}的前面要加上单引号,就如:’#{_parameter}’的格式。