1、介紹
Mybatis是一個應用於dao層框架(持久層框架)。持久層:數據訪問層。
他也是一個ORM框架(對象 關係 映射),相比於hibernate,他是一個半自動的框架。
2、優點
1.Jdbc的缺點:
重複工作多,每次都要創建連接(連接池),獲得執行sql語句的對象,執行sql語句,然後處理結果集,最後釋放資源。
爲處理結果集,工作非常複雜,參數的處理比較麻煩。
2.Mybatis的優點:
讓程序員關注sql語句。
參數的設置,結果集的處理,框架自動幫你生成。
簡單易學。
靈活。
Mybatis入門
1、準備數據庫
2、準備實體類
3、導包
(1).Mybatis包
(2).數據庫驅動包
4、書寫配置文件
(1).核心配置文件
sqlMapConfig.xml
① .導入約束
<?xmlversion="1.0" encoding="UTF-8" ?>
<!DOCTYPEconfiguration
PUBLIC "-//mybatis.org//DTDConfig 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
② .配置內容
<!--環境-->
<environmentsdefault="development">
<environmentid="development">
<transactionManagertype="JDBC"></transactionManager>
<dataSourcetype="POOLED">
<propertyname="driver"value="com.mysql.jdbc.Driver"></property>
<propertyname="url"value="jdbc:mysql://localhost:3306/mybatis_demo"></property>
<propertyname="username" value="root"></property>
<propertyname="password" value="123"></property>
</dataSource>
</environment>
</environments>
<!--映射-->
<mappers>
<mapperresource="cn/hd/pojo/UserMapper.xml"></mapper>
</mappers>
(2).映射文件
<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTDMapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test">
<selectid="findUserById" parameterType="int"resultType="cn.hd.pojo.User" >
SELECT * FROM t_user WHERE id= #{id}
</select>
<selectid="findUserByName" parameterType="String"resultType="cn.hd.pojo.User">
SELECT * FROM t_user WHEREusername LIKE "%"#{username}"%"
</select>
<insert id="addUser"parameterType="cn.hd.pojo.User">
<!--
keyProperty:將查詢到主鍵設置到parameterType指定的對象的哪個屬性
order:SELECT LAST_INSERT_ID()的執行順序,相對於insert語句來說他的執行順序。
-->
<selectKeykeyProperty="id" resultType="Integer" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTOt_user(name,sex,address,balance) VALUES (#{name},#{sex},#{address},#{balance})
</insert>
<delete id="deleteUser"parameterType="Integer" >
DELETE FROM t_user WHERE id = #{id}
</delete>
<update id="updateUser"parameterType="cn.hd.pojo.User">
UPDATE t_user SET name = #{name}WHERE id = #{id}
</update>
</mapper>
(3).log4j
# Global logging configuration
#在開發環境下日誌級別設置爲debug,生產環境下設置成info或error
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
5、配置介紹
1.SqlMapConfig
命名可以修改,位置任意。當然我們建議的名字是SqlMapConfig,位置放在目錄下。
(1).environments
表示SqlMapConfig的運行環境。
(2)運行環境
數據庫的基本信息,事務。
(3).mppers
表示數據源。
2.UserMapper.xml
名字可以修改,位置任意。
名字建議User.xml(ibatis) UserMpper.xml(Mybatis)我們建議命名爲類名+Mapper.xml
所有的sql語句都寫在USerMaper中。
mapper的namespace屬性
解決在不同表中查詢的sql語句的名字衝突,比如:
User表 findById order表 findById名字衝突,不識別,所以可以給不同的表的數據源加上一個前綴,對應的是namespace屬性。
<select id="findUserById"parameterType="int" resultType="cn.hd.pojo.User" >
SELECT* FROM t_user WHERE id = #{id}
</select>
id 給當前的sql語句起一個識別id,parameterType:參數類型
resultType:結果集封裝的類型。
#{id}:佔位符 裏面對的名字任意
簡單實用的Mybatis的增刪改查
1.查找一個用戶
<!--
mapper:映射
namespace="test":確保調用方法的唯一性,避免多張表多個mapper調用方法重複
parameterType:參數類型
resultType:結果集封裝的類型
-->
<mapper namespace="test">
<selectid="findUserById" parameterType="int"resultType="cn.hd.pojo.User" >
SELECT * FROM t_user WHERE id= #{id}
</select>
測試代碼
@Test
public voidfun1() throws IOException {
InputStream in =Resources.getResourceAsStream("sqlMapConfig.xml");
/*獲得SessionFactory,讀取流*/
SqlSessionFactory sessionFactory =new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession =sessionFactory.openSession();
User user =sqlSession.selectOne("test.findUserById", 1);
System.out.println(user);
sqlSession.close();
}
2.通過名字模糊查找用戶
<!--
# 佔位符
$ 字符串拼接 sql注入(不建議使用)
也可以使用佔位符 1.直接將整個當成參數在代碼中傳遞時手動拼接%%
2.sql提供的
$和#區別:#裏面的變量名隨意 ${變量名} 不能隨便寫,如果是 常用類型 必須用value
-->
<select id="findUserByName" parameterType="String"resultType="cn.hd.pojo.User">
SELECT * FROM t_user WHERE name LIKE"%"#{name}"%"
</select>
測試代碼
@Test
public void fun2() throws IOException {
InputStream in =Resources.getResourceAsStream("sqlMapConfig.xml");
/*獲得SessionFactory,讀取流*/
SqlSessionFactory sessionFactory =new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession =sessionFactory.openSession();
List<User>list = sqlSession.selectList("test.findUserByName", "李");
System.out.println(list);
sqlSession.close();
}
3.添加一個用戶
<!--/*如果參數是引用類型 佔位符的賦值方式爲 ognl表達式的方式 #{屬性名}*/-->
<insert id="addUser"parameterType="cn.hd.pojo.User">
INSERT INTOt_user(name,sex,address,balance) VALUES (#{name},#{sex},#{address},#{balance})
</insert>
測試代碼
@Test
public void fun3() throws IOException {
InputStream in =Resources.getResourceAsStream("sqlMapConfig.xml");
/*獲得SessionFactory,讀取流*/
SqlSessionFactory sessionFactory =new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession =sessionFactory.openSession();
User user = new User();
user.setName("楊二狗");
user.setAddress("坑");
user.setSex("nv");
user.setBalance(1000);
int insert =sqlSession.insert("test.addUser", user);
System.out.println(insert);
sqlSession.commit();
System.out.println(insert);
sqlSession.close();
}
這種操作並不會把新生成的記錄中的主鍵保存到對象中,但是有一種需求,在保存用戶的同時,要利用用戶主鍵去保存一條新的記錄。所以爲滿足該需求,提供了新的標籤。
<!—
keyProperty:將查詢到主鍵設置到parameterType指定的對象的哪個屬性
order:SELECTLAST_INSERT_ID()的執行順序,相對於insert語句來說他的執行順序。
-->
<!--如果參數是引用類型 佔位符的賦值方式爲 ognl表達式的方式 #{屬性名}-->
<insert id="addUser" parameterType="cn.hd.pojo.User">
<selectKeykeyProperty="id" order="AFTER"resultType="int">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTOt_user(name,sex,address,balance) VALUES (#{name},#{sex},#{address},#{balance})
</insert>
keyProperty:對應的是對象中的屬性名KeyCloumn對應的是數據庫中的字段名。
resultType:對應的是返回值結果類型(intString)分別對應數據庫生成代理主鍵的策略。Int 對應自動遞增,String對應uuid。
order 順序跟數據庫底層有關,自動遞增默認先添加數據,再生成主鍵 。但是uuid就是先生成id再去添加數據。
如果是增刪改,必須要提交事務才能持久化到數據庫。
查詢語法
SELECT LAST_INSERT_ID()適用於自動遞增。
SELECT uuid() 適用於uuid。通過id刪除用戶
4.通過id刪除用戶
<delete id="deleteUser"parameterType="Integer">
DELETE FROM t_user WHERE id =#{id}
</delete>
測試代碼
@Test
public void fun4() throws IOException {
InputStream in =Resources.getResourceAsStream("sqlMapConfig.xml");
/*獲得SessionFactory,讀取流*/
SqlSessionFactory sessionFactory =new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession =sessionFactory.openSession();
int delete =sqlSession.delete("test.deleteUser", 5);
sqlSession.commit();
System.out.println(delete);
sqlSession.close();
}
5.通過id修改用戶
<update id="updateUser"parameterType="cn.hd.pojo.User">
UPDATEt_user SET name = #{name},sex = #{sex},address = #{address},balance=#{balance}WHERE id = #{id}
</update>
測試代碼
@Test
public void fun5() throws IOException {
InputStream in =Resources.getResourceAsStream("sqlMapConfig.xml");
/*獲得SessionFactory,讀取流*/
SqlSessionFactory sessionFactory =new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession =sessionFactory.openSession();
User user = new User();
user.setId(8);
user.setName("楊二狗");
user.setAddress("水");
user.setSex("男");
user.setBalance(1000);
int update =sqlSession.update("test.updateUser", user);
sqlSession.commit();
System.out.println(update);
sqlSession.close();
}
原始dao層開發
package cn.hd.dao.impl;
import cn.hd.dao.UserDao;
import cn.hd.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
public class UserDaoImpl implements UserDao {
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactorysqlSessionFactory) {
this.sqlSessionFactory =sqlSessionFactory;
}
@Override
public User findUserById(Integer id){
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("test.findUserById",1);
sqlSession.commit();
sqlSession.close();
return user;
}
@Override
public Integer addUser(User user) {
SqlSession sqlSession = sqlSessionFactory.openSession();
int insert = sqlSession.insert("test.addUser",user);
sqlSession.commit();
sqlSession.close();
return insert;
}
@Override
public Integer deleteUser(Integer id){
return null;
}
}
測試代碼
package cn.hd.dao;
import cn.hd.dao.UserDao;
import cn.hd.dao.impl.UserDaoImpl;
import cn.hd.pojo.User;
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 java.io.IOException;
import java.io.InputStream;
public class Demo {
private UserDao userDao;
@Before
public void before() throws IOException{
InputStream in = Resources.getResourceAsStream("cn/hd/mapper/sqlMapConfig.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
userDao = new UserDaoImpl(build);
}
@Test
public void fun1(){
User userById = userDao.findUserById(1);
System.out.println(userById);
}
}
dao層的mapper開發
不用去寫實現類,他會使用代理的方式自動生成實現代碼,想要使用mapper開發,必須遵循以下原則:
1、 接口的名字建議和mapper映射文件的名字保持一致,並且在同一目錄下。
namespace必須和接口的完整路徑名保持一致。
2、 接口中的方法名必須和mapper中的id保持一致。
3、 方法的返回值和配置文件中的resultType保持一致。
4、 參數的類型必須保持一致。
在代碼中,就不需要關注SqlSession對象的方法調用了insert、update、delete、selectOne、selectList
sqlSession.getMapper(UserMapper.class);
返回一個接口的代理對象,直接調用該對象的方法即可。
@Test
public void fun1() throws IOException {
InputStream in =Resources.getResourceAsStream("cn/hd/dao/sqlMapConfig.xml");
SqlSessionFactory build = newSqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = build.openSession();
UserMapper mapper =sqlSession.getMapper(UserMapper.class);
User userById =mapper.findUserById(1);
System.out.println(userById);
}
注意:使用mapper開發,它的參數永遠只有一個,如果有多個參數,需要將多的參數封裝成pojo類。
Mybatis自動識別接口中的方法的返回值,從而調用session.selectOne和selectList方法。
SqlMapConfig配置詳解
配置文件中的屬性順序不能更改。
1、properties
設置配置信息
<!--自動讀取properties文件-->
<propertiesresource="db.properties"></properties>
2、settings
全局設置 mybatis的二級緩存 設置mybatis的加載屬性。
3、 typeAliases
別名
<!--別名-->
<typeAliases>
<!--單個別名-->
<typeAliastype="cn.hd.pojo.User" alias="user"></typeAlias>
<!--包的掃描方式,多個別名,別名不區分大小寫 cn.hd.pojo.User 使用User/user-->
<packagename="cn.hd.pojo"></package>
</typeAliases>
決定着mapper.xml文件中的數據類型可以使用簡短的名字。
<select id="findUserById"parameterType="Integer" resultType="user" >
• typeHandlers
類型控制器,將數據庫中的數據類型和Java中的數據類型進行匹配。一般情況下不需要我們去書寫。
• objectFactory
• plugins
• environments
• environment
• transactionManager
• dataSource
• databaseIdProvider
• mappers
映射文件,書寫方式一共有四種。
1、mapper
<mapper resource="cn/hd/sqlmapconfig/UserMapper.xml"></mapper>
2、通過接口來讀取配置文件
①.接口的名字必須和配置文件保持一致
②.接口和配置文件必須在同一目錄下
<mapperclass="cn.hd.sqlmapconfig.UserMapper"></mapper>
3、通過絕對路徑來讀取
<mapper url=""></mapper>
4、讀取的是接口的包名,因此要求多有的接口和對應的配置文件都要保持一致(名字和位置)
<packagename="cn.hd.sqlmapconfig"></package>
總結:推薦使用的第四種,你的接口和配置文件同名且在同一個包下。