mybatis学习(3)进阶
11、mybatis和hibernate本質區別和應用場景
1、hibernate:是一個標準的ORM(對象關系映射),不需要程序員寫sql,sql語句自動生成
?????? :對sql語句進行優化,修改困難
適應于需求變化不多的中小型項目,egg:后臺管理系統,ERP(enterprise resource planning)ORM(object,relational,Mapping),OA(office automation )system辦公自動化,無紙化辦公模式。
2、mybatis:專注的是sql,需要程序員編寫sql語句,sql優化修改,優化方便
(不完全的ORM框架,可以實現映射(輸入映射、輸出映射))
?????? 適用于需求變化比較多的項目,敏捷式開發(egg:互聯網項目)
3、企業技術選型:低成本,高回報作為技術選型的原則,根據項目組的技術力量進行選擇。
?
12、mybatis開發dao的方法
?????? 1、SqlSession的使用范圍:
?
SqlSessionFactoryBuilder:將其當成一個工具類使用即可,在需要創建SqlSessionFactory時,只需要new一次SqlSessionFactoryBuilder即可
SqlSessionFactory:使用單例模式管理sqlSessionFactory(工廠一旦創建,使用一個實例)
?
SqlSession:是一個面向用戶(程序員)的接口,提供了很多操作數據庫的方法
?????? selectOne:
?????? selectList:(返回單個或多個對象)
SqlSession是線程不安全的,在SqlSession實現類中除了有接口中的方法(操作數據庫的方法),還有數據域屬性,
?
SqlSession最佳適用場合在方法體內,定義成局部變量使用。
??????
2、原始dao開發方法(程序員寫dao接口和dao實現類)
手寫dao接口和dao實現類
需要向dao實現類中注入SqlSessionFactory,在方法體通過SqlSessionFactory創建SqlSession
????????????? dao接口:
public interface UserDao {
?
??? //根據userId查詢用戶信息
??? public User findUserById(int userId) throws Exception;
???
??? //添加用戶信息
??? public void insertUser(User user) throws Exception;
???
??? //刪除用戶信息
??? public void deleteUser(int userId) throws Exception;
}
?
????????????? dao:
public class UserDaoImpl implements UserDao {
?
??? //需要向dao實現類中注入SqlSessionFactory
??? //這里通過構造方法注入
??? private SqlSessionFactory sqlSessionFactory;
??? public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
??????? this.sqlSessionFactory = sqlSessionFactory;
??? }
???
???
??? @Override
??? public User findUserById(int userId) throws Exception {
??????? SqlSession sqlSession = sqlSessionFactory.openSession();
??????? User user = sqlSession.selectOne("test.findUserById", userId);
??????? 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 userId) throws Exception {
??????? SqlSession sqlSession = sqlSessionFactory.openSession();
??????? sqlSession.delete("test.deleteUser", userId);
??????? sqlSession.commit();
??????? sqlSession.close();
???????
??? }
?
}
?
????????????? 單元測試:
public class UserDaoImplTest {
?
??? private SqlSessionFactory sqlSessionFactory;
??? //此方法是在執行testFindUserById之前執行
??? @Before
??? public void setUp() throws Exception {
??????? //創建sqlSessionFactory
??????? String resource = "SqlMapConfig.xml";
??????? InputStream config = Resources.getResourceAsStream(resource);
??????? sqlSessionFactory = new SqlSessionFactoryBuilder()
?????????????? .build(config);
??? }
??? @Test
??? public void testFindUserById() throws Exception {
??????? //創建UserDao的對象
??????? System.out.println("ddddd:"+sqlSessionFactory);
??????? UserDao userDao = new UserDaoImpl(sqlSessionFactory);
??????? //調用UserDao的方法
???????
??????? User user = userDao.findUserById(4);
???????
??????? System.out.println(user);
??? }
?
}
原始dao的開發問題:
?????? 1、dao接口實現類方法中存在大量模板方法,(提取公共代碼)
?????? 2、調用sqlSession方法時將statement的userId硬編碼了
?????? 3、調用sqlSession方法時傳入的變量,由于sqlSession方法使用泛型,即使變量類型傳入錯誤,在編譯階段也不報錯,不利于開發。
3、mapper代理方法(程序員只需要寫mapper接口)相當于dao接口
思路:?????????? (mapper代理開發規范)
?????? 1、編寫mapper.xml映射文件
?????? 2、編寫mapper接口(相當于dao接口),需要遵循一些開發規范,mybatis可以自動生成mapper接口實現類代理對象。
開發規范:
?????? *在mapper.xml中,namespace等于mapper接口地址
<!-- namespace命名空間,作用就是對sql進行分類化管理,理解sql隔離
注意:使用mapper代理方法開發,namespace有特殊重要的作用
-->
<mapper namespace="com.fzy.mybatis.mapper.UserMapper">
?????? *mapper.java接口中的方法名和mapper.xml中statement的id一致
?????? *mapper.java接口中的方法輸入參數類型和mapper.xml中statement的parameterType指定的類型一致
?????? *mapper.java接口中的方法返回值類型和mappe.xml中的resultType指定的類型一致。
public User findUserById(int id) throws Exception;
?
開發規范主要時對相似代碼進行統一生成
?
?????? 測試 :
mapper.java
?
public interface UserMapper {
?
??? public User findUserById(int userId) throws Exception;
mapper.xml
?
<select id="findUserById" parameterType="int" resultType="com.fzy.mybatis.po.User">
??????? select * from users where userId = #{userId}
</select>
?
在SqlMapConfig.xml中配置加載mapper.xml
<mapper resource="mapper/UserMapper.xml"/>
?
測試代碼:
public class UserMapperTest {
?
??? private SqlSessionFactory sqlSessionFactory;
??? //此方法時在執行testFindUserById之前執行
???
??? @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 {
??????? SqlSession sqlSession = sqlSessionFactory.openSession();
??????? System.out.println("sqlSession:"+sqlSession);
??????? //創建UserMapper的代理對象
??????? UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
??????? System.out.println("userMapper:"+userMapper);
??????? //調用UserMapper的方法
??????? User user = userMapper.findUserById(4);
???????
??????? System.out.println(user);
??? }
?
}
?
問題總結:
1、代理對象內部調用selectOne和selectList
?????? 如果mapper方法返回單個pojo對象(非集合對象),代理對象內部通過selectOne查詢數據庫
?????? 若mapper方法返回集合對象,代理對象內部通過selectList查詢數據庫
2、mapper接口方法參數只能有一個是否影響系統開發
??????
?????? 系統框架中,dao層的代碼時被業務層公用的
即使mapper接口只有一個參數,可以使用包裝類型的pojo滿足不同的業務方法的需求。
注意:持久層方法的參數可以用包裝類型,map,,,service方法中建議不要使用包裝類型(不利于業務層的可擴展性)。
?
?
?
13、mybatis的全局配置文件
配置內容:
?????? properties(屬性)
?????? settings(全局配置參數)
?????? typeAliases(類型別名)
typeHandlers(類型處理器)
objectFactory(對象工廠)
plugins(插件)
environments(環境集合屬性對象)
?????? enviroument(環境子屬性對象)
????????????? transactionManager(事務管理)
????????????? dataSource(數據源)
mappers(映射器)
?????? 1、properties
將數據庫連接參數單獨配置在db.properties中,只需要在SqlMapConfig.xm中加載db.properties的屬性值(解決數據庫連接參數硬編碼)
?????? 將數據庫連接參數只配置在db.properties中
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/travel?characterEncoding=utf-8
jdbc.username = root
jdbc.password = 123456
原因:方便對參數進行統一管理,其他的xml文件可以引用該db.properties
<!-- 加載屬性文件 -->
??? <properties resource="db.properties">
??????? <!-- properties中還可以配置一些屬性名和屬性值 -->
??????? <!-- <property name="" value=""/> -->
??? </properties>
???
???
??? <!-- 和spring整合后environments配置將移除 -->
??? <environments default="development">
??????? <environment id="development">
??????? ??? <!-- 使用jdbc事物管理,事物控制由mybatis進行 -->
?????????? <transactionManager type="JDBC" />
?????????? <!-- 數據庫連接池,由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 class="com.fzy.mybatis.mapper.UserMapper"/> -->
??? ??? <mapper resource="mapper/UserMapper.xml"/>
??? ???
??? </mappers>
注:mybatis加載屬性的順序
?????? 1、在properties元素體內定義的屬性首先被讀取
?????? 2、其后會讀取properties元素中resource或url加載的屬性,它會覆蓋已讀取的同名屬性
?????? 3、最后讀取parameterType傳遞的屬性,它會覆蓋已讀取的同名屬性
so:parameterType傳遞的屬性具有最高優先級,其次是properties中的resource或url,之后是properties元素體內定義的屬性。
?
?????? 不要在propeties元素體內添加任何屬性值,只將屬性值定義在properties文件中,在properties文件中定義屬性名要有一定的特殊性,egg:xxx.xxx.xxx
?
?????? 2、settings全局參數配置(需要時再設置)
mybatis框架在運行時可以調整一些運行參數:egg:開啟二級緩存,開啟延遲加載…
全局參數會影響mybatis的運行行為
?????? 3、typeAliases(別名)常用
在mapper.xml中,定義很多的statement,statement需要parameterType指定輸入參數的類型,需要resultType指定輸出結果的映射類型
?????? 可以針對parameterType和resultType指定的類型定義一些別名,方便開發。
默認別名:
?
自定義別名:
<!-- 別名定義 -->
??? <typeAliases>
??????? <!-- 針對單個別名的定義
??????? type:類型的路徑
??????? alias:別名 -->
??????? <typeAlias type="com.fzy.mybatis.po.User" alias="user"/>
</typeAliases>
?
<!-- 批量別名定義
??????? 指定包名,mybatis自動掃描包中的po類,自動定義別名,別名就是類名(首字母大小寫均可)
???????? -->
??????? <package name="com.fzy.mybatis.po"/>
?
?????? 4、typeHandlers類型處理器
mybatis中通過typeHandlers完成jdbc類型和Java類型的轉換
?????? 通常情況下,mybatis提供的類型處理器滿足日常需要,不需要自定義
?????? 5、mappers(映射配置)
加載單個映射文件(通過resource或url)
?????? <!-- 加載映射文件 -->
??? <mappers>
??? ??? <!-- 通過resource方法一次加載一個映射文件 -->
??? ??? <mapper resource="sqlmap/User.xml"/>
??? ??? <!-- <mapper class="com.fzy.mybatis.mapper.UserMapper"/> -->
??? ??? <mapper resource="mapper/UserMapper.xml"/>
??? </mappers>
通過mapper接口加載單個mapper
<!-- 通過mapper接口加載映射文件
??? ??? 規范:需要將mapper接口類名和mapper.xml映射文件名稱保持一致,且在一個目錄中。
??? ??? 前提:使用的是mapper代理方法
??? ???? -->
??? ???? <mapper class="com.fzy.mybatis.mapper.UserMapper"/>
根據規范:將mapper.java和mapper.xml放在一個目錄中,且同名
?
批量加載mapper(推薦使用)
<!-- 批量加載mapper
??? ???? 指定mapper接口的包名,mybatis自動掃描包下邊所有的mapper接口進行加載
??? ???? 規范:需要將mapper接口類名和mapper.xml映射文件名稱保持一致,且在一個目錄中。
??? ???? 前提:使用的是mapper代理方法
??? ????? -->
??? ????? <package name="com.fzy.mybatis.mapper"/>
轉載于:https://www.cnblogs.com/fzywhy/p/9581936.html
總結
以上是生活随笔為你收集整理的mybatis学习(3)进阶的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java基础(39)Arrays.bin
- 下一篇: scrapy 安装流程和启动