1. 程式人生 > >mybatis入門之原始dao開發與mapper代理開發

mybatis入門之原始dao開發與mapper代理開發

前言:

相信很多朋友和筆者一樣,在開始學習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的其他知識也會陸陸續續總結,請多關照~


注:以上文章僅是個人學習過程總結,若有不當之處,望不吝賜教。