您的位置:首页 > 其它

Mybatis的基本使用与企业常用MyBatis开发Dao方式

2015-04-19 00:06 411 查看
MyBatis是一个优秀的“不完全的”ORM框架,因为它需要程序员手动写SQL,而相对于Hibernate来说更加的灵活。它完成了关系模型到对象模型的映射,话不多说,直奔主题。

最近公司有一个项目在使用MyBatis作为开发的ORM,所以顺便就来说一点使用MyBatis开发的方式,为了更为纯净,所以此处做与相关框架的整合(如:Spring):

首先,看一下MyBatis的基本框架:



另外一个图示(来自百度):



说明:
1. SqlMapConfig.xml 文件时MyBatis的核心配置文件,可以配置数据源(链接池)、事务…
2. mapper.xml (名字根据需要来定,只要mapper到SqlMapConfig.xml文件中即可)是MyBatis的一个重要的配置文件,用于对JavaBean(POJO)做映射。
3. SqlSession 会话——面向程序员的接口。用于对数据库的CRUD
4. Executor 执行器,底层实现,SqlSession内部是通过Executor来操作数据库的,Executor是一个底层封装对象,用户看不到。Executor需要Mapped Statement中封装的数据信息来操作数据库(mapper.xml中配置的信息+POJO)
5. Mapped Statement 是MyBatis的一个封装对象,封装了SQL语句、传入的SQL语句的参数,将SQL查询结果映射(即输出)成的Java对象。

下面,通过三个程序来观察:
1. 简单MyBatis的入门程序
2. 使用Dao 与 DaoImpl 的方法的MyBatis程序
3. 使用动态代理对象的MyBatis

三个程序实现,循序渐进,以为基础:
1、简单MyBatis的入门程序
首先建立一个Java工程,导入MyBatis的核心jar包与依赖jar包:

说明:我使用的MyBatis的版本是: mybatis-3.2.8

jar包准备:



lib中为MyBatis的依赖jar包:



导入数据库驱动jar包(使用MySQL)



新建Java Project:MyBatis_Accessor,在项目下新建一个source folder(相当于CLASSPATH): myBatis_config 以及一个folder: lib ,然后将准备好的jar包Paste到lib中去,然后 Add to Build Path



在myBatis_config中添加相关配置文件:
添加一个log4j的properties 文件(如果你不需要日志,可以不配置,同时可以不导入相关jar包):



</pre><p></p><p align="left"> </p><p align="left">log4j. properties 配置代码如下:</p><p align="left"></p><pre name="code" class="java"># Global logging configuration
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


log4j的具体配置如有不明之处,自行Google or Baidu

配置MyBatis的核心配置文件: SqlMapConfig.xml

<?xml version="1.0"encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTDConfig 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 注意:在与Spring整合后,此文件将被废除 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<!-- 配置连接池 -->
<dataSource type="POOLED">
<property name="driver"value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull"/>
<property name="username"value="root" />
<property name="password"value="Jasber0619" />
</dataSource>
</environment>
</environments>

</configuration>


接下来,在数据库test里面建一张表user_ 并插入几条数据:



</pre>现在,创建一个POJO类,在其里面重写了toString()方法以便观察 User:<p></p><p align="left"></p><pre name="code" class="java">package cn.jasberyon.mybatis.pojo;

import java.util.Date;

/**
*
* @author Jasber-Yon
* @date 2015-04-18
*/
public classUser {

private Integer id;
private String username;
private String pwd;
private String sex;
private Date birthday;

public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
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;
}

@Override
public String toString() {
return "User [id="+ id + ", username="+ username+ ", pwd="+ pwd+ ", sex="
+sex+ ", birthday=" + birthday+ "]";
}
}


然后,我们创建一个Mapper配置文件:user_mapper.xml ,即对刚才的POJO类User与user_表进行映射:

<?xml version="1.0"encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTDMapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test">

<select id="findUserByName" parameterType="string"
resultType="cn.jasberyon.mybatis.pojo.User">
SELECT * FROM user_ WHERE username=#{id}
</select>
</mapper>


说明:
1. mapper标签中的 namespace命名空间表示为你的这个mapper命名,在后面测试代码中使用sqlsession.selectOne(“namespace名.select标签中id指定的值”,用户sql查询的参数)
2. select:将select标签内容称为 statement。
3. id:是user_mapper.xml映射文件中唯一标识,statement的id
4. parameterType:指定向SQL(向statement中)中传入参数的类型,注意:string,及参数是MyBatis的方言。
5. #{}:表示一个占位符,{}中的,id表示传入变量名,当传入单个值时,{}中的变量名可以随意。
6. resultType:将SQL查询结果集映射成java对象的类型,注意:其映射成结果集时,不管sql查询的结果是多少条,其类型是代表其中的一条数据的类型,即POJO类型(这在后边的第三种方式中将体现)。

现在,将user_mapper.xml 在 SqlMapConfig.xml 里面进行配置:

<!-- 加载映射文件 -->
<mappers>
<mapper resource="sql_mapper/user_mapper.xml"/>
</mappers>


如图:



好了,现在我们开始编写查询程序(测试) MyBatisTest.java :

package cn.jasberyon.mybatis.test;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import cn.jasberyon.mybatis.pojo.User;

/**
*
* @author Jasber-Yon<br>
* @date 2015-04-18<br>
*/
public classMyBatisTest {

public static void main(String[] args) throws IOException {
//MyBatis的配置文件
Stringresource= "SqlMapConfig.xml";
InputStreaminputStream= Resources.getResourceAsStream(resource);
//创建会话工厂
SqlSessionFactorysqlSessionFactory= newSqlSessionFactoryBuilder().build(inputStream);
//从会话工厂中得到会话
SqlSessionsqlSession= sqlSessionFactory.openSession();
Useruser= sqlSession.selectOne("test.findUserByName","jasber");
System.out.println("-------------------------------------result-----------------------------------");
System.out.println(user);
System.out.println("------------------------------------------------------------------------------");
//关闭session
sqlSession.close();

}

}


说明:
User user =
sqlSession.selectOne("test.findUserByName","jasber");
一句中“test”为user_mapper.xml文件中mapper标签的namespace指定的命名空间名。“findUserByName”是select标签的唯一标识(指定要执行那一条语句),"jasber"就是我们指定的需要传入查询的参数。

看一下,我们现在的开发环境的项目结构:



那么,现在我们来总结一下,使用MyBatis的基本开发步骤:
1. 建立Java项目,导入相关jar包
2. 配置log4j.properties 文件(可忽略)
3. 配置MyBatis的核心配置文件 SqlMapConfig.xml(文件名可自定义)文件,在此文件中配置数据库的连接数据源、事务、数据库连接池等。
4. 创建一个POJO类:User,其类成员属性与数据库中表字段名一致。生成getter和setter方法,如需要可重写toSting()方法。
5. 编写POJO类与数据库表的映射文件user_mapper.xml(文件名可自定义)。
6. 将映射文件user_mapper.xml配置到SqlMapConfig.xml(是被映射,托管给MyBatis)。
7. 编写查询程序(测试)

现在,在已有的基础上,作插入数据(删除、更新同理,详见MyBatis的API)的操作:
① 到user_mapper.xml 映射配置文件中去配置一条插入语句:

<insert id="inserUser"parameterType="cn.jasberyon.mybatis.pojo.User">
<!-- user_ 是对应的表名,设置参数时,#{}内的值要与User中的属性名一致。因为设置了user_表的id自增,所以插入时就不用管它了 -->
<!-- 注意SQL结束时不要加分号 -->
insert into user_(username,pwd, sex, birthday) values(#{username},#{pwd},#{sex},#{birthday})
</insert>


截图:



② 编写插入测试(在原操作代码基础上):



User user2= newUser();
user2.setUsername("MyBatis插入演示");
user2.setPwd("ggggg123");
user2.setSex("1");
user2.setBirthday(new Date());
//插入数据
sqlSession.insert("test.inserUser",user2);
//CUD操作需要事务,提交事务
sqlSession.commit();


运行成功:



查询验证:



好了,我们已经有了一个大体的了解了,现在来演示一下,另外的两种开发方式:企业中使用MyBatis开发Dao方法:
1.使用Dao 与 DaoImpl 的方法的MyBatis程序
2.使用动态代理对象的MyBatis的Dao实现

1.使用Dao 与 DaoImpl 的方法的MyBatis程序
我们需要编写Dao接口以及Dao接口的实现类:DaoImpl。
开发步骤:
① UserDao.java
② UserDaoImpl.java
③ user_mapper.xml 映射文件

① UserDao.java :

package cn.jasberyon.mybatis.dao;

import cn.jasberyon.mybatis.pojo.User;

/**
*
* @author Jasber-Yon<br>
* @date 2015-04-18<br>
*/
public interfaceUserDao {

/**
* 查询一个用户
* @param selectId
* @param username
* @return
* @throws Exception
*/
public UserfindUserByName(String selectId, String username)throwsException;
}


② UserDaoImpl.java :

需要注入SqlSesstionFactory,SqlSesstionFactory生成SqlSesstion,如果是MyBatis和Spring进行整合,那么则让Spring管理(IOC)SqlSesstionFactory,将SqlSesstionFactory在Spring容器中以单例方法存在。因为SqlSesstionFactory创建SqlSesstion的方法是线程安全的。

package cn.jasberyon.mybatis.dao.impl;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import cn.jasberyon.mybatis.dao.UserDao;
import cn.jasberyon.mybatis.pojo.User;

public classUserDaoImpl implements UserDao{

private SqlSessionFactory sqlSessionFactory;

publicUserDaoImpl(SqlSessionFactory sqlSessionFactory) {
// TODO Auto-generated constructor stub
this.sqlSessionFactory= sqlSessionFactory;
}

@Override
public UserfindUserByName(String selectId, String username)throwsException {
// TODO Auto-generated method stub
//从会话工厂得到会话 SqlSession
SqlSessionsession= this.sqlSessionFactory.openSession();
Useruser= session.selectOne(selectId, username);
session.close();
return user;
}

}


③ user_mapper.xml 映射文件

<?xml version="1.0"encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTDMapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test">

<select id="findUserByName" parameterType="string"
resultType="cn.jasberyon.mybatis.pojo.User">
SELECT * FROM user_ WHERE username=#{id}
</select>
</mapper>


测试(使用JUnit,Eclipse EE 已集成):
测试类:UserDaoImplTest

package cn.jasberyon.mybatis.dao.impl.j_unit_test;

import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import cn.jasberyon.mybatis.dao.UserDao;
import cn.jasberyon.mybatis.dao.impl.UserDaoImpl;
import cn.jasberyon.mybatis.pojo.User;

public classUserDaoImplTest {

private SqlSessionFactory sqlSessionFactory;

@Before
public void setUp() throws Exception {
//MyBatis的配置文件
Stringresource= "SqlMapConfig.xml";
InputStreaminputStream= Resources.getResourceAsStream(resource);
//创建会话工厂
this.sqlSessionFactory= newSqlSessionFactoryBuilder().build(inputStream);
}

@Test
public void test() throws Exception {
UserDaouserDao= newUserDaoImpl(sqlSessionFactory);
Useruser= userDao.findUserByName("test.findUserByName","neo");
System.out.println("-------------------------------------result-----------------------------------");
System.out.println(user);
System.out.println("------------------------------------------------------------------------------");
}

@After
public void tearDown() throws Exception {
System.out.println("Testing is Over");
}

}


测试通过:





这个操作的关键点,是要在XxxDaoImpl.java中注入SqlSessionFactory
此时的项目结构(使用到的用红线标注)



下面是另一种方法,也是我推荐的。
2.使用动态代理对象的MyBatis
使用动态代理对象实现,我们只需要编写mapper接口(即Dao接口),不需要再编写其实现类了。
开发步骤:
① userMapper.xml 映射文件
② UserMapper.java (相当于UserDao接口)

① UserMapper.java (相当于UserDao接口)
package cn.jasberyon.mybatis.mapper;

import cn.jasberyon.mybatis.pojo.User;

/**
*
* @author Jasber-Yon<br>
* @date 2015-04-18<br>
*/
public interfaceUserMapper {

public User findUserByName(String suername) throws Exception;
}


② userMapper.xml 映射文件
<?xml version="1.0"encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTDMapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 注意:此时 namespace是mapper接口的全限定名 -->
<mapper namespace="cn.jasberyon.mybatis.mapper.UserMapper">

<select id="findUserByName" parameterType="string"
resultType="cn.jasberyon.mybatis.pojo.User">
SELECT * FROM user_ WHERE username=#{id}
</select>

</mapper>


③ 在SqlMapConfig.xml 文件中加载 userMapper.xml文件

<!-- 加载映射文件 -->
<mappers>
<mapper resource="sql_mapper/userMapper.xml" />
</mappers>


④ 测试:

package cn.jasberyon.mybatis.dao.impl.j_unit_test;

import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import cn.jasberyon.mybatis.mapper.UserMapper;
import cn.jasberyon.mybatis.pojo.User;

public classUserMapperTest {

private SqlSessionFactory sqlSessionFactory;

@Before
public void setUp() throws Exception {
//MyBatis的配置文件
Stringresource= "SqlMapConfig.xml";
InputStreaminputStream= Resources.getResourceAsStream(resource);
//创建会话工厂
this.sqlSessionFactory= newSqlSessionFactoryBuilder().build(inputStream);
}

@After
public void tearDown() throws Exception {
System.out.println("Testing is Over");
}

@Test
public voidtestFindUserByUsername() throws Exception {
//得到 SqlSession
SqlSessionsqlSession= this.sqlSessionFactory.openSession();
//通过 sqlSession得到UserMapper的代理对象
UserMapperuserMapper= sqlSession.getMapper(UserMapper.class);
//调用UserMapper的查询方法
Useruser= userMapper.findUserByName("克雷格");
System.out.println("-------------------------------------result-----------------------------------");
System.out.println(user);
System.out.println("------------------------------------------------------------------------------");
}

}


测试通过:





那么在演示一个查询用户列表的代码:
① 编写(修改一下下,这样该的原因见最后总结)userMapper.xml 文件:

<?xml version="1.0"encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTDMapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 注意:此时 namespace是mapper接口的全限定名 -->
<mapper namespace="cn.jasberyon.mybatis.mapper.UserMapper">

<select id="findUserList" resultType="cn.jasberyon.mybatis.pojo.User">
SELECT * FROM user_
</select>

</mapper>


② 在UserMapper.java中添加一个方法:public List<User> findUserList()throws Exception;
package cn.jasberyon.mybatis.mapper;

import java.util.List;

import cn.jasberyon.mybatis.pojo.User;

/**
*
* @author Jasber-Yon<br>
* @date 2015-04-18<br>
*/
public interfaceUserMapper {

public UserfindUserByName(String username) throwsException;

public List<User>findUserList() throwsException;
}


③ 测试:
package cn.jasberyon.mybatis.dao.impl.j_unit_test;

import java.io.InputStream;
import java.util.List;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import cn.jasberyon.mybatis.mapper.UserMapper;
import cn.jasberyon.mybatis.pojo.User;

public classUserMapperTest {

private SqlSessionFactory sqlSessionFactory;

@Before
public void setUp() throws Exception {
//MyBatis的配置文件
Stringresource= "SqlMapConfig.xml";
InputStreaminputStream= Resources.getResourceAsStream(resource);
//创建会话工厂
this.sqlSessionFactory= newSqlSessionFactoryBuilder().build(inputStream);

}

@Test
public void testFindUserList() throws Exception {
//得到 SqlSession
SqlSessionsqlSession= this.sqlSessionFactory.openSession();
//通过 sqlSession得到UserMapper的代理对象
UserMapperuserMapper= sqlSession.getMapper(UserMapper.class);
//调用UserMapper的查询方法
List<User>list= userMapper.findUserList();
System.out.println("-------------------------------------result-----------------------------------");
System.out.println(list.size());
System.out.println("------------------------------------------------------------------------------");

sqlSession.close();
}

@After
public void tearDown() throws Exception {
System.out.println("Testing is Over");
}

}


测试通过:





再看一下此时的程序结构(红色标识使用的):



最后我们来总结一下:
除了前面的小结之外,动态代理对象,开发规则:

1. userMapper.xml 的 namespace是UserMapper的(全限定)路径
2. userMapper.xml中的statement的id是 UserMapper.java 中的方法名,必须要一致(但是第一种Dao和DaoImpl的方式则不是这样,因为它是在实现方法中限定的,具体请见代码部分)。
3. userMapper.xml中的statement的parameterType的类型和UserMapper.java 中的方法形参类型一致
4. userMapper.xml 中的statement的resultType的类型和UserMapper.java中的方法返回的值的类型一致(如果返回的是多条,List <User> 那么就是User的全限定路径),resultType的类型应该是查询结果一条记录映射的java对象类型。
5. 是返回一个List还是单个对象,由UserMapper接口的方法返回值类型来决定。
6. 如果返回的是一个List集合,生成的代理对象内部调用 sqlSession.selectList() 方法获取一个集合。
7. 如果返回的是单个对象(一个User),生成的代理对象内部调用 sqlSession.selectOne() 方法获取单个对象。

因为时间关系,没有进行详尽的叙述,尚有不足。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: