最近开发任务挺紧,写dao层的同事还出差了,只能自己动手了。为了学习mybatis,写了一个demo程序,应该算是对mybatis的基本配置项有了些了解。直接上代码。。
User类如下:
package name.mathyrs.domain;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private int id;
private String userName;
private String password;
private Date birthday;
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 getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String toString() {
return userName + " : " + password + " : " + birthday.toString();
}
}
建表sql如下:
CREATE TABLE User (
id INTEGER not null primary key autoincrement,
userName varchar not null,
password varchar not null,
birthday Datetime not null
);
注:工程中我使用的是sqlite数据库,不支持TIMESTAMP类型。但是mybatis已提供的typeHandlers类型处理器中不包含java.util.Date和Datetime之间的转换功能,包含java.util.Date与TIMESTAMP类型之间的转换。而sqlite数据库本身的类型亲和性可以将TIMESTAMP类型的数据存储在Datetime类型的列中。因此我将数据表中的birthday属性类型设置为DATETIME。
mybatis配置文件:
<configuration>
<settings>
<setting name="cacheEnabled" value="false"/>
settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="org.sqlite.JDBC" />
<property name="url" value="jdbc:sqlite::resource:sqlite3/mathyrs.db" />
<property name="username" value="" />
<property name="password" value="" />
dataSource>
environment>
environments>
<mappers>
<mapper resource="name/mathyrs/dao/UserDao.xml" />
mappers>
configuration>
注意:configuration元素中的标签项必须按照下面顺序设置,否则程序会报错。
(properties>settings>typeAliases>typeHandlers>objectFactory>objectWrapperFactory>plugins>environments>mappers)
IUserDao接口代码:
package name.mathyrs.dao;
import name.mathyrs.domain.User;
public interface IUserDao {
void addUser(User user);
User selectUserbyName(String userName);
User selectUser(String userName, String password);
void updateUser(User user);
void deleteUser(User user);
}
UserDao.xml代码如下:
<mapper namespace="name.mathyrs.dao.IUserDao" >
<select id="selectUserbyName" resultType="name.mathyrs.domain.User" parameterType="java.lang.String" >
select *
from User
where userName = #{userName,jdbcType=VARCHAR}
select>
<select id="selectUser" resultType="name.mathyrs.domain.User" >
select *
from User
where userName = #{0,jdbcType=VARCHAR} AND password = #{1,jdbcType=VARCHAR}
select>
<delete id="deleteUser" parameterType="name.mathyrs.domain.User" >
delete from user
where id = #{id,jdbcType=INTEGER}
delete>
<insert id="addUser" parameterType="name.mathyrs.domain.User" >
insert into user (userName, password, birthday)
values (#{userName,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{birthday,jdbcType=TIMESTAMP}
)
insert>
<update id="updateUser" parameterType="name.mathyrs.domain.User" >
update user
set userName = #{userName,jdbcType=VARCHAR},
password = #{password,jdbcType=VARCHAR},
birthday = #{birthday,jdbcType=TIMESTAMP}
where id = #{id,jdbcType=INTEGER}
update>
mapper>
如果数据表属性名与领域对象的对应属性名相同,那么可以利用mybatis的自动封装功能将查询结果封装为领域对象。
如果数据表属性名与领域对象的对应属性名不同,也可以通过在sql中设置与领域对象属性名相同的别名。
以上两种情况在select标签中使用resultType即可。
如果涉及到复杂查询,如关联表查询。或者领域对象的属性并不与查询结果属性一一对应时,需定义resultMap。
复杂情况将在以后讨论。
先对插入和查询进行测试,代码如下:
DaoTest.java
package name.mathyrs.mybatis;
import static org.junit.Assert.*;
import java.io.Reader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
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.Test;
import name.mathyrs.dao.IUserDao;
import name.mathyrs.domain.User;
public class DaoTest {
private static SqlSessionFactory sqlSessionFactory;
private static Reader reader;
static{
try{
reader = Resources.getResourceAsReader("config/mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}catch(Exception e){
e.printStackTrace();
}
}
public static SqlSessionFactory getSession(){
return sqlSessionFactory;
}
@Test
public void test() {
SqlSession session = sqlSessionFactory.openSession();
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date birthday = sdf.parse("1990-03-01 18:30:00");
IUserDao userDao = session.getMapper(IUserDao.class);
User user = new User();
user.setUserName("mathyrs");
user.setPassword("123");
user.setBirthday(birthday);
userDao.addUser(user);
//插入操作必须提交
session.commit();
User user1 = userDao.selectUserbyName("mathyrs");
assertEquals(user1.getPassword(), user.getPassword());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
session.close();
}
}
}
在sqlSession中,实际上调用的是transactionManager来完成的具体的事务提交和回滚操作。因此,执行过修改数据库操作的命令之后需调用commit()方法才能将事务提交到数据库中。
maven工程配置文件pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>name.mathyrs.mybatisgroupId>
<artifactId>mybatisDemoartifactId>
<packaging>jarpackaging>
<version>1.0-SNAPSHOTversion>
<name>mybatisDemoname>
<url>http://maven.apache.orgurl>
<properties>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
properties>
<build>
<resources>
<resource>
<directory>src/main/resourcesdirectory>
resource>
resources>
build>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.8.1version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.1.1version>
dependency>
<dependency>
<groupId>org.xerialgroupId>
<artifactId>sqlite-jdbcartifactId>
<version>3.8.11.2version>
dependency>
dependencies>
project>
在DaoTest.java中,如果去掉session.commit();操作,测试代码仍然可以成功运行(当然,数据库中并未插入数据)。起初我以为使mybatis的缓存的原因,但是即使清理掉一级缓存,关闭二级缓存的情况下测试仍然能够成功。即将DaoTest.java修改如下仍然能够测试通过:
package name.mathyrs.mybatis;
import static org.junit.Assert.*;
import java.io.Reader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
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.Test;
import name.mathyrs.dao.IUserDao;
import name.mathyrs.domain.User;
public class DaoTest {
private static SqlSessionFactory sqlSessionFactory;
private static Reader reader;
static{
try{
reader = Resources.getResourceAsReader("config/mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}catch(Exception e){
e.printStackTrace();
}
}
public static SqlSessionFactory getSession(){
return sqlSessionFactory;
}
@Test
public void test() {
SqlSession session = sqlSessionFactory.openSession();
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date birthday = sdf.parse("1990-03-01 18:30:00");
IUserDao userDao = session.getMapper(IUserDao.class);
User user = new User();
user.setUserName("mathyrs");
user.setPassword("123");
user.setBirthday(birthday);
userDao.addUser(user);
//未提交事务
session.clearCache();
User user1 = userDao.selectUserbyName("mathyrs");
assertEquals(user1.getPassword(), user.getPassword());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
session.close();
}
}
}
后来了解到这是数据库事务的特性,具体细节尚待深入学习。
道行尚浅,欢迎拍砖!!