文章目錄
一、JDBC問題總結
1.數據庫連接創建、釋放頻繁造成系統資源浪費,從而影響系統性能。使用數據庫連接池可以解決此問題;
2.SQL語句寫在代碼中,所以想修改SQL需要修改源代碼,不易維護;
3.使用PreparedStatement向佔位符號傳參數存在固定代碼,SQL語句的where條件可能會變化,造成要修改代碼,從而不易維護;
4.對結果集解析存在固定代碼,SQL變化導致解析代碼變化,系統不易維護,如果能將數據庫記錄封裝成POJO對象解析比較方便。
二、Mybatis架構
三、Mybatis入門程序
1、環境搭建及通過ID查詢示例
在數據庫中創建表:
語句:
CREATE TABLE `user` (
`id` BIGINT(32) AUTO_INCREMENT,
`username` VARCHAR(32),
`birthday` VARCHAR(32),
`sex` VARCHAR(32),
`address` VARCHAR(32),
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
表結構:
創建工程:Javaproject
導入jar包:與src平行的位置創建一個文件夾lib,將要導入的jar包放進去,再Build Path
創建映射類:User.java(極其get、set方法,這裏省略)
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String username;// 用戶姓名
private String sex;//性別
private String birthday;// 生日
private String address;// 地址
}
創建核心配置文件:sqlMapConfig.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>
<!-- 和spring整合後 environments配置將廢除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事務管理 -->
<transactionManager type="JDBC" />
<!-- 數據庫連接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis_01?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="2e5y8hxf" />
</dataSource>
</environment>
</environments>
<!--映射的位置-->
<mappers>
<mapper resource = "sqlXml/User.xml"/>
</mappers>
</configuration>
創建映射配置文件:User.xml
parameterType:輸入參數類型,可以是簡單數據類型、pojo對象、pojo包裝對象
resultType:輸出結果類型
命名空間namespace:用於存在多個配置映射時進行區分;
#{}:表示佔位符,相當於select * from user where id = ? 中的?
<?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">
<!-- 寫SQL語句 -->
<mapper namespace = "user_test">
<!-- 通過ID查詢一個用戶 -->
<select id="findUserById" parameterType = "Integer" resultType = "pojo.User">
select * from user where id = #{v}
</select>
</mapper>
創建日誌文件:log4j.properties用具顯示記錄的程序運行過程
# Global logging configuration
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
創建測試類文件:
public class TestDemo1 {
@Test
public void demo1() throws Exception {
//加載核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//創建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//創建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//執行SQL語句
User user = sqlSession.selectOne("user_test.findUserById", 1);
System.out.println(user);
}
}
測試結果:
2、通過用戶名模糊查詢
修改映射配置文件:
${}:表示字符串拼接,相當於select * from user where username like ‘% ${value} %’ ,這裏{}內必須爲value;
另一種寫法:select * from user where username like “%”#{haha}"%" ,這裏的#{haha}相當於’haha’;
<?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">
<!-- 通過用戶名模糊查詢 -->
<select id="findUserByUsername" parameterType = "String" resultType = "pojo.User">
select * from user where username like '%${value}%'
</select>
</mapper>
修改測試類:
public class TestDemo1 {
@Test
public void demo1() throws Exception {
//加載核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//創建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//創建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//執行SQL語句
List<User> users = sqlSession.selectList("user_test.findUserByUsername","三");
for(User user:users)
System.out.println(user);
}
}
測試結果:
3、添加用戶並返回添加的用戶ID
1.添加用戶:
修改映射配置文件:
<?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">
<!-- 寫SQL語句 -->
<mapper namespace = "user_test">
<!-- 添加用戶 -->
<insert id="insertUser" parameterType = "pojo.User">
insert into user(username,birthday,address,sex)
values (#{username},#{birthday},#{address},#{sex})
</insert>
</mapper>
修改測試類:
@Test
public void demo2() throws Exception {
//加載核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//創建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//創建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//執行SQL語句
User user = new User();
user.setUsername("張無忌");
user.setBirthday("1650年0101");
user.setAddress("武當山");
user.setSex("男");
int i = sqlSession.insert("user_test.insertUser",user);
sqlSession.commit();
}
測試結果:
2.返回添加的用戶ID:
修改映射配置文件:
<!-- 添加用戶 -->
<insert id="insertUser" parameterType = "pojo.User">
insert into user(username,birthday,address,sex)
values (#{username},#{birthday},#{address},#{sex})
</insert>
修改測試類:
System.out.println(user.getId());
測試結果:
按照最新添加的用戶,輸出其id值。
4、通過ID修改用戶
修改映射配置文件:
<?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">
<!-- 寫SQL語句 -->
<mapper namespace = "user_test">
<!-- 更新用戶 -->
<update id="updateUserById" parameterType = "pojo.User">
update user set username = #{username},sex = #{sex},birthday = #{birthday},address = #{address}
where id = #{id}
</update>
</mapper>
修改測試類:
@Test
public void demo3() throws Exception {
//加載核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//創建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//創建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//執行SQL語句
User user = new User();
user.setId(3);
user.setUsername("趙敏");
user.setBirthday("1650年0101");
user.setAddress("元大都");
user.setSex("女");
int i = sqlSession.update("user_test.updateUserById",user);
sqlSession.commit();
}
測試結果:
5、通過ID刪除用戶
修改映射配置文件:
<?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">
<!-- 寫SQL語句 -->
<mapper namespace = "user_test">
<!-- 刪除用戶 -->
<update id="deleteUserById" parameterType = "Integer">
delete from user where id = #{hahaha}
</update>
</mapper>
修改測試類:
@Test
public void demo4() throws Exception {
//加載核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//創建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//創建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//執行SQL語句
sqlSession.delete("user_test.deleteUserById",3);
sqlSession.commit();
}
測試結果:刪除了ID爲3的用戶。
四、Mybatis與Hibernate區別
概述:Mybatis和Hibernate不同,它不完全是一個ORM框架,Hibernate完全是ORM框架,因爲MyBatis需要程序員自己編寫Sql語句。mybatis可以通過XML或註解方式靈活配置要運行的sql語句,並將java對象和sql語句映射生成最終執行的sql,最後將sql執行的結果再映射生成java對象。
區別一:Mybatis學習門檻低,簡單易學,程序員直接編寫原生態sql,可嚴格控制sql執行性能,靈活度高,非常適合對關係數據模型要求不高的軟件開發;
區別二:Hibernate對象/關係映射能力強,數據庫無關性好,對於關係模型要求高的軟件(例如需求固定的定製化軟件)如果用hibernate開發可以節省很多代碼,提高效率。
總之,按照用戶的需求在有限的資源環境下只要能做出維護性、擴展性良好的軟件架構都是好架構,所以框架只有適合纔是最好。
五、原始DAO開發和Mapper動態代理開發
1、原始DAO開發
注意:這裏省略User.xml和sqlMapConfig.xml文件的編寫;
創建UserDao接口和實現類:在DAO中注入工廠,並與數據庫建立聯繫;
public interface UserDao { //接口
public User selectUserById(Integer id);
}
public class UserDaoImpl implements UserDao{ //實現類
//注入工廠
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
super();
this.sqlSessionFactory = sqlSessionFactory;
}
//通過ID查詢一個用戶
@Override
public User selectUserById(Integer id) {
SqlSession sqlSession = sqlSessionFactory.openSession();
return sqlSession.selectOne("user_test.findUserById",id);
}
}
創建測試類:這裏創建DAO之後,沒有創建Service層,所以使用Junit測試代替。在測試類中創建Session工廠,然後將工廠作爲入參,創建DAO對象,之後就可以使用userDao進行查詢操作了。
public class MybatisDaoTest {
public SqlSessionFactory sqlSessionFactory;
@Before
public void before() throws Exception{
//加載核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
}
@Test
public void demo1() throws Exception{
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
User user = userDao.selectUserById(2);
System.out.println(user);
}
}
2、Mapper動態代理開發
注意:這裏省略User.xml和sqlMapConfig.xml文件的編寫;
編寫動態代理接口:
遵循四個原則:
(1)Mapper接口方法名與映射配置文件Mapper.xml(這裏爲User.xml)中相應statement的id名一致;
(2)Mapper接口中的輸出參數類型與Mapper.xml中的定義的每個sql的resultType的類型相同;
(3)Mapper接口中的輸入參數類型與Mapper.xml中的定義的每個sql的parameterType的類型相同;
(4)將Mapper.xml命名空間namespace設置爲接口的類路徑名,綁定此接口。
User.xml爲:
代理接口代碼爲:
public interface UserMapper {
public User findUserById(Integer id);
}
編寫測試類:
@Test
public void demo1() throws Exception {
//加載核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//創建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//創建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//sqlSession幫我生成一個實現類
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findUserById(1);
System.out.println(user);
}
測試結果:
兩點注意:
1.針對selectOne和selectList說明:
動態代理對象調用sqlSession.selectOne()和sqlSession.selectList()是根據mapper接口方法的返回值決定,如果返回list則調用selectList方法,如果返回單個對象則調用selectOne方法;
2.namespace說明
mybatis官方推薦使用mapper代理方法開發mapper接口,程序員不用編寫mapper接口實現類。
六、sqlMapConfig.xml核心配置文件分析
SqlMapConfig.xml中配置的內容和順序如下:標籤可以省略不配置,但是順序不能變;
1、properties(屬性標籤)
概述:位於configuration子標籤下的屬性標籤,用於填充value值;
使用properties標籤前:
使用properties標籤後:
在src目錄下建立jdbc.properties文件:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_01?characterEncoding=utf-8
jdbc.username=root
jdbc.password=2e5y8hxf
2、typeAliases(別名標籤)
第一種方式:直接將pojo.User起一個別名叫User,可以在User.xml(映射配置文件)中直接使用User;
<typeAliases>
<typeAlias type="pojo.User" alias = "User"/>
</typeAliases>
第二種方式:可以在User.xml(映射配置文件)中直接使用pojo包裏所以的類名;
<typeAliases>
<package name="pojo"/>
</typeAliases>
使用方式:
另外,Mybatis支持的別名:
3、mappers(屬性標籤)
1.mapper子標籤:
第一種方式:使用resource
<mappers>
<mapper resource = "sqlXml/User.xml"/>
</mappers>
第二種方式:使用class,此方法也要求Mapper代理中的接口名稱與映射文件名稱一致,且放在同一目錄下(即:通過Mapper代理接口來找到UserMapper.xml(映射配置文件,即前面的User.xml),前提是該接口與xml文件的名字相同,這裏是都爲UserMapper)。
<mappers>
<mapper class = "mapper.UserMapper"/>
</mappers>
第三種方式:使用url,要求絕對路徑,一般不用。
2.package字標籤:此方法也要求Mapper代理中的接口名稱與映射文件名稱一致,且放在同一目錄下,這裏爲mapper目錄,企業中一般用這種方式。
<mappers>
<package name = "mapper"/>
</mappers>