JDBC 是Java的官方数据库连接接口
接口设计为 driver => connect ==> statement, 继而在 statement 交互 各类 sql语句;
connect 阶段
编写代码实例化 driver
改方法的基础步骤全部自己编码实现
public static void main(String[] args) {
try {
Driver driver = new com.mysql.jdbc.Driver();
String url;
Properties info = new Properties();
url = "jdbc:mysql://127.0.0.1:3306/mydb";
info.put("user", "root");
info.put("password", "root");
Connection connection = driver.connect(url, info);
System.out.println(connection); // 输出:com.mysql.jdbc.Connection@15c77fb
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
jdbc:mysql://127.0.0.1:3306/mydb
主协议:jdbc 子协议:mysql
主机名:127.0.0.1:3306
默认数据库:mydb
URL中, 协议名与主机名使用 // 分割
DriverManager注册驱动
对一些基础方法的封装,驱动对象需要注册给DriverManager
public void testRegDriver() {
try {
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
String url = "jdbc:mysql://127.0.0.1:3306/mydb";
String user = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, user,
password);
System.out.println(connection); // 输出:com.mysql.jdbc.Connection@115e69a
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
反射驱动类
所有的驱动类的静态代码块中已添加DriverManager的注册
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
// ~ Static fields/initializers
// ---------------------------------------------
//
// Register ourselves with the DriverManager
//
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
一般使用反射的方式加载一次驱动类字节码即可, 使用该方式可以把Class.forName("com.mysql.jdbc.Driver"); 的驱动类动态配置
public void testRf() {
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/mydb";
String user = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, user,
password);
System.out.println(connection); // 输出:com.mysql.jdbc.Connection@24332f
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
statement交互数据库
statement是一个交互, 可以执行任意sql语句, 在获取到statement的connect权限允许上.
Statement
执行基础的更新语句,返回影响的行数;
public void testStatement() {
Connection connection = getConnection();
int result = 0;
try {
Statement statement = connection.createStatement();
result = statement
.executeUpdate("INSERT mytable( id, NAME, pwd ) VALUES( '3', 'jack', '123a' );");
System.out.println(result);// 输出:1
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
PreparedStatement
可以防止注入, 获取时不采用getXXX(), 其他操作和statement类似;
public void testPreStatement() {
Connection connection = getConnection();
int result = 0;
try {
PreparedStatement preparedStatement = connection
.prepareStatement("INSERT mytable( id, NAME, pwd ) VALUES( ?, ?, ? )");
preparedStatement.setString(1, "4");
preparedStatement.setString(2, "jacj'--"); //能防止注入
preparedStatement.setString(3, "23123a");
//preparedStatement.setString(4, "23123a"); //不能多出参数 也不能少 必须和 ?一致
result = preparedStatement.executeUpdate();
System.out.println(result);// 输出:1
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
查询表
java.sql.ResultSet
该容器是个迭代器, 指向可读元素左边
数据库默认查询出来的数据都是 string, 该容器封装了 getInt getTime 等访问器自动将数据转换, 可以全部取string出来
访问器可以用列名 和整形下标( 1开始 )区分列
public void testQuery() {
Connection connection = getConnection();
try {
PreparedStatement preparedStatement = connection
.prepareStatement("SELECT id,NAME,pwd FROM users WHERE 1=1");
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
System.out.println(resultSet.getString("id") + ","
+ resultSet.getInt("name") + ","
+ resultSet.getString("pwd"));
System.out.println(resultSet.getString(1) + ","
+ resultSet.getInt(2) + ","
+ resultSet.getString(3));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
java.sql.ResultSet滚动
转载:http://www.blogjava.net/juhongtao/archive/2006/01/06/26898.html
mysql无论怎么设置都可以前后滚动, oracle则该参数生效, 数据为1行交互一次, 滚动后即销毁.
设置不敏感的话, 结果集里面的数据一直是初次查询得到的数据
设置敏感的话, 数据和数据库中同步, 其他连接更新数据后, 实时同步
第三个参数决定是否同步数据库
用缺省设置创建时,ResultSet 是一种只能访问一次(one-time-through)、只能向前访问(forward-only)和只读的对象。您只能访问数据一次,如果再次需要该 数据,必须重新查询数据库。
然而,并不只有这一种方式。通过设置 Statement 对象上的参数,您可以控制它产生的 ResultSet。例如:
这个 Statement 现在将产生可以更新并将应用其他数据库用户所作更改的 ResultSet。您还可以在这个 ResultSet 中向前和向后移动。
第一个参数指定 ResultSet 的类型。其选项有:
TYPE_FORWARD_ONLY:缺省类型。只允许向前访问一次,并且不会受到其他用户对该数据库所作更改的影响。
TYPE_SCROLL_INSENSITIVE:允许在列表中向前或向后移动,甚至可以进行特定定位,例如移至列表中的第四个记录或者从当前位置向后移动两个记录。不会受到其他用户对该数据库所作更改的影响。
TYPE_SCROLL_SENSITIVE:象 TYPE_SCROLL_INSENSITIVE 一样,允许在记录中定位。这种类型受到其他用户所作更改的影响。如果用户在执行完查询之后删除一个记录,那个记录将从 ResultSet 中消失。类似的,对数据值的更改也将反映在 ResultSet 中。
第二个参数设置 ResultSet 的并发性,该参数确定是否可以更新 ResultSet。其选项有:
CONCUR_READ_ONLY:这是缺省值,指定不可以更新 ResultSet
CONCUR_UPDATABLE:指定可以更新 ResultSet
然而,并不只有这一种方式。通过设置 Statement 对象上的参数,您可以控制它产生的 ResultSet。例如:
...
Class.forName(driverName);
db = DriverManager.getConnection(connectURL);
Statement statement = db.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE
);
String orderElName = xmlfileEl.getElementsByTagName("order").item(0)
.getFirstChild().getNodeValue();
...
这个 Statement 现在将产生可以更新并将应用其他数据库用户所作更改的 ResultSet。您还可以在这个 ResultSet 中向前和向后移动。
第一个参数指定 ResultSet 的类型。其选项有:
TYPE_FORWARD_ONLY:缺省类型。只允许向前访问一次,并且不会受到其他用户对该数据库所作更改的影响。
TYPE_SCROLL_INSENSITIVE:允许在列表中向前或向后移动,甚至可以进行特定定位,例如移至列表中的第四个记录或者从当前位置向后移动两个记录。不会受到其他用户对该数据库所作更改的影响。
TYPE_SCROLL_SENSITIVE:象 TYPE_SCROLL_INSENSITIVE 一样,允许在记录中定位。这种类型受到其他用户所作更改的影响。如果用户在执行完查询之后删除一个记录,那个记录将从 ResultSet 中消失。类似的,对数据值的更改也将反映在 ResultSet 中。
第二个参数设置 ResultSet 的并发性,该参数确定是否可以更新 ResultSet。其选项有:
CONCUR_READ_ONLY:这是缺省值,指定不可以更新 ResultSet
CONCUR_UPDATABLE:指定可以更新 ResultSet