编写java程序时,一般一个类(或者接口)都是放在一个独立的java文件中,并且类名同文件名(如果类是public的,类名必须与文件名一致;非public得,无强制要求)。如果想把多个java类放在一个java文件中,则只能有一个public类。如下面的两个类放在同一个文件中就会报错,无法编译通过。 可以看出,因为TestOne.java文件中已经有一个public类TestOne,这时再加了一个public类TestTwo就报错了。如果将类TestTwo前面的public修饰符去掉就没有问题了。 我们下面介绍内部类的概念和使用,所谓内部类,简单的说,就是一个类定义在另一个类的内部。与上面的两个类在同一个文件中不同(TestOne和TestTwo虽然在一个文件中,但相互没有嵌套,是并列的)。 采用内部类,有时会对代码的可读性带来一点问题,但很多场景下还是很有必要的。尤其在使用一些框架(如java的swing,集合框架中的排序操作)等,使用内部类(尤其是匿名内部类)会带来很多便利;再比如我们在开发Android app时,就会大量的使用内部类,如果不了解内部类的含义和使用规则,几乎无法顺利的进行Android app的开发。 内部类有其特别的地方,其中核心之一是,内部类实例可以访问包含它的外部类的所有成员,包括private成员。另外非常关键的一点是,内部类的使用必须与一个外部类的实例绑定,注意是实例,后面的例子中会说明这点。 内部类也分好几种情况,下面一一来解释。 一、一般内部类…
JAVA:JDBC入门教程(三) PreparedStatement的使用
前两章我们写了一个 DBTools 工具类,可以进行简单的数据库操作,但是有很大的局限性,今天就来改善一下这个类,学习一个新的对象 PreparedStatement
- 为什么要使用PreparedStatement
前面我们建立了一个store数据库,并且建立了一个user数据表,表里包含字段 id ,account ,password ,role。而且还向里面加入了一条数据 sql 语句是这样写的INSERT INTO store.user (account,password,role) VALUES ('admin','123',1)
我直接把字段的值直接写在了sql语句里,不过通常情况下,(‘admin’,’123’,1) 这里面都是一些变量,为了方便,我们会建立一个实体类,来对应相应的数据库表,现在新建一个 user 实体类
package com.ikeepstudying.domain; public class User { //用户的ID private int id; //用户名 private String account; //密码 private String password; //用户角色 private int role; //无参构造 public User() { super(); } //有参构造 public User(int id, String account, String password, int role) { super(); this.id = id; this.account = account; this.password = password; this.role = role; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getAccount() { return account; } public void setAccount(String account) { this.account = account; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getRole() { return role; } public void setRole(int role) { this.role = role; } }
假设现在又一个 user 实体,里面封装了我们需要的数据,我们要把这个 user 插入数据库中,sql 语句就变成了
"INSERT INTO store.user (account,password,role) VALUES (" + user.getAccount() + ",'" + user.getPassword() + "'," + user.getRole() + ")";
由于我们要在 sql 语句中加入变量,所以我们不得不拼接字符串,这种方式麻烦,效率低,容易出错,安全性不高,PreparedStatement 对象就可以解决以上的问题。
2. 如何使用 PreparedStatement
使用 PreparedStatement 对象操作数据库可以分为一下几步
- 获取数据库连接
- 写sql语句,设置占位符,用 ?代替变量
- 创建PreparedStatement对象
- 为占位符进行赋值
- 执行操作
- 释放资源
下面我们就把上面提到的那个 user 使用PreparedStatement对象插入数据库
@Test public void insertUsers() throws SQLException { User user = new User(2,"master","123",2); //获取数据库连接 Connection conn = DBTools.getConnection(); //写sql语句,设置占位符,用 ?代替变量 String sql = "INSERT INTO store.user (account,password,role) VALUES (?,?,?)"; //创建 PreparedStatement 对象 PreparedStatement preparedStatement = conn.prepareStatement(sql); //为占位符进行赋值 preparedStatement.setString(1,user.getAccount());//第一个参数是第几个占位符,第二个参数是为这个占位符进行赋值 preparedStatement.setString(2,user.getPassword()); preparedStatement.setInt(3,user.getRole()); //执行操作 preparedStatement.executeUpdate(); //释放资源 DBTools.release(null, null, conn); }
测试一下这个类。其他的delete update 方法也一样,我们先前写了一个通用的更新方法 update(String sql),很明显我们不能只把这里带有占位符的 sql 语句传过去,还需要占位符对应的值,所以要对前面的那个方法进行改进。这样的话 update 方法就需要两个形式参数,一个是带有占位符的 sql 语句,另一个是占位符 对应的值。不过不同的 sql 语句占位符的个数也是不同的,所以我们要用到可变参数 Object…args
方法改进如下:
//通用的更新方法 public static void update(String sql,Object...args){ Connection conn = null; PreparedStatement preparedStatement = null; try { //获取数据库连接 conn = DBTools.getConnection(); //创建PreparedStatement对象 preparedStatement = conn.prepareStatement(sql); //通过循环来给sql的占位符赋值 for(int i=0;i<=args.length-1;i++){ preparedStatement.setObject(i+1, args[i]); } //执行更新操作 preparedStatement.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally{ release(null,null,conn); } }
测试一下这个通用方法,改一下 用户名为 master 的密码
@Test public void updatePasswd() { User user = new User(); user.setAccount("master"); user.setPassword("jiaoshou"); user.setRole(1); String sql = "UPDATE store.user SET password=?, role=? WHERE account=?"; DBTools.update(sql, user.getPassword(),user.getRole(),user.getAccount()); }
测试一下,OK!!
JAVA: JDBC入门教程(二) 通过JDBC进行简单的增删改查
JAVA:JDBC入门教程(三) PreparedStatement的使用
本文:JAVA:JDBC入门教程(三) PreparedStatement的使用