使用PreparedStatement对数据库表进行操作

  • 使用PreparedStatement实现CRUD操作

CRUD:增、删、改、查

2.1操作和访问数据库

1、数据库连接被用于向数据库服务器发送命令和SQL语句,并接受数据库服务器返回的结果。其实一个数据库连接就是一个Socket连接。

2、在java.sql包中有三个接口分别定义了对数据库的调用的不同方式:

    Statement:用于执行静态SQL语句并返回它所生成结果的对象。

    PrepatedStatement:SQL语句被预编译并存储在此对象中,可以使用此对象多次高效地执行该语句。

    CallableStatement:用于执行SQL存储过程

2.2 Statement操作数据库的弊端

问题1:存在拼串操作,繁琐

String sql="SELECT USER,PASSWORD FROM user_table WHERE user='"+user+"' AND password='"+password+"'";

 

问题2:存在SQL注入问题

SQL注入利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中并注入非法的SQL语句段或命令(eg:SELECT user,password FROM user_table Where user=’a’ OR 1=’AND password=’OR’1’=’1’),从而利用系统的SQL引擎完成恶意行为的做法。

代码演示

	@Test
	public void testLogin() {
		Scanner sc=new Scanner(System.in);
		System.out.println("请输入用户名");
		String user = sc.next();
		System.out.println("请输入密码");
		String password=sc.next();
		String sql="SELECT USER,PASSWORD FROM user_table WHERE user='"+user+"' AND password='"+password+"'";
		User user1 = get(sql, User.class);
		if (user1!=null){
			System.out.println("登陆成功");
		}else {
			System.out.println("用户名不存在或者密码不存在");
		}

 

为避免出现sql注入:只要使用PreparedStatement(从Statement扩展而来)取代Statement

2.3 PreparedStatement实现表数据的添加操作

操作数据库的方法变化

Driver代表数据库驱动:使用DriverManager创建Driver对象

Connection代表数据库连接:jdbc:mysql://localhost:3306(mysql 8.0)13306(mysql 5.0)/表名

PreparedStatement代表数据库操作:代表的预编译的SQL语句

常用方法:PreparedStatement(String sql)

 

PreparedStatement代码实现

 

添加操作

  1. 配置文件,系统类加载器,通过Properties获取配置文件信息

 

  try {
            //读取配置文件的4个基本信息
            //系统类加载器
            //file=new File("E:\\Idea-workspace\\ConnectionJava\\src\\jdbc_1.Properties");
            //is=new FileInputStream(file);
            is= ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc_1.properties");
             properties=new Properties();
            properties.load(is);
            String user = properties.getProperty("user");
            String password = properties.getProperty("password");
            String url=properties.getProperty("url");
            String dirverClass=properties.getProperty("dirverClass");

(2)加载驱动——dirverClass和获取连接 

 //加载驱动
            Class.forName(dirverClass);
            //获取连接
            connection= DriverManager.getConnection(url, user, password);
            System.out.println(connection);

(3)通过PreparedStatement预编译SQL语句——获得PreparedStatement的实例 

//预编译SQL语句——返回PreparedStatement的实例
            String sql="insert into customers(name,email,birth)values(?,?,?)";//?为占位符
            ps = connection.prepareStatement(sql);

 (4)填充占位符,为SQL语句赋值

 //填充占位符
            ps.setString(1,"艾薇儿");
            ps.setString(2,"aiweier@qq.com");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            java.util.Date date = sdf.parse("1999-02-02");
            ps.setDate(3,new Date(date.getTime()));

 (5)执行SQL语句

 //执行SQL语句
            ps.execute();
            System.out.println("插入成功");

完整代码如下 

 @Test
    public void testInsert(){
        InputStream is=null;
        Properties properties=null;
        Connection connection=null;
        PreparedStatement ps=null;
        //File file=null;
        try {
            //读取配置文件的4个基本信息
            //系统类加载器
            //file=new File("E:\\Idea-workspace\\ConnectionJava\\src\\jdbc_1.Properties");
            //is=new FileInputStream(file);
            is= ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc_1.properties");
             properties=new Properties();
            properties.load(is);
            String user = properties.getProperty("user");
            String password = properties.getProperty("password");
            String url=properties.getProperty("url");
            String dirverClass=properties.getProperty("dirverClass");
            //加载驱动
            Class.forName(dirverClass);
            //获取连接
            connection= DriverManager.getConnection(url, user, password);
            System.out.println(connection);
            //预编译SQL语句——返回PreparedStatement的实例
            String sql="insert into customers(name,email,birth)values(?,?,?)";//?为占位符
            ps = connection.prepareStatement(sql);
            //填充占位符
            ps.setString(1,"艾薇儿");
            ps.setString(2,"aiweier@qq.com");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            java.util.Date date = sdf.parse("1999-02-02");
            ps.setDate(3,new Date(date.getTime()));
            //执行SQL语句
            ps.execute();
            System.out.println("插入成功");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                if (is!=null)
                    is.close();
            }catch (Exception e){
                e.printStackTrace();
            }
            try {
                if (connection!=null)
                    connection.close();
            }catch (Exception e){
                e.printStackTrace();
            }
            try {
                if (ps!=null)
                    ps.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }

对于操作数据库常用方法的封装

因为在大多数数据库连接中不能缺少对配置文件的获取、数据库的连接和数据库的资源和Statement的关闭操作,于是将他们全部封装在一个JDBCUtils中,直接使用方法调用,减少代码冗余。

  1. getConnection()方法,对配置文件进行获取以及数据库连接
 /**
     * 获取数据库连接操作
     * @return Connection的对象,获得连接
     */
    public static Connection getConnection() {
        InputStream is = null;
        File file = null;
        Properties properties = null;
        Connection connection=null;
        try {
            //读取配置文件的4个基本信息
//            file = new File("jdbc_1.properties");
            is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc_1.properties");
            properties = new Properties();
            properties.load(is);
            String user = properties.getProperty("user");
            String password = properties.getProperty("password");
            String url = properties.getProperty("url");
            String dirverClass = properties.getProperty("dirverClass");
            //加载驱动
            Class.forName(dirverClass);
            //获取连接
            connection= DriverManager.getConnection(url, user, password);
            System.out.println(connection);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null)
                    is.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        return connection;
    }

 2.对连接和Statement的关闭

 /**
     * 关闭连接和Statement的操作
     * @param connection
     * @param ps
     */
    public static  void closeResource(Connection connection, Statement ps){
        try {
            if (connection!=null)
                connection.close();
        }catch (Exception e){
            e.printStackTrace();
        }
        try {
            if (ps!=null)
                ps.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

修改操作

 /**
     * 修改customer表中的一条记录
     */
    @Test
    public void test2(){
        Connection connection = null;
        PreparedStatement ps = null;
        try {
            //获取数据库连接
            connection = JDBCutils.getConnection();
            //预编译SQL语句——返回PreparedStatement的实例
            String sql="update customers set name=? where id=?";
            ps = connection.prepareStatement(sql);
            //填充占位符
            ps.setObject(1,"莫扎特");
            ps.setInt(2,18);
            //执行SQL语句
            ps.execute();
            System.out.println("修改成功");
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            //资源的关闭
            JDBCutils.closeResource(connection,ps);
        }

    }

 

通过调用JDBCUtils的两个静态方法,减少了代码长度,使代码更好维护

通用增删改操作

因为增删改这三个操作的不同只有在预编译SQL语言时体现,则只需要通过形参来改变则就可以使增删改方法变的简便

(1)增删改的封装方法

  /**
     * 通用的增删改操作
     */
    @Test
    public void testUpdate(){
        String sql="delete from customers where id=?";
        update(sql,3,4,5);//删除id=3,4,5的三条数据
    }
    //sql中的占位符应该与可变形参obj的长度相同
    public void update(String sql,Object ...objects) {
        Connection connection = null;
        PreparedStatement ps = null;
        try {
            //获取数据库的连接
            connection = JDBCutils.getConnection();
            //预编译SQL语句
            ps = connection.prepareStatement(sql);
            //填充占位符
            for (int i = 0; i < objects.length; i++) {
                ps.setObject(i+1,objects[i]);
            }
            //执行操作
            ps.execute();
            System.out.println("操作完成");
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            //关闭资源
            JDBCutils.closeResource(connection,ps);
        }

    }
}

 (2)对封装方法的测试

 /**
     * 通用的增删改操作
     */
    @Test
    public void testUpdate(){
        String sql="delete from customers where id=?";
        update(sql,3,4,5);//删除id=3,4,5的三条数据
    }

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

物理变化

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值