分析 Jdbc、JdbcTemplate、Mybatis 原理區別(程式碼解析)
阿新 • • 發佈:2021-03-30
寫在前面:
- 原始碼(可直接執行):
- 參考部落格:
- 該部落格要是對您有幫助,請點個贊支援一下,謝謝!
文章目錄
1. 總結 Jdbc、JdbcTemplate、Mybatis 原理及其區別
- Jdbc
- API 允許使用者訪問任何形式的表格資料,尤其是儲存在關係資料庫中的資料。
- 執行流程:
1. 連線資料來源,如:資料庫。
2. 為資料庫傳遞查詢和更新指令。
3. 處理資料庫響應並返回的結果。 - 架構圖
- JdbcTemplate
- JDBC 已經能夠滿足大部分使用者最基本的需求,但是在使用 JDBC 時,必須自己來管理資料庫資源如:獲取 PreparedStatement,設定 SQL 語句引數,關閉連線等步驟。
- JdbcTemplate 是 Spring 對 JDBC 的封裝,目的是使 JDBC 更加易於使用
- JdbcTemplate 處理了資源的建立和釋放。他幫助我們避免一些常見的錯誤,比如忘了總要關閉連線。他執行核心的 JDBC 工作流,如 Statement 的建立和執行,而我們只需要提供 SQL 語句和提取結果。
- Mybatis
- MyBatis 是一款優秀的持久層框架。
- 它支援定製化 SQL、儲存過程以及高階對映。
- MyBatis 避免了幾乎所有的 JDBC 程式碼和手動設定引數以及獲取結果集。
- MyBatis 可以使用簡單的 XML 或註解來配置和對映原生型別、介面和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 物件)為資料庫中的記錄。
- MyBatis 本是apache的一個開源專案iBatis, 2010年這個專案由apache software foundation 遷移到了google code,並且改名為MyBatis 。
- 2013年11月遷移到Github。
2. 實現資料庫 MySQL 的增刪改查[ 具體程式碼實現 ]
環境搭建:
- 建立資料表 user;含有 id、name、pwd 欄位
- 建立 Maven 工程,匯入 jar 包
<!-- mysql驅動 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.4</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
2.1 使用 Jdbc 實現
- JDBC 固定步驟:
- 載入驅動
- 連線資料庫,代表資料庫
- 向資料庫傳送SQL的物件Statement : CRUD
- 編寫SQL (根據業務,不同的SQL)
- 執行SQL
- 關閉連線
- 使用 Jdbc 查詢
public class TestJdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException, SQLException {
//配置資訊
//useUnicode=true&characterEncoding=utf-8 解決中文亂碼
String url="jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=utf-8";
String username = "root";
String password = "Kc635908933";
//1.載入驅動
Class.forName("com.mysql.jdbc.Driver");
//2.連線資料庫,代表資料庫
Connection connection = DriverManager.getConnection(url, username, password);
//3.向資料庫傳送 SQL 的物件 Statement,PreparedStatement : CRUD
Statement statement = connection.createStatement(); // 建立 SQL 物件
//4.編寫SQL
String sql = "select * from mybatis.user";
//5.執行查詢SQL,返回一個 ResultSet : 結果集
ResultSet rs = statement.executeQuery(sql);
while (rs.next()){
System.out.println("id="+rs.getObject("id"));
System.out.println("name="+rs.getObject("name"));
System.out.println("password="+rs.getObject("pwd"));
}
//6.關閉連線,釋放資源(一定要做) 先開後關
rs.close();
statement.close();
connection.close();
}
}
- 使用 Jbdc 插入資料
public class TestJdbc2 {
public static void main(String[] args) throws Exception {
//配置資訊
//useUnicode=true&characterEncoding=utf-8 解決中文亂碼
String url="jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=utf-8";
String username = "root";
String password = "Kc635908933";
//1.載入驅動
Class.forName("com.mysql.jdbc.Driver");
//2.連線資料庫,代表資料庫
Connection connection = DriverManager.getConnection(url, username, password);
//3.編寫SQL
String sql = "insert into mybatis.user(id, name, pwd) values (?,?,?);";
//4.預編譯
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,24);//給第一個佔位符? 的值賦值為1;
preparedStatement.setString(2,"狂神說Java");//給第二個佔位符? 的值賦值為狂神說Java;
preparedStatement.setString(3,"123456");//給第三個佔位符? 的值賦值為123456;
//5.執行SQL
int i = preparedStatement.executeUpdate();
if (i>0){
System.out.println("插入成功@");
}
//6.關閉連線,釋放資源(一定要做) 先開後關
preparedStatement.close();
connection.close();
}
}
2.2 使用 JdbcTemplate 實現(Spring)
- 定義 Book 實體類
public class Book {
private String id;
private String bookname;
private String bookauther;
public String getId() {
return id;
}
public String getBookname() {
return bookname;
}
public String getBookauther() {
return bookauther;
}
public void setId(String id) {
this.id = id;
}
public void setBookname(String bookname) {
this.bookname = bookname;
}
public void setBookauther(String bookauther) {
this.bookauther = bookauther;
}
@Override
public String toString() {
return "Book{" +
"id='" + id + '\'' +
", bookname='" + bookname + '\'' +
", bookauther='" + bookauther + '\'' +
'}';
}
}
- 定義 BookDao 介面類
// 介面類
public interface BookDao {
void add(Book book);
void update(Book book);
void delete(String id);
int selectCount();
Book findBookInfo(String id);
List<Book> findAllBook();
void batchAddBook(List<Object[]> batchArgs);
void batchUpdateBook(List<Object[]> batchArgs);
void batchDeleteBook(List<Object[]> batchArgs);
}
- 定義 BookDaoImpl 實現類
// 介面實現類
//@Repository <bean id="bookDaoImpl" class="......"/>
public class BookDaoImpl implements BookDao{
// 注入JDBCTemplete
// <property name="jdbcTemplate" ref="jdbcTemplate"/>>
@Autowired
private JdbcTemplate jdbcTemplate;
// 新增的方法
@Override
public void add(Book book) {
// 資料庫增加
// 1.sql語句--在userdb資料庫內的tb_books資料表上
String sql="insert into tb_book values(?,?,?)";
Object[] args={book.getId(),book.getBookname(),book.getBookauther()};
// 2.呼叫方法實現
int update = jdbcTemplate.update(sql,args);
System.out.println(update);
}
// 更新方法
@Override
public void update(Book book) {
String sql="update tb_book set bookname=?, bookauther=? where id=?";
Object[] args={book.getId(),book.getBookname(),book.getBookauther()};
int update = jdbcTemplate.update(sql,args);
System.out.println(update);
}
// 刪減方法
@Override
public void delete(String id) {
String sql="delete from tb_book where id=?";
int update = jdbcTemplate.update(sql,id);
System.out.println(update);
}
// 查詢方法1-返回某個值
@Override
public int selectCount() {
String sql = "select count(*) from tb_book";
int count = jdbcTemplate.queryForObject(sql,Integer.class);
return count;
}
// 查詢方法2-返回物件
@Override
public Book findBookInfo(String id) {
String sql = "select * from tb_book where id=?";
Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id);
return book;
}
// 查詢方法3-返回集合
@Override
public List<Book> findAllBook() {
String sql = "select * from tb_book";
List<Book> bookList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class));
return bookList;
}
// 批量新增
@Override
public void batchAddBook(List<Object[]> batchArgs) {
String sql = "insert into tb_book values(?,?,?)";
int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(Arrays.toString(ints));
}
// 批量修改
@Override
public void batchUpdateBook(List<Object[]> batchArgs) {
String sql = "update tb_book set bookname=?, bookauther=? where id=?";
int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(Arrays.toString(ints));
}
// 批量刪除
@Override
public void batchDeleteBook(List<Object[]> batchArgs) {
String sql="delete from tb_book where id=?";
int[] ints = jdbcTemplate.batchUpdate(sql,batchArgs);
System.out.println(Arrays.toString(ints));
}
}
- 定義 BookService 類
//@Service
public class BookService {
// 注入Dao
// @Autowired
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
// 新增方法
public void addBook(Book book){
bookDao.add(book);
}
// 修改的方法
public void updateBook(Book book){
bookDao.update(book);
}
// 刪除的方法
public void deleteBook(String id){
bookDao.delete(id);
}
// 查詢1-返回某個值 (查詢表中記錄數)
public int findCount(){
return bookDao.selectCount();
}
// 查詢2-返回物件 (查詢圖書詳情 )
public Book findOne(String id){
return bookDao.findBookInfo(id);
}
// 查詢3-返回集合 (查詢圖書列表分頁)
public List<Book> findAll(){
return bookDao.findAllBook();
}
// 批量新增--陣列形式
// batchArgs--批量指令
public void batchAdd(List<Object[]> batchArgs){
bookDao.batchAddBook(batchArgs);
}
// 批量修改
public void batchUpdate(List<Object[]> batchArgs){
bookDao.batchUpdateBook(batchArgs);
}
// 批量刪除
public void batchDelete(List<Object[]> batchArgs){
bookDao.batchDeleteBook(batchArgs);
}
}
- 建立 bean1.xml 配置檔案
<!--配置資料庫連線池-->
<bean id="dataSource1" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="jdbc:mysql:///userdb" /><!--資料庫的地址-->
<property name="username" value="root" /><!--使用者名稱-->
<property name="password" value="Kc635908933" /><!--密碼-->
<property name="driverClassName" value="com.mysql.jdbc.Driver" /> <!--驅動名稱-->
</bean>
<!-- 元件掃描 -->
<context:component-scan base-package="com.spring"></context:component-scan>
<!-- JdbcTemplate 物件 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入 dataSource-->
<!--通過set方法注入-->
<property name="dataSource" ref="dataSource1"></property><!--set方式注入-->
</bean>
<!-- 註冊類 -->
<bean id="bookDaoImpl" class="com.spring.dao.BookDaoImpl"></bean>
<bean id="bookService" class="com.spring.service.BookService">
<property name="bookDao" ref="bookDaoImpl"/>
</bean>
</beans>
- 測試類 TestBook
public class TestBook {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService", BookService.class);
// 新增資料
// Book book = new Book();
// book.setUserid("66");
// book.setUsername("hh");
// book.setUserpwd("343242");
// bookService.addBook(book);
// // 修改資料
// Book book = new Book();
// book.setId("10");
// book.setBookname("kc");
// book.setBookname("30");
// bookService.updateBook(book);
//
// // 刪除資料
// bookService.deleteBook("8");
// // 查詢1
int count = bookService.findCount();
System.out.println(count);
//
// // 查詢2
Book book = bookService.findOne("66");
System.out.println(book);
//
// // 查詢3
List<Book> all = bookService.findAll();
System.out.println(all);
// 批量新增
// List<Object[]> batchArgs = new ArrayList<>(); // 陣列形式
// Object[] o1 = {"3","java","c++"};
// Object[] o2 = {"4","nba","ncaa"};
// Object[] o3 = {"5","ball","mysql"};
// batchArgs.add(o1);
// batchArgs.add(o2);
// batchArgs.add(o3);
// bookService.batchAdd(batchArgs);
// 批量修改
// List<Object[]> batchArgs = new ArrayList<>(); // 陣列形式
// Object[] o1 = {"java","111","3"};
// Object[] o2 = {"nba","222","4"};
// Object[] o3 = {"ball","333 ","5"};
// batchArgs.add(o1);
// batchArgs.add(o2);
// batchArgs.add(o3);
// bookService.batchUpdate(batchArgs);
// 批量刪除
// List<Object[]> batchArgs = new ArrayList<>(); // 陣列形式
// Object[] o1 = {"3"};
// Object[] o2 = {"4"};
// Object[] o3 = {"5"};
// batchArgs.add(o1);
// batchArgs.add(o2);
// batchArgs.add(o3);
// bookService.batchDelete(batchArgs);
}
}
2.3 使用 Mybatis 實現
- 建立資料表 User 實體類
public class User {
private int id;
private String name;
private String pwd;
// 無參構造
public User() {
}
// 有參構造
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
- 建立 UserMapper 介面類
public interface UserMapper {
// 查詢所有使用者
List<User> getUserList();
//根據ID查詢使用者
User getUserById(int id);
// 模糊查詢
List<User> getUserLike(String value);
// 使用map新增使用者
int addUser2(Map<String, Object> map);
// 插入
int addUser(User user);
// 更新
int updateUser(User user);
// 刪除
int deleteUser(int id);
}
- 定義 UserMapper.xml 配置檔案(實現 UserMapper 介面類)
<!-- 定義介面 -->
<mapper namespace="com.dao.UserMapper">
<!-- 查詢 -->
<!-- resultType==返回型別 -->
<!-- id=介面類方法 -->
<select id="getUserList" resultType="com.pojo.User">
select * from mybatis.user
</select>
<!-- 根據id號查詢 -->
<select id="getUserById" resultType="com.pojo.User" parameterType="int">
select * from mybatis.user where id = #{id}
</select>
<!-- 模糊查詢 -->
<select id="getUserLike" resultType="com.pojo.User" parameterType="String">
select * from mybatis.user where name like "%"#{value}"%"
</select>
<!-- 插入 -->
<!--物件中的屬性,可以直接取出來-->
<insert id="addUser" parameterType="com.pojo.User">
insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd});
</insert>
<!-- 使用map插入-->
<insert id="addUser2" parameterType="map">
insert into mybatis.user(id, name, pwd) values (#{Userid},#{Username},#{Userpwd})
</insert>
<!-- 更新 -->
<update id="updateUser" parameterType="com.pojo.User">
update mybatis.user set name=#{name},pwd=#{pwd} where id = #{id} ;
</update>
<!-- 刪除 -->
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id = #{id}
</delete>
</mapper>
- 定義 mybatis-config 配置檔案
<!--configuration核心配置檔案-->
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="Kc635908933"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="UserMapper.xml"></mapper>
</mappers>
</configuration>
- 建立 MyBatisUtils 工具類
// sqlSessionFactory ---> sqlSession
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static{
try {
// 使用Mybatis第一步:獲取sqlSessionFactory物件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//既然有了 SqlSessionFactory,顧名思義,我們就可以從中獲得 SqlSession 的例項了。
// SqlSession 完全包含了面向資料庫執行 SQL 命令所需的所有方法。
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
- 測試類 Test
public class UserMapper_Test {
@Test
public void getUserList() {
//第一步:獲得SqlSession物件
SqlSession sqlSession = MybatisUtils.getSqlSession();
//方式一:getMapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = userMapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
//關閉SqlSession
sqlSession.close();
}
@Test
public void getUserById(){
//第一步:獲得SqlSession物件
SqlSession sqlSession = MybatisUtils.getSqlSession();
//方式一:getMapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(4);
System.out.println(user);
//關閉SqlSession
sqlSession.close();
}
@Test
public void getUserLike(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = userMapper.getUserLike("李");
for(User user : userList){
System.out.println(user);
}
sqlSession.close();
}
@Test
public void addUser(){
//第一步:獲得SqlSession物件
SqlSession sqlSession = MybatisUtils.getSqlSession();
//方式一:getMapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int num = userMapper.addUser(new User(4,"kuangcheng","123456"));
System.out.println(num);
// 提交事物
sqlSession.commit();
// 查詢所有事物
List<User> userList = userMapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
//關閉SqlSession
sqlSession.close();
}
@Test
public void addUser2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 建立 map
Map map = new HashMap();
map.put("Userid", 12);
map.put("Username", "cat");
map.put("Userpwd", "1234595");
int num = userMapper.addUser2(map);
System.out.println(num);
// 提交事物
sqlSession.commit();
// 關閉 sqlSession
sqlSession.close();
}
@Test
public void updateUser(){
//第一步:獲得SqlSession物件
SqlSession sqlSession = MybatisUtils.getSqlSession();
//方式一:getMapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int num = userMapper.updateUser(new User(4,"kc","88888888"));
System.out.println(num);
// 提交事物
sqlSession.commit();
//關閉SqlSession
sqlSession.close();
}
@Test
public void deleteUser(){
//第一步:獲得SqlSession物件
SqlSession sqlSession = MybatisUtils.getSqlSession();
//方式一:getMapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int num = userMapper.deleteUser(52);
System.out.println(num);
// 提交事物
sqlSession.commit();
//關閉SqlSession
sqlSession.close();
}
}
2.4 [ 拓展 ] 使用 Spring 整合 Mybatis
3. 總結
- 推薦使用 Mybatis 框架,省心省力;
- 但技術沒有優劣之分,單純使用 Jdbc 也能很好的實現具體操作;
- 沒有最好的,只有合適的,看自己的需求