JDBC(java database connectivity)(java数据库连接)
JDBC即是使用统一的一套java代码操作所有的关系型数据库
注意:在一个模块或项目中所有的jar应该导入到一个libs包中
类似于 Person是接口,Worker是实现类, Person p=new Worker();
public class JDBCDemo01 {
public static void main(String[] args) throws Exception {
//1、导入驱动jar包
//2、注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//3、获取数据库的连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/javawebtest01", "root", "123456");
//4、定义SQL语句
String sql = "update stuinfo set math=100 where id=1";//将id为1的数学成绩改为100
//5、获取执行sql语句的对象
Statement stmt = conn.createStatement();
//6、执行sql语句,接受返回结果
int count = stmt.executeUpdate(sql);
//7、处理结果
System.out.println(count);
//8、释放资源
stmt.close();
conn.close();
}
}
JDBC的各个对象
- DriverManager(驱动管理对象)
- 功能:
- 注册驱动 告诉程序该用哪个数据库驱动jar包
Class.forName(“com.mysql.cj.jdbc.Driver”);也是注册驱动
在Driver类中的静态代码块 DriverManager.registerDriver(new Driver());
也是在用Driver中的registerDriver方法;
mysql5之后该代码块可以不写–>Class.forName(“com.mysql.cj.jdbc.Driver”); - 获取数据库连接
Connection conn = DriverManager.getConnection(url,user,password);
url指定连接的路径 即ip、端口、数据库名称
url写法: jdbc:mysql://ip地址(域名):端口号/数据库名称
若使用本机的3306端口,则url可以简写为–> jdbc:mysql:///javawebtest01
- 注册驱动 告诉程序该用哪个数据库驱动jar包
- 功能:
- Connection(数据库连接对象)
- 功能:获取执行sql的对象
- 管理事务:
- 开启事务setAutoCommit(); 调用该方法设置参数为false,即开启事务
- 提交事务commit();
- 回滚事务rollback();
Statement(执行sql的对象) 不能防止sql注入问题- boolean execute(String sql);执行任意sql语句
- int executeUpdate(String sql); 执行DML(增删改)语句、DDL(对表和库操作)语句
返回值是影响的行数,可以通过影响行数判断DML语句是否执行成功(>0) - ResultSet executeQuery(String sql); 执行DQL(查询)语句
返回结果集对象
- ResultSet(结果集对象) 封装查询到的结果对象
next(); 游标向下移动
get×××(); 获取数据 xxx代表数据类型 如getInt();
该方法参数可以就收int或String,int代表列的编号(1即第一列的值)String代表列的名称 - PreparedStatement(执行sql的对象) 功能比Statement更强大,能防止sql注入问题
抽取JDBC工具类 MyUtils.JDBCUtils
目的->简化书写,简化重复度高的代码
工具类的方法都建议静态,方便调用
JDBC事务管理
在catch中回滚,实现回滚
管理事务:
- 开启事务setAutoCommit(); 调用该方法设置参数为false,即开启事务
- 提交事务commit();
- 回滚事务rollback(); ,在catch中处理
JDBC事务操作以及preparedStatement使用案例↓
public class TestTransaction {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps1 = null;
PreparedStatement ps2 = null;
try {
conn = JDBCUtils.getConnection();
//开启事务
conn.setAutoCommit(false);
String sql1 = "update account set balance=balance-? where id=?";
String sql2 = "update account set balance=balance+? where id=?";
ps1 = conn.prepareStatement(sql1);
ps2 = conn.prepareStatement(sql2);
ps1.setInt(1, 500);
ps1.setInt(2, 1);
ps2.setInt(1, 500);
ps2.setInt(2, 2);
//使用preparedStatement,执行execute函数时不需要传递参数
ps1.executeUpdate();
int a = 3 / 0;//手动制造异常,没使用回滚的话ps1会执行,ps2不会执行,
ps2.executeUpdate();
//执行这里就提交事务
conn.commit();
} catch (Exception e) {
try {
if (conn != null) {
conn.rollback();
}
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
} finally {
JDBCUtils.close(ps1, conn);
JDBCUtils.close(ps2, null);
}
}
}
数据库连接池
数据库连接池:存放数据库连接的容器
当系统初始化后,容器被创建,容器中会申请一些连接对象,↓
用户访问数据库时从容器中获取对象,访问完成之后归还给容器
如果连接对象Connection是从连接池中获取的↓
那么调用Connection.close()方法则不会关闭连接,而是归还给连接池
- 节约资源
- 用户访问高效
- C3P0 数据库连接池技术
- 导入jar包
- 定义配置文件 c3p0.properties 或者 c3p0-config.xml
直接放在src目录下 - 创建核心对象
- 获取连接
public class TestC3P0 {
public static void main(String[] args) throws SQLException {
//1、创建数据库连接池对象
DataSource ds = new ComboPooledDataSource();//使用默认配置,有参数就是指定名称配置
//3、获取数据库连接对象
Connection conn = ds.getConnection();
//归还连接对象到连接池
conn.close();
}
}
- Druid 数据库连接池技术,由Alibaba提供
- 导入jar包
- 定义配置文件properties
- 加载配置文件Properties
- 获取数据库连接对象:通过工厂类来获取DruidDataSourceFactory
- 获取连接
Druid工具类
public class TestDruid {
public static void main(String[] args) throws Exception {
//Druid的配置文件是properties文件可以放在任意位置,起任意名字
Properties pro = new Properties();
InputStream is = TestDruid.class.getClassLoader().getResourceAsStream("DatabaseConnectionPool/druid.properties");
pro.load(is);
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
Connection conn = ds.getConnection();
System.out.println(conn);
}
}
定义Druid工具类
public class DruidUtils {
//定义成员变量
private static DataSource ds;
static {
Properties pro = new Properties();
try {
pro.load(DruidUtils.class.getClassLoader().getResourceAsStream("MyUtils/druid_utils.properties"));
//获取DataSource
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
//释放资源
public static void close(Statement statement, Connection connection) {
/*if (statement != null) {
try {
statement.close();//释放
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();//归还
} catch (SQLException e) {
e.printStackTrace();
}
}*/
close(null, statement, connection);
}
//重载释放
public static void close(ResultSet resultSet, Statement statement, Connection connection) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();//释放
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();//归还
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//获取连接池
public static DataSource getDataSource() {
return ds;
}
}
使用Druid工具类,操作数据库的模板,以后操作数据库就参照如下代码
注意:在同一项目/模板中不能存在内容一样的配置文件
//使用DruidUtils工具类
public class UseDruidUtils {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
//向account表添加记录
try {
//1、获取连接
conn = DruidUtils.getConnection();
//2、定义sql
String sql = "insert into account values(null,?,?);";
//3、获取preparedStatement对象
ps = conn.prepareStatement(sql);
//4、给?赋值
ps.setString(1, "DruidUtils");
ps.setInt(2, 10000);
//5、执行sql
int count = ps.executeUpdate();
System.out.println(count);
} catch (SQLException e) {
e.printStackTrace();
} finally {
DruidUtils.close(ps, conn);
}
}
}
JDBC Template
JDBCTemplate 是Spring框架对JDBC的简单封装
- 导入jar包
如果使用的是 druid jdbcTemplate ,需要导入 ↓
JDBCTemplate jar包5个+druid jar包1个 + 数据库驱动包 - 创建jdbcTemplate对象,依赖数据源DataSource
- 调用jdbcTemplate的方法来完成CRUD(增删改)的操作
update(); 执行DML
queryForMap(); 查询结果,将结果集封装为map集合
queryForList(); 查询结果,结果封装为List集合
query(); 查询结果,将结果封装为JavaBean对象
queryForObject();将查询结果封装为对象
JdbcTemplate基本使用
public class TestTemplate {
public static void main(String[] args) {
//1、创建JdbcTemplate对象
JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
//2、调用方法
String sql = "update account set balance=? where id=?";
int count = template.update(sql, 888, 1);//使用参数给?赋值
System.out.println(count);
}
}
采用Junit单元测试的方法来练习Template的方法
package JDBCTemplate;
import MyUtils.DruidUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
public class Junit_PracticeTemplate {
//Junit单元测试,让方法独立执行
private JdbcTemplate template = null;
private String sql = null;
@Before
public void init() {
template = new JdbcTemplate(DruidUtils.getDataSource());
sql = "";
}
@After
public void end() {
System.out.println("method end !");
}
//1、修改一条记录
@Test
public void test1() {
sql = "update account set balance=? where id=?";
int count = template.update(sql, 666, 1);
System.out.println(count);
}
//2、添加一条记录
@Test
public void test2() {
sql = "insert into account values(?,?,?);";
int count = template.update(sql, null, "黑马程序员", 20000);
System.out.println(count);
}
//3、删除刚刚添加的记录
@Test
public void test3() {
sql = "delete from account where id=?";
int count = template.update(sql, 4);
System.out.println(count);
}
//4、查询id为1的记录,并封装到Map集合中
@Test
public void test4() {
sql = "select * from account where id=?";
//该结果集查询的长度只能是1
//key=列名 value=值
Map<String, Object> map = template.queryForMap(sql, 1);
System.out.println(map);
}
//5、查询所有的记录封装为List集合
@Test
public void test5() {
sql = "select * from stuinfo";
List<Map<String, Object>> list = template.queryForList(sql);
for (Map<String, Object> stringObjectMap : list) {
System.out.println(stringObjectMap);
}
}
//6、查询所有的记录,将其封装为Emp对象的List集合
@Test
public void test6() {
sql = "select * from account";
List<Emp> empList = template.query(sql, new RowMapper<Emp>() {
@Override
public Emp mapRow(ResultSet resultSet, int i) throws SQLException {
Emp emp = new Emp();
int id = resultSet.getInt("id");
String name = resultSet.getString(2);
int balance = resultSet.getInt(3);
emp.setId(id);
emp.setName(name);
emp.setBalance(balance);
return emp;
}
});
for (Emp emp : empList) {
System.out.println(emp);
}
}
//6-2、简化上一个方法
@Test
public void test6_2() {
sql = "select * from account";
List<Emp> empList = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));
for (Emp emp : empList) {
System.out.println(emp);
}
}
//7、查询总记录数
@Test
public void test7() {
sql = "select count(id) from stuinfo";
Long total = template.queryForObject(sql, Long.class);
System.out.println(total);
}
}