1. MyBatis認識 MyBatis是一款優秀的持久層框架,它支持定製化SQL、存儲過程以及高級映射。MyBatis可以使用簡單的XML配置或註解來配置和映射原生信息,將介面和Java的POJO(Plain Ordinary Java Object,普通Java對象)映射成資料庫中的數據。 2. ...
1. MyBatis認識
MyBatis是一款優秀的持久層框架,它支持定製化SQL、存儲過程以及高級映射。MyBatis可以使用簡單的XML配置或註解來配置和映射原生信息,將介面和Java的POJO(Plain Ordinary Java Object,普通Java對象)映射成資料庫中的數據。
2. 使用MyBatis完成基礎的CRUD
2.1.導入對應MyBatis及資料庫連接jar包
asm-3.3.1.jar
cglib-2.2.2.jar
commons-logging-1.1.1.jar
javassist-3.17.1-GA.jar
log4j-1.2.17.jar
mybatis-3.2.1.jar
mysql-connector-java-5.1.26-bin.jar
slf4j-api-1.7.2.jar
slf4j-log4j12-1.7.2.jar
2.2.建立資料庫的表
2.3. 對應資料庫表創建Domain類
public class Product { private Long id; private Long dir_id; // 商品分類編號 private String productName;// 商品名稱 private String supplier; // 供應商 private String brand; // 品牌 private Double salePrice; // 零售價 private Double cutoff; // 折扣比例 private Double costPrice; // 進價 。。。。// Getter與Setter略過 }
2.4. 配置MyBatis核心配置文件
MyBatis的核心配置文件放在項目的資源文件resources目錄下,文件命名為mybatis-config.xml,具體的配置如下:
mybatis-config.xml
<?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> <!-- 引入jdbc.properties配置文件 --> <properties resource="jdbc.properties"></properties> <!--別名的配置,類的全限定名可以使用別名 alias:別名名稱 type:別名所對應的類的全限定名,別名的使用與大小寫無關--> <typeAliases> <typeAlias alias="Product" type="cn.yif.mybatis.domain.Product"></typeAlias> <typeAlias alias="User" type="cn.yif.mybatis.domain.User"></typeAlias> </typeAliases> <!--MyBatis環境配置--> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <!-- 資料庫連接配置 --> <dataSource type="POOLED"> <property name="driver" value="${driverClassName}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <!—- Mapper.xml文件配置 --> <mappers> <mapper resource="cn/yif/mybatis/mapper/ProductMapper.xml"/> <mapper resource="cn/yif/mybatis/mapper/UserMapper.xml"/> </mappers> </configuration>
2.5. 關聯jdbc.properties文件配置
driverClassName = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/mybatis01_0317
username = root
password = admin
2.6. 對象關係映射文件XXXMapper.xml
映射文件XXXMapper.xml是對應Domain屬性與DaoImpl中方法並與資料庫欄位產生關係的唯一映射配置,在這裡面我們可以存放基礎的CRUD對應的Sql文件,去執行資料庫的操作:
<?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文件,一般是domain的全路徑名+Mapper來命名 --> <mapper namespace="cn.yif.mybatis.domain.Product"> <!--id表示唯一標識,parameterType標識參數的類型,resultType表示返回值的類型--> <select id="queryById" parameterType="Long" resultType="cn.yif.mybatis.domain.Product"> select * from Product where id = #{id} </select> <select id="queryAll" resultType="cn.yif.mybatis.domain.Product"> select * from Product </select> <!--添加時拿到返回的主鍵: parameterType:需要傳入的對象 useGeneratedKeys:是否需要主鍵 keyColumn:資料庫中對應主鍵的列 keyProperty:對象中主鍵對應的id--> <insert id="insert" parameterType="cn.yif.mybatis.domain.Product" useGeneratedKeys="true" keyColumn="id" keyProperty="id"> insert into Product(productName, dir_id, salePrice, supplier, brand, cutoff, costPrice) values (#{productName}, #{dir_id}, #{salePrice}, #{supplier}, #{brand}, #{cutoff}, #{costPrice}) </insert> <update id="update" parameterType="cn.yif.mybatis.domain.Product"> update product set productName = #{productName}, dir_id = #{dir_id}, salePrice = #{salePrice}, supplier = #{supplier}, brand = #{brand}, cutoff = #{cutoff}, costPrice = #{costPrice} where id = #{id} </update> <delete id="delete" parameterType="Long"> delete from product where id = #{id} </delete> </mapper>
2.7. 獲取SqlSession對象並抽取工具Util類
首先我們需要讀取mybatis-config.xml核心資源文件,通過SqlSessionFactoryBuilder構建者來創建一個SqlSessionFactory工廠,通過SqlSessionFactory來創建SqlSession對象。通過SqlSession就可以執行我們的資料庫增刪查改的xml中的配置語句,最終使用之後還需要及時關閉SqlSession語句對象。基於這種增刪改查操作都是同樣的我們可以抽取一個工具類MyBatisUtil,具體實現如下:
public class MyBatisUtil { private static SqlSessionFactory sqlSessionFactory = null; private static Reader reader = null; // 因為sqlSessionFactory是線程安全的,每次初始化只需要創建一個SqlSessionFactory實例 static { try { reader = Resources.getResourceAsReader("mybatis-config.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) { e.printStackTrace(); } } // SqlSession是線程不安全的類,每個線程內單獨去獲取當前線程的SqlSession public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } // 關閉SqlSession public static void closeSqlSession(SqlSession sqlSession){ if(sqlSession != null){ sqlSession.close(); } } }
2.8. 對應實現增刪查改的DaoImpl代碼
ProductDaoImpl.java
public class ProductDaoImpl implements IProductDao { public static final String NAME_SPACE = "cn.yif.mybatis.domain.Product."; @Override public void insert(Product product) { SqlSession sqlSession = MyBatisUtil.getSqlSession(); sqlSession.insert(NAME_SPACE + "insert", product); MyBatisUtil.closeSqlSession(sqlSession); } @Override public void update(Product product) { SqlSession sqlSession = MyBatisUtil.getSqlSession(); sqlSession.update(NAME_SPACE + "update", product); MyBatisUtil.closeSqlSession(sqlSession); } @Override public void delete(Long id) { SqlSession sqlSession = MyBatisUtil.getSqlSession(); sqlSession.delete(NAME_SPACE + "delete", id); MyBatisUtil.closeSqlSession(sqlSession); } @Override public Product queryById(Long id) { SqlSession sqlSession = MyBatisUtil.getSqlSession(); Product product = sqlSession.selectOne(NAME_SPACE + "queryById", id); MyBatisUtil.closeSqlSession(sqlSession); return product; } @Override public List<Product> queryAll() { SqlSession sqlSession = MyBatisUtil.getSqlSession(); List<Product> list = sqlSession.selectList(NAME_SPACE + "queryAll"); MyBatisUtil.closeSqlSession(sqlSession); return list; } }
2.9. 對應Junit4測試類實現
public class ProductDaoImplTest { @org.junit.Test public void insert() { IProductDao productDao = new ProductDaoImpl(); Product product = new Product(); product.setProductName("測試產品112"); product.setBrand("TestBrand"); product.setCostPrice(237.5); product.setCutoff(0.85); product.setDir_id(4L); product.setSalePrice(520.0); product.setSupplier("甲骨文"); System.out.println("添加之前,查看id:" + product.getId()); productDao.insert(product); System.out.println("添加之後,查看id:" + product.getId()); } @org.junit.Test public void update() { IProductDao productDao = new ProductDaoImpl(); Product product = new Product(); product.setId(22L); product.setProductName("測試產品114"); product.setBrand("TestBrand114"); product.setCostPrice(237.1); product.setCutoff(0.45); product.setDir_id(4L); product.setSalePrice(520.1); product.setSupplier("甲骨文114"); productDao.update(product); } @org.junit.Test public void delete() { IProductDao productDao = new ProductDaoImpl(); productDao.delete(24L); } @org.junit.Test public void queryById() { IProductDao productDao = new ProductDaoImpl(); Product product = productDao.queryById(31L); System.out.println(product); } @org.junit.Test public void queryAll() { IProductDao productDao = new ProductDaoImpl(); List<Product> list = productDao.queryAll(); for (Product product: list) { System.out.println(product); } } }
3. MyBatis配置使用細節
3.1. 添加insert時拿到返回的主鍵
對應在XXXMapper.xml中需要做如下配置:
<!--添加時拿到返回的主鍵: parameterType:需要傳入的對象 useGeneratedKeys:是否需要主鍵 keyColumn:資料庫中對應主鍵的列 keyProperty:對象中主鍵對應的id--> <insert id="insert" parameterType="cn.yif.mybatis.domain.Product" useGeneratedKeys="true" keyColumn="id" keyProperty="id"> insert into Product(productName, dir_id, salePrice, supplier, brand, cutoff, costPrice) values (#{productName}, #{dir_id}, #{salePrice}, #{supplier}, #{brand}, #{cutoff}, #{costPrice}) </insert>
3.2. Log4j日誌配置
Log4j是MyBatis提供的日誌列印依賴jar包,可以幫助我們進行分析和定位問題。在Log4j日誌配置文件中我們可以規定日誌列印顯示的級別:
日誌等級:從低到高(大小寫沒有關係,但是在配置的時候都建議使用大寫)
等級從低到高(大小寫沒有關係,但是在配置的時候建議都寫大寫)
TRACE:詳細 (建議開發的時候用)
DEDUG:調試,類似於System.out.print
INFO:信息,類似於JPA列印sql等級
WARN:警告,程式可以正常運行,出現提示
ERROR:錯誤,出現異常 (建議正式環境)
具體配置文件應命名為log4j.properties,配置如下:
log4j.properties:
#log4j.properties(日誌文件):
#全局配置:先配置一個日誌的根,這個級別是ERROR
log4j.rootLogger=ERROR, stdout
#局部配置 :把左邊包名改成你自己的包名:表示我們自己這個路徑下的代碼級別
#級別說明:TRACE(詳細)、Debug(調試)、Info(信息)、Warn(警告)、Error(錯誤)
log4j.logger.cn.yif.mybatis=TRACE
#在控制台輸出和輸出的格式
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
3.3.MyBatis中設置類的別名typeAliases
① MyBatis的內置別名
MyBatis中包含內置別名,即無需配置,MyBatis框架自動涵蓋的別名,可以直接使用。
具體包含如下別名類型:
② 自定義別名
具體配置及其使用:
別名需要在mybatis-config.xml中使用,位置在<properties>標簽之後:
<!--別名的配置,類的全限定名可以使用別名 alias:別名名稱 type:別名所對應的類的全限定名,別名的使用與大小寫無關--> <typeAliases> <typeAlias alias="Product" type="cn.yif.mybatis.domain.Product"></typeAlias> <typeAlias alias="User" type="cn.yif.mybatis.domain.User"></typeAlias> </typeAliases>
使用別名:
在XXXMapper.xml文件中對應的類全限定名即可使用別名,且與大小寫無關。
3.4.列名與屬性名不一致ResultMap
資料庫中的列名與Domain類中的屬性名不一致時,如果直接使用ResultType對應,執行Sql查詢語句等會出現相應值為null的情況,這時需要配置ResultMap進行關係映射對應,告訴Sql這個資料庫中的列是對應Domain類中的哪個屬性,具體配置如下:
<?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文件,一般是domain的全路徑名+Mapper來命名 --> <mapper namespace="cn.yif.mybatis.domain.User"> <!--當Domain中的屬性與資料庫中的欄位列不一致時,需要使用resultMap id表示唯一標識,對應select中的resultMap type表示返回值類型 column:對應資料庫中的列名 property:對應Domain中類的屬性欄位--> <resultMap id="userMap" type="User"> <result column="username" property="name"></result> <result column="password" property="pwd"></result> </resultMap> <!--id表示唯一標識,parameterType標識參數的類型,resultType表示返回值的類型--> <select id="getUserById" parameterType="Integer" resultMap="userMap"> select * from user where id = #{id} </select> </mapper>