一、详细步骤
1、加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
注意:如果连接的是SQLServer
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
2、建立连接
String url = "jdbc:mysql://localhost:3306/javastudy";
String username = "root";
String password = "521216";
Connection connection = null;
//2.获取与数据库的链接
connection = DriverManager.getConnection(url, username, password);
1、数据库URL
URL用于标识数据库的位置,程序员通过URL地址告诉JDBC程序连接哪个数据库。
常用数据库URL地址的写法:
-
Oracle:jdbc:oracle:thin:@localhost:1521:javastudy
-
SqlServer:jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=javastudy
-
MySql:jdbc:mysql://localhost:3306/javastudy
2、Connection
Jdbc程序中的Connection,它用于代表数据库的链接,Collection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,创建方法为:
Connection connection = DriverManager.getConnection(url, user, pass);
这个对象的常用方法:
方法 | 描述 |
---|---|
createStatement() | 创建向数据库发送sql的statement对象。 |
prepareStatement(sql) | 创建向数据库发送预编译sql的PrepareSatement对象。 |
prepareCall(sql) | 创建执行存储过程的callableStatement对象。 |
setAutoCommit(boolean autoCommit) | 设置事务是否自动提交。 |
commit() | 在链接上提交事务。 |
rollback() | 在此链接上回滚事务。 |
3、执行SQL语句
### 1、Statement
Jdbc程序中的Statement对象用于向数据库发送SQL语句,创建方法为:
Statement statement = connection.createStatement();
Statement对象常用方法:
方法 | 含义 |
---|---|
executeQuery(String sql) | 用于向数据发送查询语句。 |
executeUpdate(String sql) | 用于向数据库发送insert、update或delete语句 |
execute(String sql) | 用于向数据库发送任意sql语句 |
addBatch(String sql) | 把多条sql语句放到一个批处理中。 |
executeBatch() | 向数据库发送一批sql语句执行。 |
//3.获取用于向数据库发送sql语句的statement
Statement statement = connection.createStatement();
//4.向数据库发sql
String sql = "select id,name,password,email,birthday from users";
st.executeQuery(sql);
2、PreparedStatement
PreparedStatement接口继承Statement,它的实例对象可以通过调用:
PreperedStatement st = connection.preparedStatement();
PreperedStatement st = null;
String sql = "select * from users where name=? and password=?";
//3.获取用于向数据库发送sql语句的Preperedstatement
st = conn.preparedStatement(sql);//在此次传入,进行预编译
st.setString(1, username);
st.setString(2, password);
//4.向数据库发sql
st.executeQuery();//在这里不需要传入sql
3、PreparedStatement较Statement的优势:
-
代码的可读性和可维护性,PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。
-
Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement 可对SQL进行预编译,从而提高数据库的执行效率。
SQL语句在被DB的编译器编译后,执行代码会被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个涵数)就会得到执行。
当然并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果,以保存有更多的空间存储新的预编译语句。
-
极大地提高了安全性,避免SQL注入的问题
4、获取结果(行列都是从1开始)
Jdbc程序中的ResultSet用于代表Sql语句的执行结果。Resultset封装执行结果时,采用的类似于表格的方式,ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据。
ResultSet rs = null;
//4.向数据库发sql,并获取代表结果集的resultset
String sql = "select id,name,password,email,birthday from users";
rs = st.executeQuery(sql);
//循环取出(id)
while(rs.next()){
String id = rs.getString(1);//1代表数据库中表的列数,id在第一列也可以("id")!!!
System.out.println("id:" + id);
}
1、获取行
ResultSet提供了对结果集进行滚动的方法:
方法 | 含义 |
---|---|
next() | 移动到下一行 |
previous() | 移动到前一行 |
absolute(int row) | 移动到指定行 |
beforeFirst() | 移动resultSet的最前面 |
afterLast() | 移动到resultSet的最后面 |
2、获取值
ResultSet既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法:
方法 | 含义 |
---|---|
getObject(int index) | 根据列的下标返回任意类型的数据 |
getObject(string columnName) | 根据列名返回任意类型的数据 |
getString(int index) | 根据列的下标返回指定类型的数据 |
getString(String columnName) | 根据列名返回指定类型的数据 |
附加:
常用数据类型转换:
SQL类型 | JDBC对应的方法 | 返回类型 |
---|---|---|
bit(1),bit(n) | getBoolean,getBytes() | Boolean,byte[] |
tinyint | getByte() | Byte |
smallint | getShort() | Short |
int | getInt | Int |
bigint | getLong() | Long |
char,varchar,longvarchar | getString | String |
text(clob),blob | getClob(),getblob() | Clob,blob |
date | getDate() | java.sql.Date |
time | getTime() | java.sql.Time |
timestamp | getTimestamp | java.sql.Timestamp |
5、释放资源
Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象。
注意:为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。
//6.关闭链接,释放资源
if(rs!=null){
try{
rs.close();
}catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if(st!=null){
try{
st.close();
}catch (Exception e) {
e.printStackTrace();
}
}
if(conn!=null){
try{
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
二、完整操作
数据库工具类:
public class JdbcUtils {
private static String driver = null;
private static String url = null;
private static String username = null;
private static String password = null;
//静态代码块,随着类的加载而执行,而且只执行一次
//父类静态代码块->子类静态代码块->子类main方法->父类非静态代码块->子类静态代码块->父类构造函数->子类构造函数
static{
try{
//加载db.properties文件
InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties prop = new Properties();
prop.load(in);
//从资源文件中取出字段值
driver = prop.getProperty("driver");
url = prop.getProperty("url");
username = prop.getProperty("username");
password = prop.getProperty("password");
//加载数据库驱动
Class.forName(driver);
}catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
//获取数据库连接对象Connection
public static Connection getConnection() throws SQLException{
//建立连接
return DriverManager.getConnection(url, username, password);
}
//释放资源(因为PreparedStatement是Statement的子类,所以定义Statement可以释放两种方式)
public static void release(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try{
rs.close();
}catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if(st!=null){
try{
st.close();
}catch (Exception e) {
e.printStackTrace();
}
}
if(conn!=null){
try{
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
资源文件:db.properties:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/javastudy
username=root
password=521216
功能实现:
//使用jdbc对数据库增删改查
public class Demo {
@Test
public void insert(){
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
String sql = "insert into users(id,name,password,email,birthday) values(?, ?, ?, ?, ?)";
st = conn.preparedStatement(sql);
st.setInt(1, 4);
st.setString(2, "xxx");
st.setString(3, "123");
st.setString(4, "156@qq.com");
st.setDate(5, new Date().getTime);
int num = st.executeUpdate(); //update
if(num>0){
System.out.println("插入成功!!");
}
}catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.release(conn, st, rs);
}
}
@Test
public void delete(){
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
String sql = "delete from users where id=?";
st = conn.preparedStatement(sql);
st.setInt(1, 4);
int num = st.executeUpdate();
if(num>0){
System.out.println("删除成功!!");
}
}catch (Exception e) {
}finally{
JdbcUtils.release(conn, st, rs);
}
}
@Test
public void update(){
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
String sql = "update users set name='wuwang',email='wuwang@sina.com' where id=3";
st = conn.createStatement();
int num = st.executeUpdate(sql);
if(num>0){
System.out.println("更新成功!!");
}
}catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.release(conn, st, rs);
}
}
@Test
public void find(){
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
String sql = "select * from users where id=?";
st = conn.preparedStatement(sql);
st.setInt(1, 1);
rs = st.executeQuery(sql);
if(rs.next()){
System.out.println(rs.getString("name"));
}
}catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.release(conn, st, rs);
}
}
}
三、常见操作
1、处理大数据
1.存取文本文件(.txt文件)
clob用于存储大文本(mysql中无clob,存储大文本采用的是text
)
注意:
mysql:tinytext<256b text<64k mediumtext<16m longtext<4g
数据库:
create table testclob
(
id int primary key auto_increment,
resume text
);
Java代码:
public class Demo {
@Test
public void add() {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
String sql = "insert into testclob(resume) values(?)";
st = conn.prepareStatement(sql);
//Reader reader = new InputStreamReader(Demo.class.getClassLoader().getResourceAsStream("1.txt"));
String path = Demo.class.getClassLoader().getResource("1.txt").getPath();//1.txt文件在src下
File file = new File(path);
st.setCharacterStream(1, new FileReader(file), (int) file.length());//将该文件添加
int num = st.executeUpdate();
if(num>0){
System.out.println("插入成功!!");
}
}catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.release(conn, st, rs);
}
}
@Test
public void read(){
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
String sql = "select resume from testclob where id=1";
st = conn.prepareStatement(sql);
rs = st.executeQuery();
if(rs.next()){
System.out.println("haha");
Reader reader = rs.getCharacterStream("resume");
char[] buffer = new char[1024];
int len = 0;
FileWriter out = new FileWriter("d:\\1.txt");
while((len = reader.read(buffer)) > 0){
out.write(buffer, 0, len);
}
out.close();
reader.close();
}
}catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.release(conn, st, rs);
}
}
}
2、存取二进制文件(图片,视频)
注意:
mysql:tinyblob<256b blob<64k mediumblob<16m longblob<4g
数据库:
create table testblob
(
id int primary key auto_increment,
image longblob
);
Java代码:
public class Demo {
@Test
public void add(){
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
String sql = "insert into testblob(image) values(?)";
st = conn.prepareStatement(sql);
String path = Demo2.class.getClassLoader().getResource("01.jpg").getPath();
st.setBinaryStream(1, new FileInputStream(path), (int) new File(path).length());
int num = st.executeUpdate();
if(num>0){
System.out.println("插入成功!!");
}
}catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.release(conn, st, rs);
}
}
@Test
public void read(){
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
String sql = "select image from testblob where id=?";
st = conn.prepareStatement(sql);
st.setInt(1, 1);
rs = st.executeQuery();
if(rs.next()){
InputStream in = rs.getBinaryStream("image");
int len = 0;
byte buffer[] = new byte[1024];
FileOutputStream out = new FileOutputStream("d:\\1.jpg");
while((len = in.read(buffer)) > 0){
out.write(buffer,0, len);
}
in.close();
out.close();
}
}catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.release(conn, st, rs);
}
}
}
2、批量处理SQL
数据库:
create table testbatch
(
id int primary key,
name varchar(20)
);
1、通过Statement
@Test
public void testbatch(){
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
String sql1 = "insert into testbatch(id,name) values(1,'aaa')";
String sql2 = "insert into testbatch(id,name) values(2,'bbb')";
String sql3 = "delete from testbatch where id=1";
st = conn.createStatement();
st.addBatch(sql1);
st.addBatch(sql2);
st.addBatch(sql3);
st.executeBatch();
st.clearBatch();
}catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.release(conn, st, rs);
}
}
2、通过preparedstatement
@Test
public void testbatch(){
long starttime = System.currentTimeMillis();
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
String sql = "insert into testbatch(id,name) values(?,?)";
st = conn.prepareStatement(sql);
for(int i=1;i<10000008;i++){ //i=1000 2000
st.setInt(1, i);
st.setString(2, "aa" + i);
st.addBatch();
if(i%1000==0){
st.executeBatch();//只有1000条数据
st.clearBatch();
}
}
st.executeBatch();//没用了
}catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.release(conn, st, rs);
}
long endtime = System.currentTimeMillis();
System.out.println("程序花费时间:" + (endtime-starttime)/1000 + "秒!!");
}
3、获取自动生成的主键
数据库:
create table test1
(
id int primary key auto_increment,//id自动生成
name varchar(20)
);
Java代码:
public class Demo {
/**
* 获取自动生成的主键
*/
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
String sql = "insert into test1(name) values(?)";
st = conn.prepareStatement(sql);
st.setString(1, "aaa");//在插入name时数据库会自动生成id
st.executeUpdate();
rs = st.getGeneratedKeys();//获取生成的主键
if(rs.next()){
System.out.println(rs.getInt(1));
}
}catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.release(conn, st, rs);
}
}
}
4、调用存储过程
public class Demo {
/*
* jdbc调用存储过程:
create procedure p_course_insert
@c_no nvarchar(50),
@c_name nvarchar(50),
@t_name nvarchar(50)
as
insert into t_course(c_no,c_name,t_name)
values(@c_no,@c_name,@t_name)
*/
public static void main(String[] args) {
Connection conn = null;
CallableStatement cs = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
cs = conn.prepareCall("{call p_course_inser(?,?,?)}");
cs.setString(1, "xxxxx");
cs.registerOutParameter(2, Types.VARCHAR);
cs.execute();
String result = cs.getString(2);
System.out.println(result);
}catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.release(conn, cs, rs);
}
}
}
5、使用事务
1、普通事务的操作
/**
* 模似转帐
create table account(
id int primary key auto_increment,
name varchar(40),
money float
)character set utf8 collate utf8_general_ci;
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);
*/
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
conn.setAutoCommit(false); //start transaction,开启事务
String sql1 = "update account set money=money-100 where name='aaa'";
st = conn.prepareStatement(sql1);
st.executeUpdate();
String sql2 = "update account set money=money+100 where name='bbb'";
st = conn.prepareStatement(sql2);
st.executeUpdate();
conn.commit();//提交
System.out.println("成功!!!"); //log4j
}catch (Exception e) {
e.printStackTrace();//如果程序出错手动回滚
}finally{
JdbcUtils.release(conn, st, rs);
}
}
2、设置事务回滚点
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
Savepoint sp = null;
try{
conn = JdbcUtils.getConnection();
conn.setAutoCommit(false); //start transaction
String sql1 = "update account set money=money-100 where name='aaa'";
st = conn.prepareStatement(sql1);
st.executeUpdate();
sp = conn.setSavepoint();//在这里设置事务回滚点
String sql2 = "update account set money=money+100 where name='bbb'";
st = conn.prepareStatement(sql2);
st.executeUpdate();
int x = 1/0;
String sql3 = "update account set money=money+100 where name='ccc'";
st = conn.prepareStatement(sql3);
st.executeUpdate();
conn.commit();
}catch (Exception e) {
try {
conn.rollback(sp);//回滚到该事务点,即该点之前的会正常执行(sql1)
conn.commit(); //回滚了要记得提交,如果没有提交sql1将会自动回滚
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}finally{
JdbcUtils.release(conn, st, rs);
}
}
3、设置事务隔离级别
conn = JdbcUtils.getConnection();
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);//避免脏读
conn.setAutoCommit(false);
/*
Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化)
Repeatable read:可避免脏读、不可重复读情况的发生。(可重复读)
Read committed:可避免脏读情况发生(读已提交)。
Read uncommitted:最低级别,以上情况均无法保证。(读未提交)
*/
隔离级别 | 脏读可能性 | 不可重复读可能性 | 幻读可能性 | 加锁读 |
---|---|---|---|---|
READ UNCOMMITTED | 是 | 是 | 是 | 否 |
READ COMMITTED | 否 | 是 | 是 | 否 |
REPEATABLE READ | 否 | 否 | 是 | 否 |
SERIALIZALBLE | 否 | 否 | 否 | 是 |
注意:不是事务隔离级别设置得越高越好,事务隔离级别设置得越高,意味着势必要花手段去加锁用以保证事务的正确性,那么效率就要降低,因此实际开发中往往要在效率和并发正确性之间做一个取舍,一般情况下会设置为READ_COMMITED,此时避免了脏读,并发性也还不错,之后再通过一些别的手段去解决不可重复读和幻读的问题就好了。
四、Spring JDBC
- Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发
1、导入JAR
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.2.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<!-- 获取上下文 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- 连接到mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
2、配置JdbcTemplate
1、配置XML文件
此处使用的是C3P0连接池,可以换成Druid
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 导入资源文件
读取db.properties文件中的数据 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 配置C3P0数据源 -->
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
</bean>
<!-- 配置Spring的jdbcTemplate
并注入一个dataSource数据源-->
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
2、代码实现
public class JDBCUtils {
private static DateSource dateSource = null;
static {
try {
InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(in);
dataSource.setUrl(properties.getProperty("url"));
dataSource.setDriverClassName(properties.getProperty("driver")); //这个可以缺省的,会根据url自动识别
dataSource.setUsername(properties.getProperty("username"));
dataSource.setPassword(properties.getProperty("password"));
//下面都是可选的配置
dataSource.setInitialSize(10); //初始连接数,默认0
dataSource.setMaxActive(30); //最大连接数,默认8
dataSource.setMinIdle(10); //最小闲置数
dataSource.setMaxWait(2000); //获取连接的最大等待时间,单位毫秒
dataSource.setPoolPreparedStatements(true); //缓存PreparedStatement,默认false
dataSource.setMaxOpenPreparedStatements(20); //缓存PreparedStatement的最大数量,默认-1(不缓存)。大于0时会自动开启缓存PreparedStatement,所以可以省略上一句代码
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static JdbcTemplate getJdbcTemplate() {
return new JdbcTemplate(dateSource);
}
public static void release(Connection connection, Statement statement, ResultSet resultSet) {
if(connection != null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(statement != null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (resultSet != null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
3、使用JdbcTemplate
1、update()
-
执行DML语句。增删改语句
-
执行插入语句有int类型的返回值
//private JdbcTemplate jdbcTemplate = JDBCUtils.getJdbcTemplate();
@AutoWired
private JdbcTemplate jdbcTemplate;
@Test
//修改指定num的name
public void testUpdate() {
String sql = "update student set name = ? where num = ?";
jdbcTemplate.update(sql, "pink",0001);
System.out.println("success");
}
2、batchUpdate批量更新
//private JdbcTemplate jdbcTemplate = JDBCUtils.getJdbcTemplate();
@AutoWired
private JdbcTemplate jdbcTemplate;
/*
*批量更新:批量 insert,update,delete
*/
@Test
public void testBatechUpdate() {
String sql = "insert into student(num,password,name,age,score) value(?,?,?,?,?)";
List<Object[]> batchArgs = new ArrayList<Object[]>();
batchArgs.add(new Object[] {"007","123","pojp",23,99});
batchArgs.add(new Object[] {"008","123","trtp",23,99});
batchArgs.add(new Object[] {"009","123","QQQp",23,99});
jdbcTemplate.batchUpdate(sql, batchArgs);
}
3、queryForObject查询单行
-
查询结果,将结果封装为
对象
-
一般用于
聚合函数
的查询
/*
*从数据库中获取一条记录,实际是得到对应的一个对象
*RowMapper:行的映射
*Spring 2.5 提供了一个便利的RowMapper实现-----BeanPropertyRowMapper
*它可自动将一行数据映射到指定类的实例中 它首先将这个类实例化,然后通过名称匹配的方式,映射到属性中去。
*字段 bean属性
*USER_NAME --> userName
*USER_ID --> userId
*/
@Test
public void testQueryForObject() {
String sql = "select num,name,age from student where id = ?";
RowMapper<stu> rowMapper = new BeanPropertyRowMapper<stu>(stu.class);
stu s = jdbcTemplate.queryForObject(sql, rowMapper,5);//最后一个参数为id值
System.out.println(s);
}
4、queryForObject单值查询
/**
* 获取单个列的值,或统计
*/
@Test
public void testQueryObjectqqq() {
String sql = "select count(name) from student";
Long count = jdbcTemplate.queryForObject(sql, Long.class);
System.out.println(count);
}
5、query查询多行
/*
*查询实体类的集合
*/
@Test
public void testQueryForList() {
String sql = "select num,name,age from student where id > ?";
RowMapper<stu> rowMapper = new BeanPropertyRowMapper<stu>(stu.class);
List<stu> s = jdbcTemplate.query(sql, rowMapper,0);//最后一个参数为id值
System.out.println(s);
}
6、queryForList():查询结果将结果集封装为list集合
- 将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
7、queryForMap():查询结果将结果集封装为map集合
- 这个方法查询的结果集长度只能是1,将列名作为key,将值作为value,将这条记录封装为一个Map集合
五、使用数据库连接池
1、C3P0数据库连接池
1、代码实现
public class JdbcUtils_C3P0 {
private static ComboPooledDataSource ds = null;
static{
try{
ds = new ComboPooledDataSource();
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbcstudy");
ds.setUser("root");
ds.setPassword("521216");
ds.setInitialPoolSize(10);//最初连接数
ds.setMinPoolSize(5);//最小连接数
ds.setMaxPoolSize(20);//最大连接数
}catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
public static Connection getConnection() throws SQLException{
return ds.getConnection();
}
public static void release(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try{
rs.close();
}catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if(st!=null){
try{
st.close();
}catch (Exception e) {
e.printStackTrace();
}
}
if(conn!=null){
try{
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
2、使用配置文件(src下):c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy</property>
<property name="user">root</property>
<property name="password">521216</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
<named-config name="mysql">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy</property>
<property name="user">root</property>
<property name="password">521216</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</named-config>
<named-config name="oracle">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy</property>
<property name="user">root</property>
<property name="password">521216</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</named-config>
</c3p0-config>
//JdbcUtils_C3P0可以改成:
/*
ds = new ComboPooledDataSource();
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/day16");
ds.setUser("root");
ds.setPassword("root");
ds.setInitialPoolSize(10);//最初连接数
ds.setMinPoolSize(5);//最小连接数
ds.setMaxPoolSize(20);//最大连接数
*/
ds = new ComboPooledDataSource("mysql");//如果默认()
2、Druid数据库连接池
1、纯代码方式
//数据源配置
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://127.0.0.1/db_student?serverTimezone=UTC");
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); //这个可以缺省的,会根据url自动识别
dataSource.setUsername("root");
dataSource.setPassword("521216");
//下面都是可选的配置
dataSource.setInitialSize(10); //初始连接数,默认0
dataSource.setMaxActive(30); //最大连接数,默认8
dataSource.setMinIdle(10); //最小闲置数
dataSource.setMaxWait(2000); //获取连接的最大等待时间,单位毫秒
dataSource.setPoolPreparedStatements(true); //缓存PreparedStatement,默认false
dataSource.setMaxOpenPreparedStatements(20); //缓存PreparedStatement的最大数量,默认-1(不缓存)。大于0时会自动开启缓存PreparedStatement,所以可以省略上一句代码
//获取连接
Connection connection = dataSource.getConnection();
//Statement接口
Statement statement = connection.createStatement();
String sql1 = "insert into tb_student (name,age) values ('chy',20)";
statement.executeUpdate(sql1);
//PreparedStatement接口
String sql2 = "insert into tb_student (name,age) values ('chy',21)";
PreparedStatement preparedStatement = connection.prepareStatement(sql2);
preparedStatement.execute();
//关闭连接
connection.close();
2、配置文件方式
1、在sources下新建druid.properties
url=jdbc:mysql://127.0.0.1/db_student?serverTimezone=UTC
#这个可以缺省的,会根据url自动识别
driverClassName=com.mysql.cj.jdbc.Driver
username=root
password=abcd
##初始连接数,默认0
initialSize=10
#最大连接数,默认8
maxActive=30
#最小闲置数
minIdle=10
#获取连接的最大等待时间,单位毫秒
maxWait=2000
#缓存PreparedStatement,默认false
poolPreparedStatements=true
#缓存PreparedStatement的最大数量,默认-1(不缓存)。大于0时会自动开启缓存PreparedStatement,所以可以省略上一句设置
maxOpenPreparedStatements=20
2、使用
public class Test {
public static void main(String[] args) throws Exception {
//数据源配置
Properties properties=new Properties();
//通过当前类的class对象获取资源文件
InputStream is = Test.class.getResourceAsStream("/druid.properties");
properties.load(is);
//返回的是DataSource,不是DruidDataSource
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
//获取连接
Connection connection = dataSource.getConnection();
//Statement接口
Statement statement = connection.createStatement();
String sql1 = "insert into tb_student (name,age) values ('chy',20)";
statement.executeUpdate(sql1);
//PreparedStatement接口
String sql2 = "insert into tb_student (name,age) values ('chy',22)";
PreparedStatement preparedStatement = connection.prepareStatement(sql2);
preparedStatement.execute();
//关闭连接
connection.close();
}
}