1.什么是JDBC?
就是用来操作sql语句,程序与数据库服务器交互的桥梁。
2.JDBC核心API
|- Driver接口: 表示java驱动程序接口。所有的具体的数据库厂商要来实现此接口。
|-connect(url, properties): 连接数据库的方法。
url:连接数据库的URL
URL语法: jdbc协议:数据库子协议://主机:端口/数据库
user:数据库的用户名
password:数据库用户密码
|-DriverManager类: 驱动管理器类,用于管理所有注册的驱动程序
|-registerDriver(driver) : 注册驱动类对象
|-ConnectiongetConnection(url,user,password); 获取连接对象
|-Connection接口: 表示java程序和数据库的连接对象。
|-Statement createStatement() : 创建Statement对象
|-PreparedStatement prepareStatement(String sql) 创建PreparedStatement对象
|-CallableStatement prepareCall(String sql) 创建CallableStatement对象
|-Statement接口: 用于执行静态的sql语句
|-int executeUpdate(String sql) :执行静态的更新sql语句(DDL,DML)
|-ResultSet executeQuery(String sql) :执行的静态的查询sql语句(DQL)
|-PreparedStatement接口:用于执行预编译sql语句
|- int executeUpdate() :执行预编译的更新sql语句(DDL,DML)
|-ResultSet executeQuery() : 执行预编译的查询sql语句(DQL)
|-CallableStatement接口:用于执行存储过程的sql语句(call xxx)
|-ResultSetexecuteQuery() :调用存储过程的方法
|-ResultSet接口:用于封装查询出来的数据
|-boolean next() : 将光标移动到下一行
|-getXX(): 获取列的值
3.数据库连接
需要导入jdbc的驱动包:
实现:
public class ConnJdbc {
private String url="jdbc:mysql://localhost:3306/basicjdbc?characterEncoding=utf-8";
private String user="root";
private String password="";
/*
* 第一种连接数据的方法
* */
@Test
public void test1() throws Exception{
// Driver driver= new org.gjt.mm.mysql.Driver();
Driver driver= new com.mysql.jdbc.Driver();
Properties props=new Properties();
props.setProperty("user", user);
props.setProperty("password", password);
Connection conn=driver.connect(url, props);
System.out.println(conn);
}
/*
* 第二种连接数据库的方法(推荐)
* */
@Test
public void test2() throws Exception{
Class.forName("com.mysql.jdbc.Driver");
Connection conn=DriverManager.getConnection(url,user,password);
System.out.println(conn);
}
}
结果:
com.mysql.jdbc.JDBC4Connection@592021b7
4.JDBC工具类
文件目录结构:
db.properties:
url=jdbc:mysql://localhost:3306/basicjdbc?characterEncoding=utf-8
username=root
password=
driverClass=com.mysql.jdbc.Driver
实现:
public class JdbcUtil {
private static String url=null;
private static String username=null;
private static String password=null;
private static String driverClass=null;
static{
try{
Properties props=new Properties();
FileInputStream fis=new FileInputStream("./src/db.properties");
props.load(fis);
url=props.getProperty("url");
username=props.getProperty("username");
password=props.getProperty("password");
driverClass=props.getProperty("driverClass");
//注册驱动程序
Class.forName(driverClass);
}catch(Exception e){
e.printStackTrace();
System.out.println("驱动程序注册失败!");
}
}
//获取对象的连接
public static Connection getConnection(){
try {
Connection conn=DriverManager.getConnection(url, username, password);
return conn;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException(e);
}
}
//释放对象的连接
public static void close(Connection conn,Statement stmt,ResultSet rs){
if(rs !=null){
try{
rs.close();
}catch(SQLException e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
if(stmt !=null){
try{
stmt.close();
}catch(SQLException e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
if(conn !=null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
5.Statement接口的操作(DDL、DML、条件查询)
public class StatementJdbc {
private Connection conn=null;
private Statement stmt=null;
private ResultSet rs=null;
/*
* 执行DDL语句:创建一个表
* */
@Test
public void test1() throws Exception{
conn=JdbcUtil.getConnection();
stmt=conn.createStatement();
String sql="CREATE TABLE myUser(id INT PRIMARY KEY NOT NULL,username VARCHAR(20),gender VARCHAR(2))";
stmt.executeUpdate(sql);
JdbcUtil.close(conn, stmt, null);
}
/*
* 执行DML语句:向数据库插入一条数据
* */
@Test
public void test2() throws Exception{
conn=JdbcUtil.getConnection();
stmt=conn.createStatement();
String sql="INSERT INTO myuser VALUES(2,'李四','女')";
int row=stmt.executeUpdate(sql);
System.out.println(row);
JdbcUtil.close(conn, stmt, null);
}
/*
* 条件查询
* */
@Test
public void test3() throws Exception{
String gender="男";
conn=JdbcUtil.getConnection();
stmt=conn.createStatement();
String sql="SELECT * FROM myuser WHERE gender='"+gender+"'";
rs=stmt.executeQuery(sql);
while(rs.next()){
System.out.println(rs.getString("username"));
}
JdbcUtil.close(conn, stmt,rs);
}
}
6.PreparedStatement接口
使用这个接口可以避免了那个sql的拼接,同时也防止了sql注入。
public class PreparedStatementJdbc {
private Connection conn=null;
private PreparedStatement ps=null;
private ResultSet rs=null;
@Test
public void test1(){
String username="张三";
String gender="男";
try {
conn=JdbcUtil.getConnection();
String sql="select * from myuser where username=? and gender=?";
ps=conn.prepareStatement(sql);//对sql语句进行预编译,防止非法字符(防止sql注入)。
ps.setString(1, username);
ps.setString(2, gender);
rs=ps.executeQuery();
while(rs.next()){
System.out.println("登录成功 ,"+rs.getInt("id"));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JdbcUtil.close(conn,ps,rs);
}
}
}
结果:
登录成功 ,1
7.CallableStatement实现存储过程
首先要在SQLyog中创建存储过程:
DELIMITER $$
CREATE PROCEDURE myProcedure()
BEGIN
SELECT * FROM myuser;
END $$
CALL myProcedure();
经过数据库服务器测试,然后此存储过程测试成功。
实现:
public class Jdbc_Call {
private Connection conn=null;
private CallableStatement cs=null;
private ResultSet rs=null;
@Test
public void testCall(){
try {
conn=JdbcUtil.getConnection();
cs=conn.prepareCall("CALL proc_login()");
rs=cs.executeQuery();
while(rs.next()){
String name=rs.getString("username");
String gender=rs.getString("gender");
System.out.println(name+":"+gender);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JdbcUtil.close(conn, cs, rs);
}
}
}
结果:
至于带参数的存储过程,可以看我的使用CallableStatement调用存储过程 将会详细解释。
8.JDBC之记录批处理
使用PreparedStatement实现批处理数据时主要是以下几个方法:
实现:
public class User {
private Integer id;
private String username;
private String gender;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
public class BatchJdbc {
private Connection conn=null;
private PreparedStatement ps=null;
private ResultSet rs=null;
@Test
public void testBatch(){
List<User> list=new ArrayList<User>();
for(int i=1;i<21;i++){
User user=new User();
user.setId(i);
user.setUsername("Bryant"+i);
user.setGender("男");
list.add(user);
}
save(list);
}
public void save(List<User> list){
String sql="insert into myuser(id,username,gender) values(?,?,?)";
try{
conn= JdbcUtil.getConnection();
ps= conn.prepareStatement(sql);
for(int i=1;i<list.size();i++){
User user=list.get(i);
ps.setInt(1, user.getId());
ps.setString(2, user.getUsername());
ps.setString(3, user.getGender());
ps.addBatch();
}
ps.executeBatch();
ps.clearBatch();
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}finally{
JdbcUtil.close(conn, ps, rs);
}
}
}
结果:
解释:由于没有设置判断顺序插入,所以数据库中的记录是乱序的。
9.插入数据后获取自增长的键
在数据库中我们新建表时都会在主键处设置auto_increment作为自增长的键。在插入数据时就不必插入自增长的键了。
实现在插入数据后,获取当前记录的自增长主键:
public class Auto_increment_PrimaryKey {
private Connection conn=null;
private PreparedStatement pstmt=null;
private ResultSet rs =null;
@Test
public void testGetAutoIncrement(){
String sql="INSERT INTO fruit(apple,banana,orange) VALUES(?,?,?)";
try{
conn=JdbcUtil.getConnection();
pstmt=conn.prepareStatement(sql,PreparedStatement.RETURN_GENERATED_KEYS);
pstmt.setString(1, "苹果2");
pstmt.setString(2, "香蕉2");
pstmt.setString(3, "橘子2");
pstmt.executeUpdate();
rs=pstmt.getGeneratedKeys();
if(rs.next()){
System.out.println(rs.getInt(1));
}
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(conn, pstmt, null);
}
}
}
结果:
解释:更新记录操作要在获取自增长主键之前,先更新记录了,才会产生自增长的主键,才会获取到。
10.JDBC之事务管理
事务是指使一组最小逻辑操作单元,里面有多个操作组成。组成事务的每一部分必须要同时提交成功,否则整个操作就需要回滚。
表数据:
实现:
public class JdbcTransaction {
private Connection conn =null;
private PreparedStatement pstmt =null;
private ResultSet rs =null;
@Test
public void testTransaction(){
String sql_zs="UPDATE personInfo SET money=money-1000 WHERE NAME='张三'";
String sql_ls="UPDATE personInfo SET money=money+1000 WHERE NAME='李四'";
try{
conn=JdbcUtil.getConnection();
conn.setAutoCommit(false);//设置手动开启jdbc的事务管理
pstmt=conn.prepareStatement(sql_zs);
pstmt.executeUpdate();
pstmt=conn.prepareStatement(sql_ls);
pstmt.executeUpdate();
conn.commit();
}catch(Exception e){
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}finally{
try{
JdbcUtil.close(conn, pstmt, rs);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
结果: