JDBC

JDBC

  • JDBC(Java Database Connectivity)是Java连接数据库的一套规范,用来实现对数据库的操作。

1.JDBC API

  • JDBC是由多个接口和类进行功能实现
1.1 DriverManager类
  • 管理多个数据库驱动类,提供了获取数据库连接的方法
1.2 Connection接口
  • 代表一个数据库连接
1.3 Statement接口
  • 发送SQL语句到数据库工具
1.4 ResultSet接口
  • 保存SQL查询语句的结果数据(结果集)
1.5 SQLException类
  • 处理数据库应用程序时所发生的异常

2.JDBC开发步骤

2.1 executeUpdate()
	public class DeleteJdbc {
	    public static void main(String[] args) throws Exception{
	        //1.加载驱动
	        Class.forName("com.mysql.jdbc.Driver");
	        //2.获得连接对象
	        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/companydb","root","1234");
	        //3.获得执行SQL的对象
	        Statement statement = connection.createStatement();
	        //4.执行SQL语句,并接收结果
	        int result = statement.executeUpdate("delete from t_jobs where job_id = 'H5_mgr';");
	        //5.处理结果
	        if(result==1){
	            System.out.println("删除成功!");
	        }else{
	            System.out.println("删除失败!");
	        }
	        //6.释放资源
	        statement.close();
	        connection.close();
	    }
2.2 executeQuery()
	public class JobsQuery {
	    public static void main(String[] args) {
	            //1.加载驱动
	            Class.forName("com.mysql.jdbc.Driver");
	
	            //2.获取数据库连接对象
	            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/product", "root", "1234");
	      
	            //3.获取发送 sql 语句对象
	            Statement statement = connection.createStatement();
	
	            //4.执行 SQL 语句并接收结果集
	            ResultSet resultSet = statement.executeQuery("select  * from t_jobs");
	            //5 处理结果集
	            while(resultSet.next()){
	                //5.1有数据,依据列名获取数据
	                String job_id = resultSet.getString("job_id");
	                String job_title = resultSet.getString("job_title");
	                int min_salary = resultSet.getInt("min_salary");
	                int max_salary = resultSet.getInt("max_salary");
	                System.out.println(job_id+"\t"+job_title+"\t"+min_salary+"\t"+max_salary);
	            }
	       
	            //6.释放资源
			    rs.close();
				statement.close();
				connection.close();
		}
    }

3.常见异常

  • java.lang.ClassNotFoundException
    • 找不到类(类名书写错误、没有导入jar包)
  • java.sql.SQLExceptio
    • 与sql语句相关的错误 (约束错误、表名列名书写错误) 建议:在客户端工具中测试SQL语句之后再粘贴在代码中
  • com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column
    • 原因:列值Sting类型没有加单引号
  • Duplicate entry ‘1’ for key ‘PRIMARY’
    • 原因,主键值已存在或混乱,更改主键值或清空表
  • com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column ‘password’ in
    • 原因:可能输入的值的类型不对,确定是否插入的元素时对应的值的类型正确

4.SQL注入问题

  • 用户输入的数据中有SQL关键字或语法参与了SQL语句的编译,导致SQL语句编译后的条件含义出现不正常的现象,称为SQL注入。

5.PreparedStatement

  • 作用:
    * 预编译SQL语句,效率高
    * 安全,避免SQL注入
    * 可以动态的填充数据,执行多个同构的SQL语句
	//1.预编译 SQL 语句
	PreparedStatement pstmt = conn.prepareStatement("select * from user where username=? and password=?");	 
	//2.为参数下标赋值
	pstmt.setString(1,username);
	pstmt.setString(2,password);

6.对象关系映射(ORM)

  • 在实际应用开发中,我们需要将零散的数据进行封装处理
  • 通过实体类的属性与表字段一一对应,能够将一条记录封装到一个实体对象中
	public class T_Jobs {
	    private String job_id;
	    private String job_title;
	    private int min_salary;
	    private int max_salary;
	
	    @Override
	    public String toString() {
	        return "T_Jobs{" +
	                "job_id='" + job_id + '\'' +
	                ", job_title='" + job_title + '\'' +
	                ", min_salary=" + min_salary +
	                ", max_salary=" + max_salary +
	                '}';
	    }
	
	    public String getJob_id() {
	        return job_id;
	    }
	
	    public void setJob_id(String job_id) {
	        this.job_id = job_id;
	    }
	
	    public String getJob_title() {
	        return job_title;
	    }
	
	    public void setJob_title(String job_title) {
	        this.job_title = job_title;
	    }
	
	    public int getMin_salary() {
	        return min_salary;
	    }
	
	    public void setMin_salary(int min_salary) {
	        this.min_salary = min_salary;
	    }
	
	    public int getMax_salary() {
	        return max_salary;
	    }
	
	    public void setMax_salary(int max_salary) {
	        this.max_salary = max_salary;
	    }
	
	    public T_Jobs() {
	    }
	
	    public T_Jobs(String job_id, String job_title, int min_salary, int max_salary) {
	        this.job_id = job_id;
	        this.job_title = job_title;
	        this.min_salary = min_salary;
	        this.max_salary = max_salary;
	    }
	}

7.JDBC事务

  • JDBC中,可以通过Connection对象控制事务
    • setAutoCommit(false);//设置手动提交事务
    • commit();//提交事务
    • rollback();//回滚事务
  • JDBC中控制事务必须确保是同一个连接
	 /**
     * 开启事务
     */
    public static void beginTransaction() {
        Connection connection = getConnection();
        try {
            connection.setAutoCommit(false);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 提交事务
     */
    public static void commit() {
        Connection connection = getConnection();
        try {
            connection.commit();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(connection);
        }
    }

    /**
     * 回滚事务
     */
    public static void rollback() {
        Connection connection = getConnection();
        try {
            connection.rollback();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(connection);
        }
    }
	//开启事务,进行转账
	DBUtils.beginTransaction();

	try {
		//转出余额
		accountDao.outMoney(username, money);
		//模拟出现异常
		//int i = 10 / 0;
		//转入余额
		accountDao.inMoney(outName, money);
		//未出现异常,提交事务
		DBUtils.commit();
		System.out.println("转账成功!");
	} catch (Exception e) {
		System.err.println("转账失败!");
		//出现异常,回滚事务
		DBUtils.rollback();
	}

8.MVC三层架构

在这里插入图片描述

  • utils 存放工具类(DBUtils)
  • entity 存放实体类(Person)
  • dao 存放 DAO 接口(PersonDao)
    • impl 存放 DAO 接口实现类(PersonDaoImpl)
  • service 存放 service 接口(PersonService)
    • impl 存放 service 接口实现类(PersonServiceImpl)
  • view 存放程序启动类(main)

9.DaoUtils

public class DaoUtils {

    /**
     * 公共的更新方法
     *
     * @param sql  预处理的sql语句
     * @param args 占位符参数
     * @return 受影响的行数
     */
    public static int commonUpdate(String sql, Object... args) {
        Connection connection = DBUtils.getConnection();
        PreparedStatement prst = null;
        try {
            prst = connection.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                prst.setObject(i + 1, args[i]);
            }
            return prst.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtils.close(prst);
        }
        return 0;
    }

    /**
     * 公共的查询方法
     *
     * @param sql  预处理的sql语句
     * @param cls  需要封装的实体类
     * @param args 占位符参数
     * @param <T>  实体类类型
     * @return 实体集合List<T>
     */
    public static <T> List<T> commonQuery(String sql, Class<T> cls, Object... args) {
        Connection connection = DBUtils.getConnection();
        List<T> list = new ArrayList<>();
        PreparedStatement prst = null;
        try {
            prst = connection.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                prst.setObject(i + 1, args[i]);
            }
            ResultSet rs = prst.executeQuery();
            Field[] fields = cls.getDeclaredFields();

            while (rs.next()) {
                try {
                    T t = cls.newInstance();
                    for (int i = 0; i < fields.length; i++) {
                        String filedName = fields[i].getName();
                        Object value;
                        try {
                            //字段名不一致,会出现异常
                            value = rs.getObject(filedName);
                        } catch (SQLException e) {
                            //到配置文件中查找对应字段
                            String colName = DBUtils.getProperties().getProperty(filedName);
                            //根据对应字段获取数据
                            value = rs.getObject(colName);
                        }
                        fields[i].setAccessible(true);
                        fields[i].set(t, value);
                    }
                    list.add(t);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtils.close(prst, connection);
        }
        return list;
    }
}

10.Druid连接池

  • 存放连接的容器,实现连接的服用,节省资源
  • 配置文件
	#连接设置
	driverClassName=com.mysql.jdbc.Driver
	url=jdbc:mysql://localhost:3306/school
	username=root
	password=root
	#<!-- 初始化连接 -->
	initialSize=10
	#最大连接数量
	maxActive=50
	#<!-- 最小空闲连接 -->
	minIdle=5
	#<!-- 超时等待时间以毫秒为单位 60000毫秒/1000等于60秒 -->
	maxWait=5000
  • 使用连接池
	public class DBUtils {

    //声名DataSource对象
    private static DataSource dataSource;
    private static Properties properties;

    //使用ThreadLocal管理连接对象
    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

    /**
     *  Properties只需要加载一次
     */
    static {
        properties = new Properties();
        try {
            properties.load(DBUtils.class.getClassLoader().getResourceAsStream("./db.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            //创建连接池
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取数据库连接
     *
     * @return 数据库连接
     */
    public static Connection getConnection() {
        Connection connection = threadLocal.get();
        try {
            if (connection == null) {
                //从连接池中获取连接
                connection = dataSource.getConnection();
                threadLocal.set(connection);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    /**
     * 关闭资源
     *
     * @param args 需要关闭的对象
     */
    public static void close(AutoCloseable... args) {
        for (AutoCloseable arg : args) {
            if (arg != null) {
                try {
                    if (arg instanceof Connection) {
                        threadLocal.remove();
                    }
                    arg.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值