传统JDBC与MyBatis 在Java应用程序中,数据库操作是一个重要的组成部分。传统JDBC(Java Database Connectivity)是Java提供的一种标准API,用于与关系型数据库进行交互。然而,传统JDBC存在一些不足之处,如代码冗余、手动管理数据库连接等。MyBatis作为一种持久层框架,提供了更灵活、高效的数据库操作方式。以下是MyBatis相较于传统JDBC的优点:
基于SQL语句编程,相当灵活
MyBatis允许开发者直接编写SQL语句,并将SQL语句写在XML文件中。这种方式使得SQL语句的管理和维护更加方便,同时也支持编写动态SQL,提高了SQL语句的可重用性。
减少了50%的代码量,消除了JDBC大量冗余代码
MyBatis通过提供简洁的API和自动化的数据库连接管理,减少了传统JDBC中大量的冗余代码。开发者无需手动管理数据库连接的打开和关闭,也无需编写繁琐的SQL语句拼接代码。
与数据库兼容性高
MyBatis与数据库的兼容性非常高,只要JDBC兼容的数据库,MyBatis都支持。这意味着开发者可以在不同的数据库之间轻松切换,而无需修改大量的代码。
提供映射标签,支持对象与数据库的ORM字段关系映射
MyBatis提供了丰富的映射标签,支持对象与数据库的ORM(Object-Relational Mapping)字段关系映射。开发者可以通过简单的配置,将数据库表中的字段映射到Java对象的属性上,从而简化了数据操作的复杂性。
JDBC连接数据库步骤 Java JDBC连接数据库的一般步骤如下:
1. 加载数据库驱动
在连接数据库之前,需要加载相应的数据库驱动。不同的数据库有不同的驱动类名。该步骤在Spring Boot中通常通过配置文件自动完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;public class JdbcExample { public static void main (String[] args) { String driver = "com.mysql.cj.jdbc.Driver" ; try { Class.forName(driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
2. 建立数据库连接
使用驱动类中的getConnection(url, userName, password)
方法来连接数据库。
3. 创建Statement实例对象
通过上一步获得的数据库连接对象,调用createStatement
方法创建一个Statement
对象,用于执行SQL语句。
4. 执行SQL语句
使用Statement
对象的executeQuery
或executeUpdate
方法执行SQL语句。
5. 取出SQL运行结果
执行SQL语句后,可以通过ResultSet
对象获取查询结果。
6. 关闭连接
在执行完数据库操作后,要关闭数据库连接以避免占用资源。关闭连接需要逐级进行,即先关闭ResultSet
,再关闭Statement
,最后是Connection
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class JdbcExample { public static void main (String[] args) { String url = "jdbc:mysql://localhost:3306/mydb" ; String user = "root" ; String password = "root" ; String sql = "SELECT * FROM users" ; Connection conn = null ; Statement stmt = null ; ResultSet rs = null ; try { conn = DriverManager.getConnection(url, user, password); stmt = conn.createStatement(); rs = stmt.executeQuery(sql); while (rs.next()) { System.out.println(rs.getString("name" )); } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (rs != null ) rs.close(); if (stmt != null ) stmt.close(); if (conn != null ) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
原生MyBatis的应用 在Spring Boot项目中使用原生的MyBatis进行数据库操作,需要按照以下步骤进行配置和开发。以下是详细的步骤说明:
1. 配置MyBatis
在项目的pom.xml
中引入MyBatis的依赖。
1 2 3 4 5 <dependency > <groupId > org.mybatis.spring.boot</groupId > <artifactId > mybatis-spring-boot-starter</artifactId > <version > 2.1.4</version > </dependency >
在项目的application.yml
或application.properties
中配置数据源。
1 2 3 4 5 6 7 8 9 10 spring: datasource: url: jdbc:mysql://localhost:3306/mydb username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.model
在项目结构中创建SQL映射文件Mapper。xml
,通常放在src/main/resources/mapper
目录下。
2. 创建实体
创建用于映射数据库表的实体类,字段名与类型需要与数据库中对应表保持一致。
1 2 3 4 5 6 7 8 9 package com.example.model;public class User { private Long id; private String name; private String email; }
3. 编写SQL映射文件
创建XML文件,定义SQL语句和映射关系。
1 2 3 4 5 6 <mapper namespace ="com.example.dao.UserDao" > <select id ="getUserById" parameterType ="long" resultType ="User" > SELECT * FROM users WHERE id = #{id} </select > </mapper >
4. 编写DAO接口
创建DAO接口,定义数据库操作方法。
1 2 3 4 5 6 7 package com.example.dao;import com.example.model.User;public interface UserDao { User getUserById (Long id) ; }
5. 编写具体的SQL语句
在SQL映射文件中实现DAO接口,编写具体的SQL语句。
1 2 3 4 5 6 <mapper namespace ="com.example.dao.UserDao" > <select id ="getUserById" parameterType ="long" resultType ="User" > SELECT * FROM users WHERE id = #{id} </select > </mapper >
6. 调用DAO操作方法
在服务层或控制层调用DAO中的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.example.service;import com.example.dao.UserDao;import com.example.model.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Service public class UserService { @Autowired private UserDao userDao; public User getUserById (Long id) { return userDao.getUserById(id); } }
MyBatis中#
与$
区别 在MyBatis中,#{}
和${}
是两种不同的参数占位符,它们在处理SQL语句时有着不同的行为和用途。以下是对这两种占位符的详细解释及其区别:
#{}
占位符MyBatis在处理#{}
时,会创建预编译的SQL语句,将#{}
替换为?
,在具体执行SQL时会为预编译中的?
赋值,调用PreparedStatement
的set
方法来赋值。
预编译SQL :预编译的SQL执行效率高,因为数据库可以缓存预编译的SQL语句,减少了解析和编译的开销。
防止SQL注入 :预编译的SQL语句可以防止SQL注入攻击,因为参数值会被正确地转义和处理。
安全性高 :适合传递参数,特别是用户输入的参数。
1 2 3 <select id ="getUserById" parameterType ="long" resultType ="User" > SELECT * FROM users WHERE id = #{id} </select >
${}
占位符MyBatis在处理${}
时,只会创建普通的SQL语句,然后在执行SQL语句时将参数拼接到SQL中。
优点:
灵活性高 :适合用于动态SQL拼接,如动态表名、列名等。
缺点:
不能防止SQL注入 :因为参数直接拼接到SQL语句中,如果参数未经过校验、过滤,可能会导致安全问题。
执行效率低 :每次执行SQL语句时都需要重新解析和编译SQL,效率较低。
1 2 3 <select id ="getUserByDynamicColumn" parameterType ="map" resultType ="User" > SELECT * FROM users WHERE ${column} = #{value} </select >
区别总结
特性
#{}
占位符
${}
占位符
处理方式
预编译SQL,替换为?
,调用set
方法
直接拼接参数到SQL语句中
执行效率
高(预编译SQL)
低(每次都需要解析和编译SQL)
安全性
高(防止SQL注入)
低(不能防止SQL注入)
适用场景
传递参数(特别是用户输入的参数)
动态SQL拼接(如动态表名、列名等)
**优先使用#{}
**:在大多数情况下,优先使用#{}
占位符,因为它提供了更高的安全性和执行效率。
**谨慎使用${}
**:仅在需要动态拼接SQL语句时使用${}
,并确保对参数进行严格的校验和过滤,以防止SQL注入攻击。
MyBatis与MyBatis Plus区别 MyBatis Plus是一个基于MyBatis的增强工具库,旨在简化开发并提高开发效率。以下是MyBatis Plus相较于MyBatis的主要区别和增强功能:
CURD操作
MyBatis Plus通过集成BaseMapper
接口,提供了一系列内置的快捷方法,使得CURD操作更加简单,无需编写重复的SQL语句。
1 2 3 public interface UserMapper extends BaseMapper <User> { }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <mapper namespace ="com.example.dao.UserDao" > <select id ="getUserById" parameterType ="long" resultType ="User" > SELECT * FROM users WHERE id = #{id} </select > <insert id ="insertUser" parameterType ="User" > INSERT INTO users (name, email) VALUES (#{name}, #{email}) </insert > <update id ="updateUser" parameterType ="User" > UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id} </update > <delete id ="deleteUser" parameterType ="long" > DELETE FROM users WHERE id = #{id} </delete > </mapper >
代码生成器
MyBatis Plus提供了代码生成器功能,可以根据数据库表结构自动生成实体类、mapper接口以及XML映射文件,减少了手动编写的工作量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class CodeGenerator { public static void main (String[] args) { AutoGenerator mpg = new AutoGenerator (); DataSourceConfig dsc = new DataSourceConfig (); dsc.setUrl("jdbc:mysql://localhost:3306/mydb" ); dsc.setDriverName("com.mysql.cj.jdbc.Driver" ); dsc.setUsername("root" ); dsc.setPassword("root" ); mpg.setDataSource(dsc); StrategyConfig strategy = new StrategyConfig (); strategy.setNaming(NamingStrategy.underline_to_camel); strategy.setColumnNaming(NamingStrategy.underline_to_camel); strategy.setEntityLombokModel(true ); strategy.setRestControllerStyle(true ); mpg.setStrategy(strategy); mpg.execute(); } }
通用方法封装
MyBatis Plus封装了许多常用的方法,如条件构造器、排序、分页查询等,简化了开发过程。
1 2 3 4 5 public List<User> getUsersByCondition (String name, Integer age) { QueryWrapper<User> queryWrapper = new QueryWrapper <>(); queryWrapper.like("name" , name).eq("age" , age); return userMapper.selectList(queryWrapper); }
分页插件
MyBatis Plus内置了分页插件,可以轻松实现分页查询功能。
1 2 3 4 public IPage<User> getUsersByPage (int page, int size) { Page<User> pageParam = new Page <>(page, size); return userMapper.selectPage(pageParam, null ); }
多租户支持
MyBatis Plus :MyBatis Plus提供了多租户支持,可以轻松实现多租户数据隔离的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Configuration public class MyBatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor () { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor (); interceptor.addInnerInterceptor(new TenantLineInnerInterceptor (new TenantLineHandler () { @Override public Expression getTenantId () { return new LongValue (1L ); } @Override public String getTenantIdColumn () { return "tenant_id" ; } })); return interceptor; } }
注解支持
MyBatis Plus提供了丰富的注解支持,如@TableName
、@TableId
、@TableField
等,简化了实体类的配置。
1 2 3 4 5 6 7 8 9 @TableName("users") public class User { @TableId(type = IdType.AUTO) private Long id; private String name; private String email; }