爲何會產生 Hibernate Mybatis 這類的dao層框架java
傳統的jdbc 雖然執行速度很快,可是開發效率很低,隨着面向對象開發的設計思想,在面向對象編程中 將對象 進行持久化,存入關係型的數據庫時,因爲關係型數據庫的設計思想是數學思惟,在持久化時,必需要對象拆分各個屬性值,纔可存入數據庫;傳統的jdbc 持久化時 對象持久化時 ,取出對象的一個一個屬性,過去繁瑣,而且不便於維護,而市場上的面向對象的數據庫還並不成熟,因此爲了調節面向對象設計的開發思想與落後的關係型數據庫之間持久化時繁瑣的問題,產生了一種新的設計規範mysql
ORM (Object Relation Mapping) 程序員
Spring對數據庫的操做在jdbc上面作了深層次的封裝,也就是工具類 jdbcTemplatespring
先看一下jdbcTemplate的大體流程圖sql
做用:數據庫
1: 它提供了AOP式的事務管理apache
AOP式的事物管理:在之前的事務管理是要融合在邏輯代碼中的,在邏輯代碼中決定事務是否提交或者回滾,這樣很容易形成代碼難以維護,代碼冗餘
可是使用spring的聲明式事務後,只須要在數據庫處理方法上註解事務,就能夠對操做進行管理,事務的設置和邏輯代碼分開,容易維護。編程
<!-- 定義template組件 --> <bean id="template" class="org.springframework.jdbc.core.JdbcTemplate"> <!-- 注入鏈接信息 --> <property name="dataSource" ref="bonecp"> </property> </bean>
com.alibaba.druid.pool.DruidDataSource
<!-- DataSource 數據源 鏈接池 存儲管理大量的連接 流行的 dbcp c3p0,proxool --> <!-- 數據源配置, 使用 BoneCP 數據庫鏈接池 --> <bean id="bonecp" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!-- 數據源驅動類可不寫,Druid默認會自動根據URL識別DriverClass --> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <!-- 基本屬性 url、user、password --> <property name="url" value="jdbc:mysql://localhost:3306/medicine?useUnicode=true&characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="root" /> <!-- 配置獲取鏈接等待超時的時間 --> <property name="maxWait" value="60000" /> <!-- 配置間隔多久才進行一次檢測,檢測須要關閉的空閒鏈接,單位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 配置一個鏈接在池中最小生存的時間,單位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="300000" /> <property name="testWhileIdle" value="true" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <!-- 配置監控統計攔截的filters --> <property name="filters" value="stat" /> </bean>
下一部是根據表 編寫實體類緩存
實體類session
package com.mxp.jdbc.entity; import java.io.Serializable; public class User implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String id; private String userName; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
還須要根據實體類寫一個rowmapper
注意這裏要繼承
org.springframework.jdbc.core.RowMapper,而後重寫maprow方法
package com.mxp.jdbc.entity; import java.sql.ResultSet; import java.sql.SQLException; import org.springframework.jdbc.core.RowMapper; /** * 每一個實體類都有這個封裝組件 * 將User記錄封裝成 User對象 * @author Administrator * */ public class UserRowMapper implements RowMapper<User>{ /** * arg1:第幾行記錄 */ @Override public User mapRow(ResultSet arg0, int arg1) throws SQLException { User user = new User(); user.setId(arg0.getString("id")); user.setUserName(arg0.getString("user_name")); return user; } }
下面能夠編寫dao了 編寫以前咱們在spring的主配置文件中要把spring的掃描組件啓動
<!-- spring組件掃描 --> <context:component-scan base-package="com.mxp"> </context:component-scan>
dao
package com.mxp.jdbc.dao; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import com.mxp.jdbc.entity.User; import com.mxp.jdbc.entity.UserRowMapper; @Repository public class ItinerantDAO { @Autowired private JdbcTemplate template;//注入的方式 public void save(User user){ String sql = "insert into test_user" + "(id,user_name) values (?,?)"; Object[] params = { user.getId(),user.getUserName() }; template.update(sql, params); } public List<User> findAll(){ String sql ="select * from test_user"; UserRowMapper rowMapper = new UserRowMapper(); List<User> list = template.query(sql, rowMapper); return list; } }
那如今就能夠寫測試方法
package test; import java.io.IOException; import java.util.List; import org.apache.ibatis.session.SqlSession; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.mxp.ControllerQW; import com.mxp.jdbc.dao.ItinerantDAO; import com.mxp.jdbc.entity.User; import com.mxp.mybatis.util.MybatisUtil; public class Test { public static void main(String[] args) {
//spring的主配置文件名 String conf = "spring-context.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(conf); ItinerantDAO dao = ac.getBean("itinerantDAO",ItinerantDAO.class); User user = new User(); user.setId("1455"); user.setUserName("文森特"); dao.save(user); } @org.junit.Test public void test(){
String conf = "spring-context.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(conf); ItinerantDAO dao = ac.getBean("itinerantDAO",ItinerantDAO.class); List<User> list = dao.findAll(); for(User u:list){ System.out.println(u.getUserName()); } } }
這jdbcTemplate 見的次數不多 至今爲止 尚未見到用的
Mybatis
原來在咱們使用jdbc的問題
1 對數據庫的鏈接 使用時就建立鏈接,不使用就當即釋放,對數據庫進行頻繁鏈接開啓和關閉,形成數據庫的資源浪費,影響數據庫的性能;
解決辦法:使用數據庫鏈接池,管理數據庫的鏈接。
2 將sql語句硬編碼到java代碼中,若是sql語句修改,須要從新編譯java代碼,不利於系統維護,
解決辦法:把sql語句I定義到xml配置文件裏;
3 在向statement中設置參數,對站位符位置和設置參數數值,硬編碼到java代碼中,
4 從result結果集中遍歷數據時,存在硬編碼,講獲取表的字段名硬編碼,不便於維護,
講結果集 自動映射成java對象
mybatis的架構
是一個持久層的項目,是阿帕奇的頂級項目,
經過 mybatis提供的映射方式,半自動的生成sql,大部分仍是須要程序員編寫sql
核心:輸入映射:能夠將statement中的輸入參數自動輸入到映射 經過ongl表達式,將查詢的結果集靈活映射成爲java對象(輸出映射)
一、 mybatis配置
SqlMapConfig.xml,此文件做爲mybatis的全局配置文件,配置了mybatis的運行環境等信息。
mapper.xml文件即sql映射文件,文件中配置了操做數據庫的sql語句。此文件須要在SqlMapConfig.xml中加載。
二、 經過mybatis環境等配置信息構造SqlSessionFactory即會話工廠
三、 由會話工廠建立sqlSession即會話,操做數據庫須要經過sqlSession進行。
四、 mybatis底層自定義了Executor執行器接口操做數據庫,Executor接口有兩個實現,一個是基本執行器、一個是緩存執行器。
五、 Mapped Statement也是mybatis一個底層封裝對象,它包裝了mybatis配置信息及sql映射信息等。mapper.xml文件中一個sql對應一個Mapped Statement對象,sql的id便是Mapped statement的id。
六、 Mapped Statement對sql執行輸入參數進行定義,包括HashMap、基本類型、pojo,Executor經過 Mapped Statement在執行sql前將輸入的java對象映射至sql中,輸入參數映射就是jdbc編程中對preparedStatement設置參數。
七、 Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本類型、pojo,Executor經過 Mapped Statement在執行sql後將輸出結果映射至java對象中,輸出結果映射過程至關於jdbc編程中對結果的解析處理過程。
<?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> <environments default="environment"> <environment id="environment"> <transactionManager type="JDBC" /> <!-- mybatis 自帶鏈接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/medicine?useUnicode=true&characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> <!-- 定義sqlMapper文件位置的 --> <mappers> <mapper resource="com/mxp/mybatis/entity/UserMapper.xml" /> </mappers> </configuration>
第二步 實體類及其sqlmap映射文件
package com.mxp.mybatis.entity; import java.io.Serializable; public class User implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String id; private String userName; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
<?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="com.mxp.mybatis.entity.UserMapper"> <sql id="userColumns"> a.id AS "id", a.user_name AS "userName" </sql> <select id="findAll" resultType="com.mxp.mybatis.entity.User" > SELECT <include refid="userColumns"/> FROM test_user a </select> <select id="findLikeName" parameterType="string" resultType="com.mxp.mybatis.entity.User" > SELECT <include refid="userColumns"/> FROM test_user a <where> a.user_name like #{name} </where> </select> </mapper>
第三部 獲取sqlsession
package com.mxp.mybatis.util; import java.io.InputStream; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MybatisUtil { public static SqlSession getInsertance(){ SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); //這是讀取文件後 造成一個輸入流 漲知識了 //Test 其實就是一個類型 寫本身的什麼類型都行 主要是爲了獲取到getClassLoader().getResourceAsStream InputStream reader = MybatisUtil.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml"); //獲取sqlsessionFactory SqlSessionFactory factory = builder.build(reader); //獲取session SqlSession session = factory.openSession(); return session; } }
第四部 寫測試類
package test; import java.io.IOException; import java.util.List; import org.apache.ibatis.session.SqlSession; import com.mxp.mybatis.util.MybatisUtil; public class Test { @org.junit.Test public void getSqllSession() throws IOException{ SqlSession session = MybatisUtil.getInsertance(); System.out.println("獲取session"); session.close(); } @org.junit.Test public void findall(){ SqlSession sqlsession = MybatisUtil.getInsertance(); List<com.mxp.mybatis.entity.User> list = sqlsession.selectList("findAll"); for(com.mxp.mybatis.entity.User u:list){ System.out.println(u.getUserName()); } sqlsession.close(); } @org.junit.Test public void findLike(){ SqlSession sqlsession = MybatisUtil.getInsertance(); List<com.mxp.mybatis.entity.User> list = sqlsession.selectList("findLikeName","%文%"); for(com.mxp.mybatis.entity.User u:list){ System.out.println(u.getUserName()); } sqlsession.close(); } }
Mybatis的
Mapper映射器接口規則,會自動生成接口實現類。
修飾public
a.根據sqlMapper定義的id屬性當接口方法名
b 根據sqlMapper定義的parameterType類型定義參數類型
c 根據sqlMapper定義的resultType的類型 定義方法的返回類型
(多行使用list<泛型(resultType的類型)>,單行使resultType的類型)
d 將sqlMapper的namespace屬性指定成爲 包名.接口名字,就是接口的位置,
如何取到接口實現類呢
從sqlsession中獲取
sqlsession.getMapper(接口的class對象);
mybatis替我生成實現類,在實現類中把sqlsession.select*的各類操做封裝起來
首先實現 d
<?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="com.mxp.mybatis.dao.UserDao"> <sql id="userColumns"> a.id AS "id", a.user_name AS "userName" </sql> <select id="findAll" resultType="com.mxp.mybatis.entity.User" > SELECT <include refid="userColumns"/> FROM test_user a </select> <select id="findLikeName" parameterType="string" resultType="com.mxp.mybatis.entity.User" > SELECT <include refid="userColumns"/> FROM test_user a <where> a.user_name like #{name} </where> </select> </mapper>
a b c
package com.mxp.mybatis.dao; import java.util.List; import com.mxp.mybatis.entity.User; public interface UserDao { public List<User> findAll(); public List<User> findLikeName(String name); }
測試生成的映射器接口實現類
@org.junit.Test public void testMapper(){ SqlSession sqlsession = MybatisUtil.getInsertance(); UserDao dao = sqlsession.getMapper(UserDao.class); List<com.mxp.mybatis.entity.User> os = dao.findAll(); for(com.mxp.mybatis.entity.User u:os){ System.out.println(u.getUserName()); } sqlsession.close(); }