JDBC最详数据库连接

Java数据库连接(Java DataBase Connectivity), 简称: JDBC

JDBC是Java连接数据库的基石,Hibernate、MyBatis等只是更好的封装了数据库

1. JDBC介绍

JDBC是一个独立于特定的数据库管理系统, 通用的SQL数据库存取和操作的公共接口,规范了不同数据库之间被Java访问需要用不同的接口
在这里插入图片描述

2. JDBC程序编写步骤

在这里插入图片描述

补充:ODBC(Open Database Connectivity,开放式数据库连接),是微软在Windows平台下推出的。使用者在程序中只需要调用ODBC API,由 ODBC 驱动程序将调用转换成为对特定的数据库的调用请求。

3. 获取数据库的连接

3.1 导入Driver接口的包
  1. 复制jar文件,进入idea
    在这里插入图片描述

  2. 在module下创建lib目录,将文件粘贴到lib目录下
    在这里插入图片描述

  3. 右击jar文件,点击Add as Library
    在这里插入图片描述

3.2 加载与注册JDBC驱动
  1. Driver类通常都不需用手动注册,在Driver类中,只要加载了类就会有今天代码块自动注册
    自动注册Driver
  2. 加载驱动用Class调用静态方法forName(),向其传入要加载的JDBC驱动的类名

Class.forName(“com.mysql.jdbc.Driver”);

3.3 URL

JDBC的URL用于一个被注册的驱动程序, 驱动程序管理器通过这个URL正确的连接数据库
URL由三部分组成: 协议:子协议://主机地址:端口号:数据库名

  • 协议: 通常都是jdbc
  • 子协议: 用于标识数据库驱动程序
    在这里插入图片描述
    MySQL的连接URL编写方式:
  • jdbc:mysql://主机名称:mysql服务端口号/数据库名称?参数=值&参数=值
  • jdbc:mysql://localhost:3306/atguigu
  • jdbc:mysql://localhost:3306/atguigu**?useUnicode=true&characterEncoding=utf8**(如果JDBC程序与服务器端的字符集不一致,会导致乱码,那么可以通过参数指定服务器端的字符集)
  • jdbc:mysql://localhost:3306/atguigu?user=root&password=123456
3.4 用户名和密码
  • user,password可以用“属性名=属性值”方式告诉数据库
  • 可以调用 DriverManager 类的 getConnection() 方法建立到数据库的连接
3.5 创建配置文件存储配置
  1. 在module下,右击创建File
    在这里插入图片描述
  2. 用户名、密码、URL、驱动都写入配置文件,如后面需要修改方便修改
    在这里插入图片描述

4. 连接数据库

    public static void main(String[] args) throws Exception {
        //1.创建输入流,指明配置文件路径
        FileInputStream fis = new FileInputStream("D:\\Java-project\\jdbc_1\\jdbc\\propertiesjdbc");
        //2.创建Properties实例
        Properties pro = new Properties();
        //3.加载配置文件
        pro.load(fis);
        //4.获取配置文件的每个值
        String user = pro.getProperty("user");
        String password = pro.getProperty("password");
        String url = pro.getProperty("url");
        String drivermanager = pro.getProperty("drivermanager");
        //5.加载驱动程序
        Class.forName(drivermanager);
        //6.测试连接是否成功
        Connection con = DriverManager.getConnection(url, user, password);
        System.out.println(con);
    }

5. 使用PreparedStatement实现CRUD操作

  • 数据库连接被赋予发送SQL命令语句,并接收数据库返回的结果
  • PreparedStatement: SQL语句被预编译在此对象中, 可以对此对象多次高效的执行语句
    在这里插入图片描述
  • PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用 PreparedStatement 对象的 setXxx() 方法来设置这些参数. setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值
5.1 使用PreparedStatement实现查询操作
	// 通用的针对于不同表的查询:返回一个对象 (version 1.0)
	public <T> T getInstance(Class<T> clazz, String sql, Object... args) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			// 1.获取数据库连接
			conn = JDBCUtils.getConnection();
			// 2.预编译sql语句,得到PreparedStatement对象
			ps = conn.prepareStatement(sql);
			// 3.填充占位符
			for (int i = 0; i < args.length; i++) {
				ps.setObject(i + 1, args[i]);
			}
			// 4.执行executeQuery(),得到结果集:ResultSet
			rs = ps.executeQuery();
			// 5.得到结果集的元数据:ResultSetMetaData
			ResultSetMetaData rsmd = rs.getMetaData();
			// 6.1通过ResultSetMetaData得到columnCount,columnLabel;通过ResultSet得到列值
			int columnCount = rsmd.getColumnCount();
			if (rs.next()) {
				T t = clazz.newInstance();
				for (int i = 0; i < columnCount; i++) {// 遍历每一个列
					// 获取列值
					Object columnVal = rs.getObject(i + 1);
					// 获取列的别名:列的别名,使用类的属性名充当
					String columnLabel = rsmd.getColumnLabel(i + 1);
					// 6.2使用反射,给对象的相应属性赋值
					Field field = clazz.getDeclaredField(columnLabel);
					field.setAccessible(true);
					field.set(t, columnVal);
				}
				return t;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 7.关闭资源
			JDBCUtils.closeResource(conn, ps, rs);
		}
		return null;
	}

6. ResultSet与ResultSetMetaData

ResultSet

  1. ResultSet是PreparedStatement的查询后返回的结果集,结果集不包含数据表中的字段名
  2. ResultSet 维护了一个指向当前数据的游标,游标在第一行上方, 当调用next()方法时,检车下一行是否有效,若有效,则返回true,进入下一行
    在这里插入图片描述

ResultSetMetaData

  1. ResultSetMetaData是ResultSet返回数据表中的元数据
  2. 且只包含数据表中字段名

可用于获取关于 ResultSet 对象中列的类型和属性信息的对象

  • ResultSetMetaData meta = rs.getMetaData();
    • getColumnName(int column):获取指定列的名称

    • getColumnLabel(int column):获取指定列的别名

    • getColumnCount():返回当前 ResultSet 对象中的列数。

    • getColumnTypeName(int column):检索指定列的数据库特定的类型名称。

    • getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。

    • isNullable(int column):指示指定列中的值是否可以为 null。

    • isAutoIncrement(int column):指示是否自动为指定列进行编号,这样这些列仍然是只读的。

7. 创建DAO的通用的数据库连接方式

DAO(Data Access Object) 数据访问对象

7.1 DAO类: 通用增删改查操作
/**
 * @author gdcho
 * @create -08-18
 */
public class DataAccessObject {

    //①、DAO类, 通用的针对不同表的查询: 返回全部
    public static <E> List<E> getAllRow(Connection con, String sql,Class<E> clazz,Object ...obj){
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<E> list = null;
        try {
            // 1.获取数据库连接
            // 2.预编译sql语句,得到PreparedStatement对象
            ps = con.prepareStatement(sql);

            for (int i = 0; i < obj.length; i++) {
                // 3.填充SQL语句的占位符
                ps.setObject(i+1,obj[i]);
            }
            // 4.执行executeQuery(),得到结果集:ResultSet
            rs = ps.executeQuery();
            // 5.得到结果集的元数据:ResultSetMetaData
            ResultSetMetaData md = rs.getMetaData();
            //6.获取数据表中的字段数
            int columnCount = md.getColumnCount();
            //7.创建ArrayAList()实现类用于存储对象
            list = new ArrayList<>();
            //8.检车下一行是否有效,若有效,则返回true,进入下一行
            while (rs.next()) {
                //9.使用泛型对象获取实例
                E e = clazz.newInstance();
                //10.遍历每个字段的元素
                for (int i = 0; i < columnCount; i++) {
                    //11.获取当前字段的元素
                    Object columnVal = rs.getObject(i + 1);
                    //12.获取当前字段的字段名
                    String columnLabel = md.getColumnLabel(i + 1);
                    //13.通过反射把获取的字段名与属性名匹配
                    Field field = e.getClass().getDeclaredField(columnLabel);
                    //14.设置安全访问,使得能访问private的属性
                    field.setAccessible(true);
                    //15.存储元素
                    field.set(e,columnVal);
                }
                //16.将实例对象存储进list
                list.add(e);
            }
            //17.返回list 便于调用时候遍历list里的对象
            return list;
        } catch (Exception throwables) {
            throwables.printStackTrace();
        } finally {
            Connect.clseResource(null,rs,ps);
        }
        return null;
    }

    //②、DAO类, 通用的针对不同表的查询: 返回单行
    public static <E> E getOneRow(Connection con, String sql, Class<E> clazz, Object... obj){
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = con.prepareStatement(sql);
            for (int i = 0; i < obj.length; i++) {
                ps.setObject(i+1,obj[i]);
            }
            rs = ps.executeQuery();
            ResultSetMetaData md = rs.getMetaData();
            int columnCount = md.getColumnCount();
            while (rs.next()) {
                E e = clazz.newInstance();
                for (int i = 0; i < columnCount; i++) {
                    Object columnVal = rs.getObject(i + 1);
                    String columnLabel = md.getColumnLabel(i + 1);
                    Field field = e.getClass().getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(e,columnVal);
                }
                return e;
            }
        } catch (Exception throwables) {
            throwables.printStackTrace();
        } finally {
            Connect.clseResource(null,rs,ps);
        }
        return null;
    }

    //③、DAO类, CUDR操作
    public static void toUpdate(Connection con,String sql,Object ...obj){
        PreparedStatement ps = null;
        try {
            ps = con.prepareStatement(sql);
            for (int i = 0; i < obj.length; i++) {
                ps.setObject(i+1,obj[i]);
            }
            ps.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            Connect.clseResource(null,ps);
        }
    }

    //④、DAO类, 查询单行单列
    public static <E> E getCount(Connection con,String sql,Object ... obj){
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = con.prepareStatement(sql);
            for (int i = 0; i < obj.length; i++) {
                ps.setObject(i+1,obj[i]);
            }
            rs = ps.executeQuery();
            while (rs.next()) {
                return (E) rs.getObject(1);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            Connect.clseResource(null, rs,ps);
        }
        return null;
    }
}

7.2 创建DAO通用操作接口

接口后需创建一个泛型, 作为实现类需要指明的泛型

//接口后创建一个泛型
public interface DataAccessObjectInterface<E> {
    //查询一行
    E toQueryOneRow(Connection con,int id);
    //查询多行
    List<E> toQueryAllRow(Connection con);
    //增加一行
    void insertOneRow(Connection con,E e);
    //删除一行
    void deleteOneRow(Connection con, int id);
    //查询总数
    Object toCount(Connection con);
    //查询最大值
    Object toMaxValue(Connection con);
}
针对单独的数据表创建JavaBean

JavaBean类中的属性名一 一对应数据表中的字段名

public class Customers {
    private long id;
    private String name;
    private String email;
    private Date birth;

    public Customers(long id, String name, String email, Date birth) {
        this.id = id;
        this.name = name;
        this.email = email;
        this.birth = birth;
    }

    public Customers() {
    }

    @Override
    public String toString() {
        return "Customers{" + "id=" + id + ", name='" + name + '\'' + ", email='" + email + '\'' + ", birth=" + birth + '}';
    }
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
    public Date getBirth() {
        return birth;
    }
    public void setBirth(Date birth) {
        this.birth = birth;
    }
}
7.3 创建DAO实现类

实现类必须继承DAO类与实现DAO通用操作接口,并重写接口中的抽象方法

public class DataAccessObjectImpl extends DataAccessObject implements DataAccessObjectInterface<Customers>{

    @Override
    public Customers toQueryOneRow(Connection con, int id) {
        String sql = "select id,name,email,birth from customers where id = ?";
        return getOneRow(con,sql,Customers.class,id);
    }

    @Override
    public List<Customers> toQueryAllRow(Connection con) {
        String sql = "select id,name,email,birth from customers";
        return getAllRow(con, sql, Customers.class);
    }

    @Override
    public void insertOneRow(Connection con, Customers cust) {
        String sql = "insert into customers(id,name,email,birth) values(?,?,?,?)";
        toUpdate(con,sql,cust.getId(),cust.getName(),cust.getEmail(),cust.getBirth());
    }

    @Override
    public void deleteOneRow(Connection con, int id) {
        String sql = "delete from customers where id = ?";
        toUpdate(con,sql,id);
    }

    @Override
    public Object toCount(Connection con) {
        String sql = "select count(*) from customers";
        return getCount(con,sql);
    }

    @Override
    public Object toMaxValue(Connection con) {
        String sql = "select max(birth) from customers";
        return getCount(con,sql);
    }
}

7.5 测试实现类的方法
public class DataAccessObjectImplTest {
    public static void main(String[] args) {
        Connection con = null;
        try {
            DataAccessObjectImpl dataAccessObject = new DataAccessObjectImpl();
            con = Connect.getConnection();

            //查询总数
            Object o = dataAccessObject.toCount(con);
            System.out.println("COUNT("+o+")");

            //查询最大值
            Object o1 = dataAccessObject.toMaxValue(con);
            System.out.println("MAX_BIRTH("+o1+")");
            System.out.println();

            //查询多行
            List<Customers> list = dataAccessObject.toQueryAllRow(con);
            list.stream().forEach(System.out::println);
            System.out.println();

            //查询单行
            Customers cust = dataAccessObject.toQueryOneRow(con, 5);
            System.out.println(cust);

            //插入一行
            Date date = new Date();
            Customers doctor = new Customers(24, "Doctor", "doc@126.com", date);
            dataAccessObject.insertOneRow(con,doctor);
            
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception throwables) {
            throwables.printStackTrace();
        } finally {
            Connect.clseResource(con,null,null);
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值