Java 之 JDBC

一、认识JDBC

JDBC是用于在Java语言编程中与数据库连接的API.JDBC是一个规范,它提供了一整套接口,允许以一种可移植的访问底层数据库API。使用JDBC驱动程序来访问数据库,并用于存储数据到数据库中.

解释上面两幅图:

java应用程序通过JDBC API首先连接到JDBC Driver,这些JDBC驱动器都是由各大数据库厂家针对JDBC提供的,我们可以在网上下载jar包来使用,然后通过JDBC驱动器就能连接到我们的数据库了。

第一步 添加驱动

1.在项目当中创建一个文件夹为lib
2.把Mysql驱动包复制到该文件夹下
3.builder path 编译路径
复制代码

第二步 连接到数据库

package con.meils.jdbc.conn;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class ConnectionClass {

	public static void main(String[] args) throws ClassNotFoundException, SQLException {
		// TODO Auto-generated method stub
		
		
		// 1、加载驱动
		// 把com.mysql.jdbc.Driver这份字节码加载进JVM
		// 当一份字节码加载进JVM的时候,就会执行字节码文件中的静态代码块
		// 这里加载该字节码之后会实例化一个驱动器
		Class.forName("com.mysql.jdbc.Driver");
		
		// 2、连接
		String url = "jdbc:mysql://localhost:3306/mytest";
		String username = "root";
		String password = "zjj19970517";
		Connection connection = DriverManager.getConnection(url, username, password);
		
		// 3、验证连接
		System.out.println(connection); // 如果有输出,表明连接成功
	}

}

复制代码

第三步 操作数据库创建表

package con.meils.jdbc.ddl;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class CreateTable {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		// 1\加载驱动
		// 把com.mysql.jdbc.Driver这份字节码加载进JVM
		// 当一份字节码加载进JVM的时候,就会执行字节码文件中的静态代码块
		// 这里加载该字节码之后会实例化一个驱动器
		Class.forName("com.mysql.jdbc.Driver");

		String url = "jdbc:mysql://localhost:3306/jdbc_db";
		String username = "root";
		String password = "zjj19970517";
		// 2\ 连接数据库
		Connection connection = DriverManager.getConnection(url, username, password);
		
		
		// 3\创建sql语句
		String sql = "create table stu (id int , name varchar(20), age int)";
		
		// 4\执行sql语句
		Statement st = connection.createStatement();
		int row = st.executeUpdate(sql);
		
		// 5\释放
		st.close();
		connection.close();
		
		
		
	}

}

复制代码

为什么要释放资源呢?

第四步 插入数据

package con.meils.jdbc.dml;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class InsertClass {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		
		// ================ 插入数据 ================
		
		Connection conn = null;
		
		Statement st = null;
		
		
		try {
			// 1、加载驱动
			Class.forName("com.mysql.jdbc.Driver");
			
			// 2、创建连接
			String url = "jdbc:mysql://localhost:3306/mytest";
			String user = "root";
			String password = "zjj19970517";
			conn = DriverManager.getConnection(url, user, password);
			
			// 3、创建sql语句
			String sql = "insert into stu values(1, 'zjj', 20)";
			st = conn.createStatement();
			
			// 4、执行语句
			int row = st.executeUpdate(sql);
			System.out.println(row);
		}catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 5、释放
			if(st!=null) {
				try {
					st.close();
				}catch (Exception e) {
					e.printStackTrace();
				}
			}
			if(conn!=null) {
				try {
					conn.close();
				}catch (Exception e) {
					e.printStackTrace();
				}
			}
			
			
		}
		
	}

}

复制代码

第五步 查询操作

package con.meils.jdbc.dql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class QueryClass {

	public static void main(String[] args) throws SQLException, ClassNotFoundException {
		// TODO Auto-generated method stub

		// ================ 查询数据 ================
		
		// 1\加载驱动
				// 把com.mysql.jdbc.Driver这份字节码加载进JVM
				// 当一份字节码加载进JVM的时候,就会执行字节码文件中的静态代码块
				// 这里加载该字节码之后会实例化一个驱动器
				Class.forName("com.mysql.jdbc.Driver");

				String url = "jdbc:mysql://localhost:3306/mytest";
				String username = "root";
				String password = "zjj19970517";
				// 2\ 连接数据库
				Connection connection = DriverManager.getConnection(url, username, password);
				
				
				// 3\创建sql语句 
				String sql = "select count(*) as total from stu"; // 查询一共有几行数据
				
				// 4\执行sql语句
				Statement st = connection.createStatement();
				ResultSet rs = st.executeQuery(sql);
				
				if(rs.next()) {
					int count = rs.getInt("total");
					System.out.println(count); // 1
				}
				
				// 5\释放
				st.close();
				connection.close();
	}

}

复制代码

数据类型对照表:

上面我们基本学会了如何与数据库打交道,但是这样使用存在许多的弊端,比如:每一步操作都进行一次数据库连接,造成浪费,所以我们在实际中要使用DAO思想来处理。

二、DAO设计

1、什么是DAO

DAO(Data Access Object)数据存储对象,介于业务逻辑层和持久层之间,实现持久化数据访问。

不使用DAO的时候:

使用DAO的情况:

三、ORM映射关系

四、Domain

1、认识domain

2、domain类

3、保存数据

4、获取数据

五、DAO设计规范

案例

我们可以编写一个DAO接口,定义了常用的数据库操作方法,这时候我们同时会连接多个数据库,比如是mysql 和 oracle ,我们可以分别实现oracleDao和mysqlDao两个类,不同类里面定义不同的操作数据库的代码,实现的功能确实相同的。

所以面向接口编程是很重要的,也是一个很好的方式。

1、包命名规范

2、类命名规范

3、开发步骤

目录如下

内容实现:

接口实现类的具体内容:

package com.meils.jdbc.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.meils.jdbc.dao.IStudentDao;
import com.meils.jdbc.domain.Student;
import com.meils.jdbc.utils.JdbcUtil;

/**
 * 实现DAO接口的类
 * @author apple
 *
 */
public class StudentDaoImpl implements IStudentDao{

	@Override
	/**
	 * 存储学生
	 * @param stu
	 */
	public void save(Student stu) {
		// TODO Auto-generated method stub
		Connection conn = null;
		PreparedStatement ps = null;
		
		try {
			// 连接数据库
			conn = JdbcUtil.getConnection();
			
			String sql = "insert into student (name, age) values (? , ?)";
			
			// 创建预编译
			ps = conn.prepareStatement(sql);
			ps.setString(1, stu.getName());
			ps.setInt(2, stu.getAge());
			
			// 执行更新
			ps.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtil.close(conn, ps, null);
		}
	}

	@Override
	public void delete(int id) {
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			// 连接数据库
			conn = JdbcUtil.getConnection();
			
			String sql = "delete from student where id = ?";
			
			// 创建预编译
			ps = conn.prepareStatement(sql);
			ps.setInt(1, id);
			// 执行更新
			ps.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtil.close(conn, ps, null);
		}
	}

	@Override
	public void update(int id, Student stu) {
		
		Connection conn = null;
		PreparedStatement ps = null;
		try {

			conn = JdbcUtil.getConnection();
			
			String sql = "update student set name=?, age=? where id = ? ";
			ps = conn.prepareStatement(sql);
			
			ps.setString(1, stu.getName());
			ps.setInt(2, stu.getAge());
			ps.setInt(3, id);
			// 执行
			ps.executeUpdate();
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtil.close(conn, ps, null);
		}
		
	
	}

	@Override
	public Student findOne(int id) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			
			conn = JdbcUtil.getConnection();
			// sql语句
			String sql = "select * from student where id = ?";
			ps = conn.prepareStatement(sql);
			ps.setInt(1, id);
			// 执行
			rs = ps.executeQuery();
			
			if (rs.next()) {
				// 保存数据
				Student stu = new Student();
				stu.setName(rs.getString("name"));
				stu.setAge(rs.getInt("age"));
				stu.setId(rs.getInt("id"));
				return stu;
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 销毁
			JdbcUtil.close(conn, ps, rs);

		}
		
		return null;
	}

	@Override
	public List<Student> findAll() {
		
		Connection conn = null;
		Statement st = null;
		ResultSet rs = null;
		try {
			
			
			conn = JdbcUtil.getConnection();
			
			
			st = conn.createStatement();
			String sql = "select * from student ";
			
			rs = st.executeQuery(sql);
			
			List<Student> list = new ArrayList<Student>();
			while (rs.next()) {
				Student stu = new Student();
				stu.setName(rs.getString("name"));
				stu.setAge(rs.getInt("age"));
				stu.setId(rs.getInt("id"));
				list.add(stu);
			}
			return list;

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtil.close(conn, st, rs);
		}
		return null;
	}
	
}

复制代码

编写测试类:

package com.meils.jdbc.dao.test;

import java.util.List;

import org.junit.Test;

import com.meils.jdbc.dao.IStudentDao;
import com.meils.jdbc.dao.impl.StudentDaoImpl;
import com.meils.jdbc.domain.Student;

/**
 * StudentDao测试类
 * @author apple
 */
public class StudentDaoTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
	}
	
	@Test
	public void save() {
		Student stu = new Student();
		stu.setName("张伟");
		stu.setAge(21);
		
		IStudentDao dao = new StudentDaoImpl();
		dao.save(stu);
	}
	
	@Test
	public void delete() {
		IStudentDao dao = new StudentDaoImpl();
		dao.delete(4);
	}

	@Test
	public void update () {
		Student stu = new Student();
		stu.setName("mmmmm");
		stu.setAge(16);
		
		IStudentDao dao = new StudentDaoImpl();
		dao.update(5, stu);
	}
	
	@Test
	public void findOne() {
		IStudentDao dao = new StudentDaoImpl();
		Student stu = dao.findOne(5);
		System.out.println(stu);
	}
	
	
	@Test
	public void findAll() {
		IStudentDao dao = new StudentDaoImpl();
		List<Student> allStu = dao.findAll();
		System.out.println(allStu);
	}
	
	
	
	
}

复制代码

JDBC工具类:

package com.meils.jdbc.utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

/**
 * JDBC  工具类
 * @author apple
 *
 */
public class JdbcUtil {
	// 配置信息
	public static String driverName = "com.mysql.jdbc.Driver";
	public static String url = "jdbc:mysql://localhost:3306/mytest";
	public static String userName = "root";
	public static String password = "zjj19970517";
	
	static {
		try {
			// 加载驱动,因为是在static块中,所以只会加载一次
			Class.forName(JdbcUtil.driverName);
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 连接数据库
	 * @return 返回连接对象
	 */
	public static Connection getConnection() {
		try {
			return DriverManager.getConnection(JdbcUtil.url, JdbcUtil.userName, JdbcUtil.password);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 关闭连接,并释放资源
	 * @param conn
	 * @param st
	 * @param rs
	 */
	public static void close(Connection conn, Statement st, ResultSet rs) {
		if(conn!=null) {
			try {
				conn.close();
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
		
		if(st!=null) {
			try {
				st.close();
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
		
		if(rs!=null) {
			try {
				rs.close();
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
}

复制代码

项目github地址

3、DAO代码重构

4、Statement接口

1 Statement 是父接口,PreparedStatement 和 CallableStatement 是子接口。

2 Statement 用于java应用程序与数据库之间的传送数据,比如传送sql语句过去,到数据库执行操作。

3 Statement 用于通用的访问,使用静态sql,其实并不好,容易SQL注入

4 PreparedStatement 用于预编译模版SQL语句,可以在运行的时候传入参数

5 CallableStatement 访问存储过程的时候使用
复制代码

5、预编译语句

防止SQL注入:

java JDBC DAO封装教程

6、通过DB类来操作数据库

JDBC的另一种封装方法:

package com.meils.jdbc.db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class MysqlDB {
	Connection conn = null; // 创建连接对象
	Statement st = null; // 创建编译语句对象
	PreparedStatement ps = null; // 创建预编译语句对象
	ResultSet rs1 = null;  // 结果集

	// 配置信息
	// 驱动名称
	private static final String driverName = "com.mysql.jdbc.Driver";
	// 数据库的地址
	private static final String URL = "jdbc:mysql://localhost:3306/mytest";
	// 数据库登录用户名
	private static final String userName = "root";
	// 数据库登录密码
	private static final String pwd = "zjj19970517";
	
	/**
	 * 连接数据库
	 * @return
	 */
	public Connection getConnection() {
		try {
			Class.forName(driverName);
			
			this.conn = DriverManager.getConnection(URL, userName, pwd);
			System.out.println("连接成功");
			
			return conn;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	// 构造函数
	public MysqlDB() {
		this.getConnection();
	}
	
	/**
	 * 查询
	 * @param sql sql语句,完整的语句,查询一般比较安全
	 * @return
	 */
	public ResultSet query(String sql) {
		try {
			this.st = this.conn.createStatement();
			this.rs1 = this.st.executeQuery(sql);
			return rs1;
		} catch (SQLException e) {
			e.printStackTrace();
		} 
		
		return null;
	}
	
	/**
	 * 更新
	 * @param sql  // 预编译sql语句
	 * @param args // 参数数组
	 */
	public void update(String sql, String [] args) {
		try {
			this.ps = this.conn.prepareStatement(sql);
			for (int i = 0 ; i < args.length ; i++) {
				this.ps.setString(i+1, args[i]);
			}
			
			this.ps.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			this.close();
		}
		
	}
	
	/**
	 * 删除
	 * @param sql
	 * @return
	 */
	public int delete(String sql){
        try {
            this.st = this.conn.createStatement();
            int num = this.st.executeUpdate(sql);
            return num;
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }  finally {
			this.close();
		}
        return 0;
    }
	
	/**
	 * 释放资源
	 */
	public void close () {
		try {
            if(rs1!=null) {
                rs1.close();
            }
            if(st!=null) {
                st.close();
            }
            if(ps!=null) {
                ps.close();
            }
            if(conn!=null) {
                conn.close();
            }

        } catch (SQLException e) {
            // TODO: handle exception
        	e.printStackTrace();
        }
	}

}

复制代码

测试以下:

package com.meils.jdbc.db;

import java.sql.ResultSet;
import java.sql.SQLException;

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		Conn();
		delete();
	}

	// 测试连接
	public static void Conn() {
		MysqlDB m = new MysqlDB();
	}

	// 测试查询
	public static void queryTest() {
		MysqlDB m = new MysqlDB();
		String sql = "select * from student";
		ResultSet result = m.query(sql);
		System.out.println(result);
		try {
			while (result.next()) {
				System.out.println(result.getString("name"));
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			m.close();
		}
	}
	// 更新
	public static void update() {
		MysqlDB m = new MysqlDB();
		String sql = "update student set name = ? where id = ?";
		String [] args = {"梅子111", "7"};
		
		m.update(sql, args);
	}
	
	// 删除
	public static void delete() {
		MysqlDB m = new MysqlDB();
		String sql = "delete from student  where id = 8";
		System.out.println(m.delete(sql));
	}
	
	
	

}

复制代码

7、调用存储过程

首先我们熟悉一下存储过程

// 新建存储过程
DELIMITER //
create PROCEDURE getStudent1(in n varchar(20))
BEGIN

	select * from student where name = n;
END //
DELIMITER ;

// 执行
call getStudent1('张锦杰');
复制代码

测试一下: (非常尴尬好像并没有结果,也没有报错,不知道是什么原因~~)

package com.meils.jdbc.dao.test;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import com.meils.jdbc.domain.Student;
import com.meils.jdbc.utils.JdbcUtil;

public class ProductTest {

	public static void main(String[] args) {
		CallableStatement cstmt = null;
		try {
			//1.连接
			Connection conn = JdbcUtil.getConnection();
			//2.
			CallableStatement cs = conn.prepareCall("{ call getStu(?)}");
			//3.设置参数
			cs.setString(1, "张锦杰");
			//4.执行
			ResultSet rs = cs.executeQuery();
			if(rs.next()) {
				Student stu = new Student();
				stu.setId(rs.getInt("id"));
				stu.setName(rs.getString("name"));
				stu.setAge(rs.getInt("age"));
				System.out.println(stu);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		

	}

}

复制代码

带有参数和输出的存储过程

// 带有参数和输出的存储过程

DELIMITER //
CREATE PROCEDURE getName ( IN i INT, OUT n VARCHAR ( 50 ) ) BEGIN
	SELECT NAME INTO
		n 
	FROM
		student 
	WHERE
		id = i;

END // DELIMITER;

call getName(1, @name);
select @name;
复制代码

测试一下:

package com.meils.jdbc.dao.test;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import com.meils.jdbc.domain.Student;
import com.meils.jdbc.utils.JdbcUtil;

public class ProductTest {

	public static void main(String[] args) {
		CallableStatement cstmt = null;
		try {
			//1.创建连接
			Connection conn = JdbcUtil.getConnection();
			//2.创建预编译语句
			CallableStatement cs = conn.prepareCall("{ call getName(?,?)}");
			//3.设置参数
			cs.setInt(1, 1);
			//4.设置输出参数
			cs.registerOutParameter(2, Types.VARCHAR);
			//5.执行
			cs.execute();
			
			//6.获取到输出的参数
			String name = cs.getString(2);
			System.out.println(name); // 张锦杰
		} catch (Exception e) {
			e.printStackTrace();
		}
		

	}

}

复制代码

8、事物

实例:

首先在减少钱之前关闭自动提交事务,期间可以进行多个操作,此时的事务提交必须手动了,需要使用conn.commit();。如果在中间发生了异常,那么就进行回滚,释放资源。

9、批处理

通常情况下如果我们想要一次性执行许多条sql语句,我们都是一条执行完毕再执行下一条,当我们使用了批处理之后,我们就可以一次性执行多条语句,话费的事件将大大缩短。

10、将文件存入数据库

通常我们不会这么做的,因为数据库的空间是非常宝贵的,文件较大,占用的空间也较大,成本也就高了,假如我们需要存文件,那么就要选择blob类型了,它是以二进制的形式来存取的,可以存视频、图片、等多媒体信息。

首先需要设置数据库中的字段类型为blob。
复制代码

存储文件到数据库:

将数据库中的文件取出来:

11、获取自动生成的主键id

需求分析:

我们可能回遇到这样的情景,我们首先注册信息,填入用户明和密码后,注册成功,此时的数据库中的id是自动添加进去的,接下来回让自己去完善自己的信息,这就要需要我们刚才创建的id了,那么如何返回id给我们下次使用呢?

两种方式获取:

1:

2:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值