原生JDBC程序中問題的總結
例:使用jdbc查詢mysql數據庫中用戶表的記錄
public String searchStudent(String number) throws SQLException{
conn = DBUtil.getConnection();
String sql = "select * from student"+
" where number=?";
PreparedStatement ptmt = conn.prepareStatement(sql);
ptmt.setString(1, number);
ResultSet rs = ptmt.executeQuery();
String str = null;
while(rs.next()){
str = rs.getString("name")+" "+
rs.getString("number")+
" "+rs.getInt("math")
+" "+rs.getInt("chinese");
}
conn.close();
return str;
}
問題總結:
(1)數據庫鏈接,使用時創建,不使用時立即釋放,頻繁鏈接數據庫,造成數據庫資源浪費,影響數據庫性能。
常用的解決方法是通過數據庫連接池來管理數據庫鏈接
(2)將sql語句硬編碼到java代碼當中,如果sql語句修改,需要重寫編譯java代碼,不利於修改維護
設想解決方案:將sql語句配置在xml文件中,
(3)向preparedStatement中設置參數,佔位符與設置的參數值硬編碼在java代碼中,不利於系統維護
設想解決方案:將sql語句和佔位符和設置變量全部配置在xml中
(4)從ResultSet結果集中遍歷結果數據是,存在硬編碼,將獲取表的字段進行硬編碼
設想解決方案:將查詢結果集,自動映射成java對象
於是mybatis因此而生。
mybatis是什麼?
MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名爲MyBatis 。2013年11月遷移到Github。
Mybatis讓程序員的主要精力放在sql上,通過mybatis提供的映射方式,自由靈活的生成(半自動化,大部分需要程序員編寫sql)滿足需求的sql語句
Mybatis可以向preparedStatement中輸入的參數自動進行輸入映射,將查詢結果集靈活的映射成java對象(輸出映射)
mybatis的特點:
-
簡單易學:本身就很小且簡單。沒有任何第三方依賴,最簡單安裝只要兩個jar文件(mysql等數據庫鏈接jar和mybatis的核心jar)+配置幾個sql映射文件易於學習,易於使用,通過文檔和源代碼,可以比較完全的掌握它的設計思路和實現。
-
靈活:mybatis不會對應用程序或者數據庫的現有設計強加任何影響。 sql寫在xml裏,便於統一管理和優化。通過sql基本上可以實現我們不使用數據訪問框架可以實現的所有功能,或許更多。
-
解除sql與程序代碼的耦合:通過提供DAO層,將業務邏輯和數據訪問邏輯分離,使系統的設計更清晰,更易維護,更易單元測試。sql和代碼的分離,提高了可維護性。
-
提供映射標籤,支持對象與數據庫的orm字段關係映射
-
提供對象關係映射標籤,支持對象關係組建維護
-
提供xml標籤,支持編寫動態sql。
mybati框架原理(工作流程):
mybatis功能架構:
我們把Mybatis的功能架構分爲三層:
(1)API接口層:提供給外部使用的接口API,開發人員通過這些本地API來操縱數據庫。接口層一接收到調用請求就會調用數據處理層來完成具體的數據處理。
(2)數據處理層:負責具體的SQL查找、SQL解析、SQL執行和執行結果映射處理等。它主要的目的是根據調用的請求完成一次數據庫操作。
(3)基礎支撐層:負責最基礎的功能支撐,包括連接管理、事務管理、配置加載和緩存處理,這些都是共用的東西,將他們抽取出來作爲最基礎的組件。爲上層的數據處理層提供最基礎的支撐。
入門程序
設置需求爲:
根據用戶的id來查詢用戶的信息
添加用戶
刪除用戶
1.準備:
先導入兩個jar包:mybatis核心jar和mysql的鏈接jar
2.配置log4j
log4j需要再導入log4j的jar
3.項目工程結構
SqlMapConfig.xml是mybatis的全局配置文件,sqlmap包下存放的是mapper.xml的映射文件
4.配置SqlMapConfig.xml
與原生JDBC不同,mybatis將數據庫鏈接部分配置在SqlMapConfig.xml中,在和spring整合之後enviroments標籤將被廢除,該部分了解即可
<?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>
<!-- 和spring整合後environments配置將廢除 -->
<environments default="development">
<environment id="development">
<!-- 使用 jdbc進行事務管理,使用mybatis進行事務控制-->
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.jdbc.mysql.Driver"/>
<property name="url" value="數據庫URL"/>
<property name="username" value="用戶名"/>
<property name="password" value="密碼"/>
</dataSource>
</environment>
</environments>
</configuration>
5.實現java代碼:根據用戶id查詢用戶信息
1)創建pojo類,加入get、set方法
public class User {
//屬性名和數據庫表字段名對應
private int id;
private String username;
private String sex;
private Date birthday;
private String address;
}
2)創建映射文件User.xml
在sqlmap包下創建User.xml(原始ibatis命名),使用mapper代理開發映射文件名稱叫XXXMapper.xml(與代理接口同名同目錄,後面再提), 在映射文件中配置sql語句。(mapper標籤的namespace(命名空間)起到唯一標識 的作用)
<?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">
//namespace命名空間起到唯一標識 的作用
<mapper namespace="test">
<select id="findUserById" parameterType="int" resultType="cn.itcast.po.User">
SELECT * FROM user WHERE id=#{id}
</select>
</mapper>
id(select的屬性):標識映射文件中的sql,將sql語句封裝到mappedStatement對象中,所以將id稱爲statement的id
#{}表示一個佔位符
#{id}:其中id表示輸入的參數,參數名稱就是id,
如果輸入參數是簡單類型,#{}中的參數名可以任意,可以是value或其他名稱
parameterType 指定輸入參數的類型 這裏指定int形
resultType:指定sql輸出的結果類型所映射的Java對象類型,select指定resultTyp
3)在SqlMapConfig.xml中加載映射文件
<mappers>
<mapper resource="sqlmap/User.xml"/>
</mapper>
4)編寫測試程序
根據用戶id查詢用戶信息
public void findUserById() throws IOException {
//mybatis配置文件
String resource = "SqlMapConfig.xml";
//得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
//創建會話工廠,傳入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通過工廠得到sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//通過SqlSession來操作數據庫
//第一個參數:映射文件中statement的id,等於=namespace+"."+statement的id
//第二個參數:指定和映射文件中所匹配的parameterType類型的參數
//sqlSession.selectOne結果是與映射文件中所匹配的resultType類型的對象
User user = sqlSession.selectOne("test.findUserById", 1);
System.out.println(user.getUsername());
//釋放資源
sqlSession.close();
}
sqlSession.selectOne("test.findUserById,1) 這一句中selectOne的兩個參數分別爲對應的映射文件的namespace(命名空間)加上點加上在User.xml中編寫的select標籤的id,第二個參數1則是傳入的id值,調用這個方法後就會去對應的
下面是在Use.xml中的select語句,拿出來對應上面
<select id="findUserById" parameterType="int" resultType="cn.itcast.po.User">
SELECT * FROM user WHERE id=#{id}
</select>
#{}是一個佔位符,等同於"?"的作用,其中#{}在接收簡單類型的數據時可以任意命名比如#{id},#{value}.....等
parameterType和resultType
在映射文件中通過parameterType指定輸入參數的類型,通過resultType來指定輸出結果裏的類型
添加用戶
1) 在User.xml中配置sql語句
<!-- 添加用戶
parameterType:指定輸入參數類型是POJO(包含用戶信息)
#{}中指定pojo的屬性名,接受到pojo對象的屬性值,mybatis通過OGNL來獲取對象的屬性值 -->
<insert id="insertUser" parameterType="cn.itcast.po.User">
insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
value(#{id},#{username},#{birthday},#{sex},#{address})中佔位符的中的變量必須對應user中的屬性名,否則將插入失敗,因爲這裏傳入的是pojo對象,不是簡單的數據類型。
2)測試代碼
@Test
public void insertUser() throws IOException{
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setUsername("linda");
user.setBirthday(new Date());
user.setSex("1");
user.setAddress("河南鄭州");
sqlSession.insert("test.insertUser",user);
//提交事務
sqlSession.commit();
System.out.println(user.getId());
sqlSession.close();
}
這裏提一下,在執行查詢之外的操作時,需要用sqlSession.commit()進行事務的提交,不然也會插入失敗。
mybatis和hibernate本質區別和應用場景
Hibernate:是一個標準的ORM(對象關係映射)框架。入門門檻高,不需要程序員寫sql,sql語句自動生成。對sql語句的優化,修改比較困難
應用場景:適用於需求變化不多的中小型的項目,比如後臺管理系統,erp,orm,oa…..
Mybatis:專注的是sql本身,需要程序員自己編寫sql語句,sql語句的修改和優化就比較方便。Mybatis是一個不完全的ORM框架,雖然程序員自己寫sql,但是mybatis也可以實現映射(輸入、輸出映射)。
應用場景:主要適用於需求變化較多的項目,比如:互聯網項目