Jdbc和Mybatis的增删改查
- 背景
- 开发前提
- Jdbc
- Mybatis
- 测试出现的问题
背景
在实习期间,结合公司的开发体系架构,在导入公司的综合配置文件依赖之后,在基础上进行Jdbc
和Myabtis
增删改查的联系。
开发前提
建立一个标准的 maven
的项目,SDK
改为自己本地jdk8
位置,修改自己本地的 maven
环境以及仓库引入 springboot
的父依赖项目。导入公司自己封装的依赖包的依赖名称。建立符合要求的包机制,其中主启动类放置的位置需要和依赖自定义扫描的位置一致,否则需要自定义包扫描机制
@ComponentScan(value = "com.mao")
配置 maven
资源导出问题
<build><resources><resource><directory>src/main/resources</directory><excludes><exclude>**/*.properties</exclude><exclude>**/*.xml</exclude></excludes><filtering>false</filtering></resource><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource></resources></build>
mybatis-config.xml
的配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><settings><!-- 这个配置使全局的映射器启用或禁用缓存 --><setting name="cacheEnabled" value="true"/><!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载 --><setting name="lazyLoadingEnabled" value="false"/><!-- 当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载 --><setting name="aggressiveLazyLoading" value="false"/><!-- 允许或不允许多种结果集从一个单独的语句中返回(需要适合的驱动) --><setting name="multipleResultSetsEnabled" value="true"/><!-- 使用列标签代替列名。不同的驱动在这方便表现不同。参考驱动文档或充分测试两种方法来决定所使用的驱动 --><setting name="useColumnLabel" value="true"/><!-- 允许JDBC支持生成的键。需要适合的驱动。如果设置为true则这个设置强制生成的键被使用,尽管一些驱动拒绝兼容但仍然有效(比如Derby) --><setting name="useGeneratedKeys" value="true"/><!-- 指定MyBatis如何自动映射列到字段/属性。PARTIAL只会自动映射简单,没有嵌套的结果。FULL会自动映射任意复杂的结果(嵌套的或其他情况) --><setting name="autoMappingBehavior" value="PARTIAL"/><!-- 配置默认的执行器。SIMPLE执行器没有什么特别之处。REUSE执行器重用预处理语句。BATCH执行器重用语句和批量更新 --><setting name="defaultExecutorType" value="SIMPLE"/><!-- 设置超时时间,它决定驱动等待一个数据库响应的时间 --><setting name="defaultStatementTimeout" value="25000"/><!--<setting name="logImpl" value="STDOUT_LOGGING" />--></settings></configuration>
Jdbc
Jdbc
英文全称Java Database connect
,翻译之后就是Java
数据库连接。
基本的 Jdbc
查询流程
//下面方法有不同的异常,我直接抛出一个大的异常
public static void main(String[] args) throws Exception { //1、导入 mysql 5 的驱动jar包//2、注册驱动Class.forName("com.mysql.jdbc.Driver");//3、获取数据库的连接对象Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/ems", "root", "123456");//4、定义sql语句String sql = "select * from studnet;";//5、获取执行sql语句的对象Statement stat = con.createStatement();//5、执行sql并接收返回结果ResultSet rs = stat.executeQuery(sql);//6、处理结果while (rs.next()){ //循环一次,游标移动一行System.out.println("id:" + rs.getString(1)); // 获取第一列的数据//获取字段为name的数据System.out.println("name:" + rs.getString("name")); System.out.println("age:" + rs.getInt(3)); // 获取第三列的数据System.out.println("score:" + rs.getInt(4)); // 获取第四列的数据}//8、释放资源rs.close();stat.close();con.close();}
建立StudentJdbc
类,组件化方面进行 Jdbc
的增删改查,其中引用到公司的jar包依赖,可能会发生数据源的冲突,如下
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'studentController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'studentJdbc': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected single matching bean but found 2: maoDatasource,hisDatasource
就是不清楚的数据源来源,发生了数据源冲突,注入数据源的时候需要通过 name
属性指定数据源
@Component
public class StudentJdbc {@Resource(name = "maoDatasource")private DataSource dataSource;}
查询全部数据的业务函数,由于在自定义的配置文件中已经连接到本地的数据库了,所以在构造连接的时候采用的是无参构造函数生成 statement
,在最开始生成变量值为null
,在使用的时候进行new
的初始化,查询的时候需要增加一个结果集资源,在结束的时候需要逆向关闭三个连接资源。
public List<Student> jdbcList() throws SQLException {List<Student> list = new ArrayList<>();Connection conn = null;Statement statement = null;ResultSet resultSet = null;try {conn = dataSource.getConnection();// 链接创建 Statementstatement = conn.createStatement();resultSet = statement.executeQuery("select * from student where deleted = 0");// 遍历结果集while (resultSet.next()) {int id = resultSet.getInt("id");String username = resultSet.getString("username");String password = resultSet.getString("password");int deleted = resultSet.getInt("deleted");Student student = new Student(id, username, password,deleted);list.add(student);System.out.println("id:" + resultSet.getInt("id") + "用户名:" + resultSet.getString("username") + "密码" + resultSet.getString("password"));}} catch (SQLException e) {throw new RuntimeException(e);}finally {resultSet.close();statement.close();conn.close();}return list;}
增加函数的代码,使用了预编译 Statement
,防止 SQL
的注入风险,sql
字符串使用占位符 ?
,预编译sql,通过 prepareStatement
放置对象,占位符标识从 1
开始,最终更新执行,结果返回一个 int
型的变量。
public int jdbcAdd(Student student) throws SQLException {Connection conn = null;PreparedStatement preStatement = null;try {conn = dataSource.getConnection();String sql = "insert into student(id,username,password) values (?,?,?);";preStatement = conn.prepareStatement(sql);preStatement.setInt(1,student.getId());preStatement.setString(2,student.getUsername());preStatement.setString(3,student.getPassword());return preStatement.executeUpdate();} catch (SQLException e) {throw new RuntimeException(e);}finally {preStatement.close();conn.close();}}
修改代码实现
public int jdbcUpdate(Student student) throws SQLException {Connection conn = null;PreparedStatement preStatement = null;try {conn = dataSource.getConnection();String sql = "update student set username = ?,password = ? where id = ?;";preStatement = conn.prepareStatement(sql);preStatement.setString(1,student.getUsername());preStatement.setString(2,student.getPassword());preStatement.setInt(3,student.getId());return preStatement.executeUpdate();} catch (SQLException e) {throw new RuntimeException(e);}finally {conn.close();preStatement.close();}}
删除代码实现
public int jdbcRemove(Integer id) throws SQLException {Connection conn = null;PreparedStatement preStatement = null;try {conn = dataSource.getConnection();String sql = "update student set deleted = 1 where id = ?;";preStatement = conn.prepareStatement(sql);preStatement.setInt(1,id);return preStatement.executeUpdate();} catch (SQLException e) {throw new RuntimeException(e);}finally {preStatement.close();conn.close();}}
Mybatis
Mybatis 官方文档
定义的 mappe
r接口
public interface StudentMapper {List<Student> list(String username);int add(Student student);int update(Student student);int remove(Integer id);}
对应 mapper.xml
配置文件 SQL
语句的编写
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sunri.mapper.StudentMapper"><insert id="add" parameterType="com.sunri.entity.Student">insert into student(id,username,password) values (#{id},#{username},#{password});</insert><update id="update">update student<set><if test="username != null">username=#{username},</if><if test="password != null">password=#{password},</if></set>where id = #{id} and deleted = 0;</update><update id="remove">update student set deleted = 1 where id = #{id} and deleted = 0;</update><select id="list" resultType="com.sunri.entity.Student">select * from student<where><if test="username!=null and username!=''">username like '%${username}%'</if>and deleted = 0</where></select></mapper>
测试出现的问题
类似于这种点击发送即可