JDBC简介
JDBC是java访问数据库的标准规范,真正怎么操作数据库还需要具体的实现类,也就是数据库驱动。
JDBC入门
1.导入驱动jar包:
复制mysql-connecetor-java-5.1.37-bin.jar到项目的Libs目录下;右击Add As Library
2.注册驱动
Class.forName(“com.mysql.jdbc.Driver”)
3.获取数据库连接对象Connection
Connection conn =DriverManager.getConnection(“jdbc:mysql://localhost:3306/crm”,”root”,”root”);
4.定义sql语句
String sql = “insert into customer(name,heightmage) VALUES(‘薛钰烨’,18,1.6)”;
5.获取执行sql语句的对象
StatementStatement stm = conn.createStatement();
6.执行sql,接收返回的结果
int count = stm.executeUpdate(sql);
7.处理结果: 打印
8.释放资源: stm.close(); conn.close();
详解JDBC中各个类
1.DriverManager: 驱动管理对象
功能:
1)注册驱动,告诉程序使用的是什么驱动。
static void registerDriver(Driver driver):注册与给定的驱动程序
写程序使用Class.forName(“com.mysql.jdbc.Driver”)mysql1,5之后可以省略,它在META-INF写了。
通过查看源码发现在com.mysql.jdbc.Driver类中有静态代码块 去注册了驱动。
2)获取数据库连接:
方法:static Connection getConnection(String url, String user,String password);
url:语法jdbc:mysql://ip地址:端口号/数据库名
细节:如果连接的是本机的mysql服务器,并且mysql服务器的端口是3306,那么可以省略为jdbc:mysql:///数据库名
2.Connecction:数据库连接对象
1)获取执行sql对象
Statement createStatement()
PreparedStatement prepareStatement(String sql);
2)管理事务
开启事务:void setAutoCommit(boolean autoCommit) 调用该方法,设置参数为false,即开启事务
提交事务:commit ();
回滚事务: rollback();
在try{获取连接后,开启事务 在sql语句执行后提交事务 }
catch( Exception e){ if(conn!=null){ 回滚事务 }}
3.Statement:执行sql的对象
1)执行sql
boolean execute(String sql) :可以执行任意sql
int executeUpdate(String sql) :执行DML(增删改)语句返回值是影响的行数
、DDL(库和表的创建create,alter,drop)无返回
ResultSet executeQuery(String sql):执行DQL语句 查询语句select,返回的是结果集ResultSet
4.ResultSet:
结果集对象,用来封装查询结果,默认游标一开始在表头
*boolean next();游标向下移动一行,判断当前行是否是最后一行(是否有数据),有则返true,无则返false
*getXxx();获取数据,
Xxx是数据类型,一次不是拿一行,一次是拿一个值。
参数:Int:代表列的编号(从1 开始)
String:代表数据库中表的列名getString(“name”);
使用步骤:游标向下一行,判断是否有数据,获取数据while(rs.next()){}
5.PreparedStatement:
执行sql的对象,是Statement的子接口,预编译sql解决sql的注入问题
SQL注入问题:在拼接sql语句时,有一些sql的特殊关键字参与sql语句字符串的拼接,造成安全性问题;
先定义sql语句,注意:sql的参数作用?作为占位符;
再生成PreparedStatement pstms = conn.preparesStatement(sql);//这里传入sql预编译
最后给占位符赋值pstmt.setXxx(参数1,参数2) ?的编号从1开始,
执行sql语句:pstms.executeQuery();//这里已经不需要传入sql语句了。
备注:后期都使用preparedStatement来执行增删改查,防止SQL注入。
数据库连池
把饭店看做是一个数据库,里面的服务员看做是连接,客人找服务员点菜看做是后端程序索要连接。
标准接口 : jdk提供的接口DataSource在 javax.sql包下的
方法:*获取连接:getConnection()
归还连接:如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法就不是关闭连接了,而是归还连接。
一般我们不实现它,由数据库厂商来实现,有C3P0和Druid(阿里巴巴提供的)
Druid使用步骤:
导入jar包:druid-1.0.9.jar ,还要数据库驱动jar包
定义配置文件,是properties文件,可以叫做任意名称,可以放在任意目录下
配置文件加载:使用Properties类
获取数据库连接池对象:通过工厂来获取:DruidDataSourceFactory.createDataSource()
获取连接:getConnection
如下配置文件放置在项目的src下
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/crm
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000
手写JDBCUtils工具类
package com.xl.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JDBCUtils {
private static DataSource dataSource;
static{
try {
//获取配置文件
Properties properties = new Properties();
properties.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
//建立连接池对象 因为这个不一定可以获取到,所以定义在外;
//使用工厂创建连接池对象
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接对象
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
public static DataSource getDataSource(){
return dataSource;
}
//释放资源
public static void close(ResultSet rs, Statement stmt,Connection conn){
if(rs!=null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
public static void close( Statement stmt,Connection conn){
close(null,stmt,conn);
}
}
JDBCTemplate的学习
封装从数据库中渠道的数据
Spring框架对JDBC的简单封装,提供了一个JDBCTemplate对象 简化JDBC的开发
使用步骤:
前提:第三方的数据库连接池使用的是Druid,导入对应jar包和数据库驱动jar包,手写工具类
1)导入jar包: □sping-jdbc、sping-beans、sping-core、spring-tx、commons-loggin-1.2.jar
2)创建JdbcTemplate对象,依赖于数据源DataSource
//有数据源,new一个JdbcTemplate,那么它可以看做是数据库连接和执行sql语句的对象合体
JdbcTemplate template =new JdbcTemplate(ds);//ds是数据库连接池对象
3)调用JdbcTemplate的方法来完成CRUD的操作
update():执行DML操作增、删、改语句//第一个参数是sql,第二个参数可变参数(数组)
queryForMap():查询结果,将结果集封装为map集合(键值对集合,只适合查询结果为1条的)
queryForList();查询结果,静结果封装为List集合//多个值,List<Map<String,>>
query():查询结果,将结果封装为javaBean对象?参数是什么?
query的参数是RowMapper的匿名类, 一般我们使用BeanPropertyRowMapper<类型>(类型的字节码对象)
queryForObject():查询结果,将查询结果封装为对象;一般使用的是聚合语句
易混:防止SQL注入的PreparedStatement pstmt,使用getXxx(位置,值);//位置编号从1开始
使用它自带的更加方便!
List list =template.query(sql,new BeanPropertyRowMapper(Customer.class));
在domain Customer中,建议成员字段的类型不是基本类型,因为基本类型是没有null值的。
使用这个new BeanPropertyRowMapper<>(),能一一映射的前提是两者都已经按照数据库中的字段名和Bean对象中的setXxx()对应起来了
实体类Customer.java
package com.xl.domain;
public class Customer {
private Integer id;
private String name;
private Integer age;
private Double height;
public Customer() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getHeight() {
return height;
}
public void setHeight(Double height) {
this.height = height;
}
@Override
public String toString() {
return "Customer{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", height=" + height +
'}';
}
}
使用JDBCTemplate
public class JDBCTemplateTest {
public static void main(String[] args) throws Exception {
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
String sql = "select count(id) from customer ";
Long total =jdbcTemplate.queryForObject(sql,Long.class);
System.out.println(total);
}
}
一种情况:当查询数据,想自定义映射关系的时候
另一种情况,使用默认的映射关系:
public void test1(){
String sql = "selecct * from customer ";
List<Customer> list = template.query(sql,new BeanPropertyRowMapper<Customer>(Customer.class));
}