前言:
相信很多朋友和笔者一样,在开始学习mybatis的时候,看完一遍mybatis相关知识,并没有记住多少,理解深刻就更谈不上,渴求一个简单的demo来测试一下自己到底了解多少,掌握多少以及mybatis到底是怎么玩的,那么机会来了,笔者将自己之前学习过程中练习的demo重新整理了下,并记录总结。
在练习这两种方式之前我们要清楚明白为什么要使用mybatis?先看看原生的数据库连接操作:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TraditionalJdbcConn {
public static void main(String[] args) {
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/name";
String user = "root";
String password = "root";
Connection conn = null;
PreparedStatement pstm = null;
ResultSet rs = null;
try {
Class.forName(driver);// 加载数据库驱动
conn = DriverManager.getConnection(url, user, password);// 得到数据库连接
String sql = "select *from new1 where id=?";
pstm = conn.prepareStatement(sql);// 得到预编译对象
pstm.setInt(1, 19);
rs = pstm.executeQuery();// 得到结果集
while (rs.next()) {
System.out.println(rs.getInt(1) + "\t" + rs.getString(2));
}
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
try {
if (rs != null)
rs.close();
if (pstm != null)
pstm.close();
if (conn != null)
conn.close();
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}
}
上面是传统的Jdbc库连接数据库的基本步骤,可以看出上述代码存在着一下几个问题:
-
数据库连接对象频繁的创建和销毁,存在很大开销。(解决:数据库连接池)
-
sql语句存在硬编码问题,后期维护和升级存在着复杂性。(解决:把语句单独写到一个配置文件中,按照一定规则读取)
-
PreparedStatement设置参数存在着硬编码问题。(解决:配置文件中写)(ps:这里提醒一点,使用statement对象和preparedStatement对象的区别是preparedStatement是预编译对象,对于同一条sql语句,第二次的执行效率远高于第一次,但是如果一条sql语句就执行一次,那么statement执行的速率更快,当然对于同一条语句的多次执行可以使用preparedStatement+批处理,其速度是远超前两者的)
-
结果集resultSet遍历数据的时候存在硬编码问题。(直接将数据映射成Java对象)
知道了为什么要用mybatis后,就直接进入正题,关于原始dao开发和mapper代理开发:
项目结构:(包括原始dao开发和mapper代理开发)
环境准备:
JAR包下载:
POJO类:
public class User {
private int id;
private String content;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "User [id=" + id + ", content=" + content + "]";
}
public User(int id, String content) {
super();
this.id = id;
this.content = content;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
}
Log4j.properties配置文件:(关于log4j的配置,详情参见log4j日志配置)
log4j.rootLogger=debug,console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d %-2p [%c.%M()] - %m%n
mybatis配置文件:
<?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>
<!-- 加载属性文件db.properties -->
<properties resource="db.properties"></properties>
<!-- 和spring整合后,environments将被废除 -->
<environments default="development">
<environment id="development">
<!-- 使用JDBC事务管理 ,事务控制由mybatis管理-->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据库连接池 ,由mybatis管理-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<mapper resource="sqlmap/user.xml"/>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
db.properties文件:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/name
jdbc.username=root
jdbc.password=root
原始dao开发:
开发人员需要编写接口,接口实现类,以及相应的XML配置文件。具体如下:
接口:
import h.l.pojo.User;
public interface UserDao {
public User findUserById(int id) throws Exception;// 根据id查询查询用户
public void insertUser(User user) throws Exception;// 新增用户
public void deleteUser(int id) throws Exception;// 删除用户
public void updateUser(User user) throws Exception;// 更新用户
}
接口实现类:(ps:除了查询,其他的操作都要commit)
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import h.l.pojo.User;
public class UserDaoImpl implements UserDao {
// 向dao实现类中注入SqlSessionFactory
// 这里通过构造函数向实现类中注入SqlSessionFactory
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
// 因为SqlSession是线程不安全的,所有SqlSession对象应该在方法中创建,不能在类中创建
// 根据id查找用户
@Override
public User findUserById(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("test.findUserById", id);
// 释放资源
sqlSession.close();
return user;
}
// 新增用户
@Override
public void insertUser(User user) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("test.insertUser", user);
sqlSession.commit();
sqlSession.close();
}
// 删除用户
@Override
public void deleteUser(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.delete("test.deleteUser", id);
sqlSession.commit();
sqlSession.close();
}
// 更新用户
@Override
public void updateUser(User user) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.update("test.updateUser", user);
sqlSession.commit();
sqlSession.close();
}
}
User.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="test">
<select id="findUserById" parameterType="int"
resultType="h.l.pojo.User">
select * from new1 where id=#{id}
</select>
<insert id="insertUser" parameterType="h.l.pojo.User">
insert into new1(id,content) values(#{id},#{content})
</insert>
<delete id="deleteUser" parameterType="int">
delete from new1 where
id=#{id}
</delete>
<update id="updateUser" parameterType="h.l.pojo.User">
update new1 set content=#{content} where id=#{id}
</update>
</mapper>
测试类:
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.Before;
import org.junit.Test;
import h.l.pojo.User;
public class UserDaoImplTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception {
// 创建sqlSessionFactory
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() throws Exception {
// 创建UserDao
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
// 调用UserDao方法
User user = userDao.findUserById(5);
System.out.println(user);
}
@Test
public void testInsertUser() throws Exception {
// 创建UserDao
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
// 创建一个对象
User user = new User();
user.setContent("5000");
// 调用UserDao方法
userDao.insertUser(user);
}
@Test
public void testDeleteUser() throws Exception {
// 创建UserDao
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
// 调用UserDao方法
userDao.deleteUser(18);
}
@Test
public void testUpdateUser() throws Exception {
// 创建UserDao
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
User user = new User();
user.setContent("江西上饶");
user.setId(19);
userDao.updateUser(user);
}
}
Mapper代理开发:
开发人员只需要编写接口和XML文件即可,mybatis可以自动生成mapper接口实现类代理对象。但是接口的编写需要按照一定的规则:
- 在mapper.xml中namespace等于mapper接口地址。
- mapper.java接口中的方法名和mapper.xml中statement的id一致。
- mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致。
- mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致。
mapper接口:
import h.l.pojo.User;
public interface UserMapper {
public User findUserById(int id) throws Exception;// 根据id查询用户
}
XXXMapper.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="h.l.mapper.UserMapper">
<select id="findUserById" parameterType="int" resultType="h.l.pojo.User">
select *from new1 where id=#{id}
</select>
</mapper>
测试文件:
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.Before;
import org.junit.Test;
import h.l.pojo.User;
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception {
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findUserById(19);
System.out.println(user);
}
}
上述就是原始到开发和mapper代理开发的简单入门,通过上面方法的比较,我们可以发现,程序员可以通过mybatis拜托硬编码的问题,使得后期的维护能够更加方便。关于mybatis的其他知识也会陆陆续续总结,请多关照~
注:以上文章仅是个人学习过程总结,若有不当之处,望不吝赐教。