JDBC、Druid数据库连接池 和DBUtils

JDBC、Druid数据库连接池 和DBUtils

☄️ 满足你光速复习JDBC有关实用技巧直到并包含spring系列的JDBCTemplate。
☔ 忘了就来看,既有文档简洁也有笔记温度

会用到的有关Mysql知识点的快速回忆整理

1 JDBC数据库

1.1 JDBC数据库连接基础

JDBC(Java DataBase Connectivity)为访问不同数据库提供统一的接口,不同的数据库厂商实现接口。

java程序员只需要使用JDBC,就可以连接任何提供了JDBC驱动程序的数据库系统。本文使用mysql数据库

序号程序编写步骤
1注册驱动
2获取连接
3执行操作
4释放资源
注册驱动
获取连接
执行操作
释放资源

1.2 JDBC 常用类的用法介绍

先看一眼,先了解就行。看到代码就懂了。先看代码也可(1.2.6 练习)。

包含sql注入、批处理、事务的操作。复习嘛,快就完了(哈哈),看api一下就想起来。想不起来的小笨蛋,看对应的代码。

1.2.1 Driver 驱动对象

注册两种方法

mysql5之后可以省略注册驱动的步骤,不需要通过DriverManager调用静态方法registerDriver()。

Driver类被加载就可以了。

1、new 一个driver实例

2、通过反射,进行类加载。class.forname(String classFullpath)

1.2.2 DriverManger 驱动管理对象

序号方法含义
1static Connection getConnection(String url, String username, String password)获取连接Connection对象
url :jdbc:mysql://ip地址(域名):端口号/数据库名称
想实现批处理在url后加rewriteBatchedStatements=true
user:数据库用户名
password:数据库密码
2-1setAutoCommit(boolean autoCommit)参数为false,则开启事务
2-2commit()提交事务
2-3rollback()回滚事务

1.2.3 Connection 连接对象

序号方法含义
1Statement createStatement();获取普通执行对象,Statement对象,用来执行sql语句的对象。不防止sql注入,不建议使用
1PreparedStatement prepareStatement(String sql)获取预编译执行对象,PrepareStatement对象,用来执行sql语句的对象。有效防止sql注入,不建议使用
2void close();释放资源,关闭连接。

1.2.4 Statement 普通执行对象

可以学习,但不推荐 。因为其不能防止sql注入。大多数情况被PrepareStatement对象代替。

序号方法含义
1ResultSet executeQuery()执行DQL语句(select 语句)。根据查询返回封装了查询结果的对象,ResultSet对象。
2int executeUpdate()执行DML语句(create、delete、insert语句)。返回影响行数(返回大于0的数表示执行成功,反之sql语句执行失败)
3void close()释放资源

1.2.4 PrepareStatement 预处理执行对象

预编译sql语句的执行者对象。在执行sql语句之前,将sql语句进行提前编译

明确sql语句的格式后,格式不会改变内容整体都会认为是参数

能防止sql注入还能批量处理sql语句

序号方法含义
1ResultSet executeQuery()执行DQL语句(select 语句)。根据查询返回封装了查询结果的对象,ResultSet对象。
2int executeUpdate()执行DML语句(create、delete、insert语句)。返回影响行数(返回大于0的数表示执行成功,反之sql语句执行失败)
3void close()释放资源
4-1setAutoCommit(boolean autoCommit)开启事务 。参数为false,则开启事务。
4-2commit()提交事务
4-3rollback()回滚事务
5-1addBatch()添加需要批处理的sql语句
5-2executeBatch()执行批量处理语句
5-3clearBatch()清空批处理包的语句

1.2.5 ResultSet 查询结果封装对象

看一眼,看到代码就明白了。

表示查询结果集的数据表

ResultSet对象保持一个光标指向数据行,一行行的判断有无数据,下移光标读取。(next()方法和while配合)

序号方法含义
1boolean next()判断是否还有数据。
true:有数据,并将索引下移
2void close()释放资源
3String getString(String name)返回字符串。获取改行数据列名为name的字符串
还有很多类似放方法。想返回什么类型数据"get数据类型"=。大同小异,具体查看API
4String getString(int index)index 从1开始,作用与上一致

1.2.6 练习

实现代码,说穿就是API。照着前面列好的API看

mysqlLogin.properties

user=root
url=jdbc\:mysql\://localhost\:3306/revJ?rewriteBatchedStatements=true
password=mima
driver=com.mysql.jdbc.Driver
Properties properties = new Properties();
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {

    properties.load(new FileInputStream("./mysqlLogin.properties"));
    String classFullPath = properties.getProperty("driver");
    String url = properties.getProperty("url");
    String user = properties.getProperty("user");
    String password = properties.getProperty("password");
//一、动态加载Driver
    Class.forName(classFullPath);
//二、获取连接 通过DriverManger
    connection = DriverManager.getConnection(url, user, password);
//三、数据库操作 执行查找操作
    String sql = "select * from test1 where id > ?";
    preparedStatement = connection.prepareStatement(sql);
    preparedStatement.setInt(1, 2);
    resultSet = preparedStatement.executeQuery();
    while (resultSet.next()) {
        int id = resultSet.getInt(1);
        String name = resultSet.getString("name");
        System.out.printf("id=%d,name=%s\n", id, name);
    }
//    String sql = "insert into test1 value(?,?)";
//    preparedStatement = connection.prepareStatement(sql);
//    preparedStatement.setInt(1,9);
//    preparedStatement.setString(2,"yu9");
//    int effectRowNum = preparedStatement.executeUpdate();
//    System.out.println(effectRowNum>0?String.format("执行成功,影响%d行",effectRowNum):"执行失败");

} catch (IOException | ClassNotFoundException | SQLException e) {
    e.printStackTrace();
} finally {
//四、释放资源
    try {
        if (resultSet != null) {
            resultSet.close();
        }
        if (preparedStatement != null) {
            preparedStatement.close();
        }
        if (connection != null) {
            connection.close();
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
}
System.out.println("---结束---");

1.3 批处理

真有小笨蛋,看api想不来呀,呜呜,好吧。我也一样。上代码。

url后要加 rewriteBatchedStatements=true

String sql = "insert into test1 value(?,?)";
preparedStatement = connection.prepareStatement(sql);
//批量添加数据 向test1表种添加50条数据
for (int i = 1; i <= 50; i++) {
    preparedStatement.setInt(1,i);
    preparedStatement.setString(2,"yu"+i);
//1、addBatch()
    preparedStatement.addBatch();
//2、executeBatch()
//3、clearBatch()
    if(i%10==0) {
        preparedStatement.executeBatch();
        preparedStatement.clearBatch();
    }
}

1.4 事务

Properties properties = new Properties();
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
    properties.load(new FileInputStream("./mysqlLogin.properties"));
    String classFullPath = properties.getProperty("driver");
    String url = properties.getProperty("url");
    String user = properties.getProperty("user");
    String password = properties.getProperty("password");
    Class.forName(classFullPath);
    connection = DriverManager.getConnection(url, user, password);
//1、看这里 根注释走
    connection.setAutoCommit(false);
    String sql = "insert into test1 value(?,?)";
    preparedStatement = connection.prepareStatement(sql);
    preparedStatement.setInt(1, 51);
    preparedStatement.setString(2, "yu51");
    int effectRowNum = preparedStatement.executeUpdate();
//故意出现异常、测试是否会回滚事务
    //会失败(我设计的)异常会导致事务回滚
    int cuo = 10 /0;
//3、 事务提交 
    connection.commit();
} catch (Exception e) {
    e.printStackTrace();
//2、事务回滚
    connection.rollback();
    System.out.println("执行失败");
} finally {
    try {
        if (resultSet != null) {
            resultSet.close();
        }
        if (preparedStatement != null) {
            preparedStatement.close();
        }
        if (connection != null) {
            connection.close();
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
}
System.out.println("---结束---");

1.5 JDBC utils

使用JDBC的基本代码不会变,每次用都写一样的代码,啰嗦!封装起来,下次还能用。


import java.io.FileInputStream;
import java.sql.*;
import java.util.Properties;

/**
 * @author Jyu
 * @version 1.0
 */
public class JDBCUtils {
    private static String user;
    private static String password;
    private static String url;
    private static String driver;

    static {
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream("./mysqlLogin.properties"));
            user = properties.getProperty("user");
            password = properties.getProperty("password");
            url = properties.getProperty("url");
            driver = properties.getProperty("driver");
            Class.forName(driver);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static Connection getConnection() {
        try {
            return DriverManager.getConnection(url,user,password);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }


    public static void close(ResultSet resultSet, Statement statement, Connection connection) {
        try {
            if(resultSet != null) {
                resultSet.close();
            }
            if(statement != null) {
                statement.close();
            }
            if(connection!= null) {
                connection.close();
            }

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

}

2 数据库连接池

2.1 数据库c3p0

我们用到:

  • c3p0-0.9.1.2.jar

c3p0-config.xml

<c3p0-config>
<!-- 数据源的名称代表连接池 -->
  <named-config name="hello"> 
<!-- 驱动类 -->
  <property name="driverClass">com.mysql.jdbc.Driver</property>
  <!-- url-->
  <!-- url=jdbc:mysql://ip:端口/数据库名 -->
  	<property name="jdbcUrl">jdbc:mysql://localhost:3306/girls</property>
  <!-- 用户名 -->
  	<property name="user">root</property>
  	<!-- 密码 -->
  	<property name="password">root</property>
  	<!-- 每次增长的连接数-->
    <property name="acquireIncrement">5</property>
    <!-- 初始的连接数 -->
    <property name="initialPoolSize">10</property>
    <!-- 最小连接数 -->
    <property name="minPoolSize">5</property>
   <!-- 最大连接数 -->
    <property name="maxPoolSize">10</property>

	<!-- 可连接的最多的命令对象数 -->
    <property name="maxStatements">5</property> 
    
    <!-- 每个连接对象可连接的最多的命令对象数 -->
    <property name="maxStatementsPerConnection">2</property>
  </named-config>
</c3p0-config>

获取连接方式

//1. 将 c3p0 提供的 c3p0.config.xml 拷贝到 src 目录
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("hello");
Connection connection = comboPooledDataSource.getConnection();

2.2Druid 数据库连接池

我们用到:

  • druid-1.1.10.jar

druid.properties

#key=value
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/revj?rewriteBatchedStatements=true
#url=jdbc:mysql://ip:端口/数据库名
username=root
password=ysk
#initial connection Size
initialSize=10
#min idle connecton size
minIdle=5
#max active connection size
maxActive=20
#max wait time (5000 mil seconds)
maxWait=5000

获取连接方式

Properties properties = new Properties();
properties.load(new FileInputStream("src/druid.properties"));
//1、看这里
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
Connection connection = dataSource.getConnection();

2.3JDBCUtilsByDruid


import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * @author xiaoyu
 * @version 1.0
 */
public class JDBCUtilsByDruid {
    private static DataSource dataSource;

    //dataSource初始化
    static {
        try {
            Properties properties = new Properties();
            //properties.load(new FileInputStream("src\\druid.properties"));
            properties.load(JDBCUtilsByDruid.class.getClassLoader().getResourceAsStream("druid.properties"));
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }

    public static void close(ResultSet resultSet, Statement statement, Connection connection) {
        try {
            if(resultSet != null) {
                resultSet.close();
            }
            if(statement != null){
                statement.close();
            }
            if(connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

}

3 Apache—DBUtils

我们用到

  • commons-dbutils-1.3.jar

3.1QueryRunner

序号方法含义
1public T query(Connection conn, String sql, ResultSetHandler rsh, Object… params)执行DQL语句(select 语句)
ResultSetHandler是一个接口,参数是一个其实现类对象
Object… param :就是给 sql 语句中的? 赋值,可以有多个值,所以是可变参数
2public int update(Connection conn, String sql, Object… params)执行DML语句(create、delete、insert语句
3public int[] batch(Connection conn, String sql, Object[] []params)批处理

3.2 ResultSetHandler接口

BeanHandler 将查询结果的一行封装到javaBean对象

Bean ListHandler 将查询结果的每一行封装到javaBean对象,然后再存入List集合

ScalerHandler 将结果集第一行的某一列放到某个对象中

还有很多,根据需要看api吧

3.3 BasicDAO




import TestDurid.utils.JDBCUtilsByDruid;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
 * @author xiaoyu
 * @version 1.0
 * BasicDAO 是其他类的父类
 */

public class BasicDAO<T> { //泛型指定具体类型
    private QueryRunner queryRunner = new QueryRunner();

    //开发通用的dml方法, 针对任意的表
    public int update(String sql,Object... parameters){
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return queryRunner.update(connection,sql,parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtilsByDruid.close(null, null, connection);
        }
    }

    public Object queryScalar(String sql, Object... parameters){
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return queryRunner.query(connection,sql,new ScalarHandler(),parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtilsByDruid.close(null, null, connection);
        }
    }

    public T querySingle(String sql,Class<T> clazz, Object... parameters) {
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return queryRunner.query(connection,sql, new BeanHandler<T>(clazz),parameters);
        } catch (SQLException e) {
           throw new RuntimeException(e);
        } finally {
            JDBCUtilsByDruid.close(null,null,connection);
        }
    }

    public List<T> queryMulti(String sql,Class<T> clazz, Object... parameters){
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return queryRunner.query(connection,sql,new BeanListHandler<T>(clazz),parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtilsByDruid.close(null, null, connection);
        }
    }
}

4 JavaWeb事务

javaWeb中的使用,利用过滤器

4.1TransactionFilter

public class TransactionFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        try {
            filterChain.doFilter(servletRequest,servletResponse);
            JDBCUtilsByDruid.commit();
        } catch (Exception e) {
            JDBCUtilsByDruid.rollBack();
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Override
    public void destroy() {

    }
}

4.2 JDBCUtilsByDruid

package com.jyu.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * @author xiaoyu
 * @version 1.0
 */
public class JDBCUtilsByDruid {
    private static DataSource dataSource;
    private static ThreadLocal<Connection> threadLocalConnection = new ThreadLocal<>();

    //dataSource初始化
    static {
        try {
            Properties properties = new Properties();
            properties.load(JDBCUtilsByDruid.class.getClassLoader().getResourceAsStream("druid.properties"));
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection()  {
        Connection connection = threadLocalConnection.get();
        if(connection == null ){
            try {
                connection = dataSource.getConnection();
                connection.setAutoCommit(false);
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
            threadLocalConnection.set(connection);
        }
        return connection;
    }

    public static void commit(){
        Connection connection = threadLocalConnection.get();
        if(connection != null){
            try {
                connection.commit();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            } finally {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            threadLocalConnection.remove();
        }
    }

    public static void rollBack(){
        Connection connection = threadLocalConnection.get();
        if(connection != null){
            try {
                connection.rollback();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            } finally {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        threadLocalConnection.remove();
    }

    public static void close(ResultSet resultSet, Statement statement, Connection connection) {
        try {
            if(resultSet != null) {
                resultSet.close();
            }
            if(statement != null){
                statement.close();
            }
            if(connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

}

4.3 BasicDAO

package com.jyu.dao;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import com.jyu.utils.JDBCUtilsByDruid;

/**
 * @author xiaoyu
 * @version 1.0
 * BasicDAO(事务) 是其他类的父类
 */

public class BasicDAO<T> { //泛型指定具体类型
    private QueryRunner queryRunner = new QueryRunner();

    //开发通用的dml方法, 针对任意的表 sql增、删、改语句
    public int update(String sql,Object... parameters){
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return queryRunner.update(connection,sql,parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public Object queryScalar(String sql, Object... parameters){
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return queryRunner.query(connection,sql,new ScalarHandler(),parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public T querySingle(String sql,Class<T> clazz, Object... parameters) {
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return queryRunner.query(connection,sql, new BeanHandler<T>(clazz),parameters);
        } catch (SQLException e) {
           throw new RuntimeException(e);
        }
    }

    public List<T> queryMulti(String sql,Class<T> clazz, Object... parameters){
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return queryRunner.query(connection,sql,new BeanListHandler<T>(clazz),parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

5 JDBCTemplate

这里要思考的是如何使用api,而不是如何记住。在拿到陌生的工具时,如何能快速上手呢。😸

bean.xml 配置文件

<!--    配置要扫描的包-->
    <context:component-scan base-package="com.jyu.spring.txhome"/>
<!--    配置引入外部属性文件-->
    <context:property-placeholder location="classpath:c3p0-config.properties"/>
<!--    配置数据源-->
    <bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSource">
        <property name="driverClass" value="${driverClass}"/>
        <property name="jdbcUrl" value="${jdbcUrl}"/>
        <property name="user" value="${user}"/>
        <property name="password" value="${password}"/>
    </bean>
<!--   配置JDBCTemplate-->
    <bean class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource"/>
    </bean>
<!--    配置事务管理器-->
    <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
        <constructor-arg name="dataSource" ref="dataSource"/>
    </bean>
<!--    配置开启基于注解的事务管理功能-->
    <tx:annotation-driven transaction-manager="transactionManager"/>

c3p0-config.properties

driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/revj?rewriteBatchedStatements=true
user=root
password=ysk
acquireIncrement=5
initialPoolSize=10
minPoolSize=5
maxPoolSize=10
maxStatements=5
maxStatementsPerConnection=2

5.1 JDBCTemplate的常用方法

序号作用补充
1-1public T queryForObject(String sql, Class requiredType, Object… args)返回单行单列
1-2public T queryForObject(String sql, RowMap rowMapper, Object… args)返回一行数据,封装到beanRowMap是接口,常用实现类BeanPropertyRowMapper
BeanPropertyRowMapper(Class<T> mappedClass)
1-3public List query(String var1, RowMapper var2, Object… var3)返回多行数据,封装到List
2public int upata(String sql, Object… args)更新数据,返回受影响的行数
3public int[] batchUpdate(String sql, List<Object[]> batchArgs)批量操作

返回单行单列

String sql = "SELECT name FROM monster WHERE id =100";
String name = bean.queryForObject(sql, String.class);
System.out.println(name);

返回单行

public void selectDataByJdbcTemplate() {
	ApplicationContext ioc = new ClassPathXmlApplicationContext("JdbcTemplate_ioc.xml");
    //得到 JdbcTemplate bean
    JdbcTemplate bean = ioc.getBean(JdbcTemplate.class);
    String sql = "SELECT id as monsterId,name,skill FROM monster WHERE id =?";
	//下面这个 rowmapper 是一个接口,可以将查询的结果,封装到你指定的 Monster 对象中. 
    RowMapper<Monster> rowMapper =  new BeanPropertyRowMapper<Monster>(Monster.class);
    Monster monster = bean.queryForObject(sql, rowMapper, 100);
    System.out.println("monster= " + monster);
}

返回多行

String sql = "SELECT id as monsterId,name,skill FROM monster WHERE id >=?";
RowMapper<Monster> rowMapper = new BeanPropertyRowMapper<Monster>(Monster.class);
List<Monster> monster_list = bean.query(sql, rowMapper, 200);

更新

String sql = "UPDATE monster SET skill = ? WHERE id=?";
int affected = bean.update(sql, "美女计", 300);
System.out.println("affected= " + affected);
System.out.println("update data ok~");

批量操作

String sql = "INSERT INTO monster VALUES(?, ?, ?)";
List<Object[]> param_list = new ArrayList<Object[]>();
param_list.add(new Object[]{500, "白蛇精", "吃人"});
param_list.add(new Object[]{600, "青蛇精", "吃小孩"});
bean.batchUpdate(sql, param_list);
System.out.println("batch add ok")

5.2 【具名参数】NamedParamterJDBCTemplate

序号作用解析
1public int update(String sql, Map<String, ?> paramMap)更新数据,返回受影响的行数。根据paramMap填充sql
2public int update(String sql, SqlParameterSource paramSource)更新数据,返回受影响的行数。根据对象属性填充sqlSqlParameterSource是接口,常用的实现类为
BeanPropertySqlParameterSource(Object object)
ApplicationContext ioc =
new ClassPathXmlApplicationContext("JdbcTemplate_ioc.xml");
//得到 NamedParameterJdbcTemplate bean
NamedParameterJdbcTemplate namedParameterJdbcTemplate =
ioc.getBean(NamedParameterJdbcTemplate.class);
String sql = "INSERT INTO monster VALUES(:my_id, :name, :skill)";
Map<String, Object> map_parameter = new HashMap<String, Object>();
map_parameter.put("my_id", 800);
map_parameter.put("name", "螃蟹精");
map_parameter.put("skill", "钳子无敌大法");
namedParameterJdbcTemplate.update(sql, map_parameter);
NamedParameterJdbcTemplate namedParameterJdbcTemplate =
ioc.getBean(NamedParameterJdbcTemplate.class);
String sql = "INSERT INTO monster VALUES(:monsterId, :name, :skill)";
Monster monster = new Monster(900, "狐狸精", "狐媚之术");
SqlParameterSource source = new BeanPropertySqlParameterSource(monster);
namedParameterJdbcTemplate.update(sql, source);

6 声明式事务

声明式事务:该事务是建立在AOP之上的,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或加入一个事务,在执行完目标方法之后根据执行情况提交或回滚事务。

事务传播机制

REQUIRED如果有事务在运行,当前方法就在这个事务内运行,否则就启动一个新事务,并在自己的事务内运行。
REQUIRES_NEW当前方法必须启动事务,并在自己的事务内运行,如果有事务正在运行,就应该将其挂起。
SUPPORTS如果有事务在运行,当前方法就在这个事务内运行,否则它可以不运行在事务中
NOT_SUPPORTED当前方法不应在事务中运行,如果有事务正在运行,将它挂起
MANDATORY当前方法必须运行在事务中运行,如果没有事务正在运行,就抛出异常
NEVER当前方法不应该运行在事务中运行,如果有事务正在运行,就抛出异常
NESTED如果有事务在运行,当前方法就应该在这个事务嵌套的事务内运行,否则就启动一个新事务,并在自己的事务内运行。

@Transtional(propagation=Propagation.REQUIRED, isolation=Isolation.REPLEATED_READER, timeout=2)

基础配置参考mysql基础的事务隔离机制。

timeout 表示超时回滚

如果一个事务执行的时间超过某个时间限制,就让该事务回滚

propagation表示事务传播机制

isolation表示事务隔离级别

MySQL的快忆

猜你准来看
补一点笔记中用到的MySQL知识点,希望能帮到大家快速的回忆、最短时间上手应用。

增删改查

单表的简单操作,恭喜sql入门( ̄﹃ ̄)

select

select (columnName_1,columnName_2) 
from tableName
where 条件表达式
group by 分组列
having 分组后的过滤条件
order by 分组列名1,分组列名2 DESC /*默认升序,desc 升序*/
limit start,rowNum /* 从start行开始,一共rowNum行*/

insert

insert into tableName(列名1,列名2)
values(1列值1,1列值2),
(2列值1,2列值2)

delete

delete from tableName
where 条件

update

update tableName 
set columnName1 =where 条件

MySQL事务

事务用于保证数据的一致性,它是一组相关的dml语句组成的,该组的dml语句要么全部成功,要么全部失败。

start transaction  /* 开启一个事务 */
savepoint 保存点名 /* 设置保存点 */
rollback to 保存点 /* 回退事务 */
rollback /* 回退全部事务 */
commit /*提交事务,所有操作生效,不可回退*/

MySQL只有在InnoDB引擎下才支持使用事务,MyISAM擎不支持事务。不开启事务的默认情况下dml语句是自动提交的不能回滚 。set autocommit=off后默认不再自动提交。

事务隔离机制

多个连接开启各自事务,操作数据库中数据时,数据库系统负责隔离操作,保证各个连接获取数据的准确性。

​ ——韩顺平循序渐进学java

定义纯白话巧记
脏读(dirty read)一个事务读取到另一个事务未提交的改变。读取到未提交的数据
不可重复读
(norepeatable read)
一个事务中多次进行查询,由于其他已提交
的事务进行修改或删除,使其每次查询返回结果集不同。
前后多次读取,数据内容不一致
幻读
(phantom read)
一个事务中多次进行查询,由于其他已提交
的事务进行插入,使其每次查询返回结果集不同。
前后多次读取,数据总量不一致

这篇文章推荐给第一次接触事务的同学,该文中主要列举了有关脏读、不可重复读、幻读的相关案例,能帮助新手更好的理解,值得一读。

【数据库】快速理解脏读、不可重复读、幻读_SunAlwaysOnline的博客-CSDN博客

隔离级别脏读不可重复读幻读加锁读
读未提交(Read uncommitted)✔️✔️✔️不加锁
读已提交(Read committed)✔️✔️不加锁
可重复读(Repeatable read)✔️不加锁
可串行化(Serializable)加锁

SQL92 标准,mysql数据库改进,InnoDB引擎,很大程度不可重复读隔离级别解决了的幻读问题,但是在没有彻底解决
推荐文章:美团三面:一直追问我, MySQL 幻读被彻底解决了吗?

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值