1 Statement を使用して動的情報を含む SQL ステートメントを実行する場合、いくつかの欠点があります:
ただは、上記の実行計画を再利用します(のでこれは静的 SQL ステートメントです しかし、INSERT INTO userrifo VALUES(1, 'JACK', '122314','141234@QQ.COM','FURY',15600) ) を実行します 実行計画を生成してから実行します
INSERT INTO userrifo VALUES(2, 'rose','122314','141234@QQ.COM ','FURY',15600)内容が異なるため、INSERTすると別の実行プランが再度生成されます。上記の状況が 1000 回実行されると、データベースは 1000 の実行プランを生成します。これはデータベースの効率に深刻な影響を及ぼします したがって、Statement は静的 SQL ステートメントの実行にのみ適しており、動的 SQL ステートメントの実行には適していません。書きやすい
SQLインジェクション問題なし
同じセマンティクスのSQLステートメントのバッチ実行により、実行プランが再利用されます 1 package cn.xiangxu.entity; 2 3 import java.io.Serializable; 4 5 public class User implements Serializable { 6 7 private static final long serialVersionUID = -5109978284633713580L; 8 9 private Integer id;10 private String name;11 private String pwd;12 public User() {13 super();14 // TODO Auto-generated constructor stub15 }16 public User(Integer id, String name, String pwd) {17 super();18 this.id = id;19 this.name = name;20 this.pwd = pwd;21 }22 @Override23 public int hashCode() {24 final int prime = 31;25 int result = 1;26 result = prime * result + ((id == null) ? 0 : id.hashCode());27 return result;28 }29 @Override30 public boolean equals(Object obj) {31 if (this == obj)32 return true;33 if (obj == null)34 return false;35 if (getClass() != obj.getClass())36 return false;37 User other = (User) obj;38 if (id == null) {39 if (other.id != null)40 return false;41 } else if (!id.equals(other.id))42 return false;43 return true;44 }45 public Integer getId() {46 return id;47 }48 public void setId(Integer id) {49 this.id = id;50 }51 public String getName() {52 return name;53 }54 public void setName(String name) {55 this.name = name;56 }57 public String getPwd() {58 return pwd;59 }60 public void setPwd(String pwd) {61 this.pwd = pwd;62 }63 @Override64 public String toString() {65 return "User [id=" + id + ", name=" + name + ", pwd=" + pwd + "]";66 }67 68 69 70 }
1 package testJDBC; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 import java.sql.SQLException; 8 import java.util.ArrayList; 9 import java.util.List;10 11 import org.junit.Test;12 13 import cn.xiangxu.entity.User;14 15 public class TestCase {16 @Test17 public void test01() {18 Connection conn = null;19 PreparedStatement ps = null;20 ResultSet rs = null;21 try {22 Class.forName("com.mysql.jdbc.Driver"); // 加载数据库驱动23 24 conn = DriverManager.getConnection( // 初始化连接对象25 "jdbc:mysql://localhost:3306/test", "root", "182838");26 27 28 String sql = "SELECT * FROM user WHERE pwd = ? "; // 拼接SQL语句,位置参数用?代替29 30 ps = conn.prepareStatement(sql); // 初始化预编译执行对象31 32 ps.setString(1, "182838"); // 设置SQL语句中的位置位置参数(注意:是从1开始数不是从0开始数)33 34 rs = ps.executeQuery(); // 执行SQL语句35 36 List<User> users = new ArrayList<User>(); // 创建一个集合来存放记录对象37 while(rs.next()) { // 遍历结果集38 // System.out.println("====================");39 // System.out.println(rs.getInt("id"));40 // System.out.println(rs.getString("name"));41 // System.out.println(rs.getString("pwd"));42 User user = new User();43 user.setId(rs.getInt("id"));44 user.setName(rs.getString("name"));45 user.setPwd(rs.getString("pwd"));46 users.add(user); // 向集合中添加元素47 }48 49 System.out.println(users); // 打印输出集合50 for(User user : users) {51 System.out.println(user);52 }53 54 // 释放资源55 rs.close();56 ps.close(); 57 conn.close();58 59 } catch (Exception e) {60 // TODO Auto-generated catch block61 e.printStackTrace();62 } finally {63 if(rs != null) {64 try {65 rs.close();66 } catch (SQLException e) {67 // TODO Auto-generated catch block68 e.printStackTrace();69 }70 }71 if(ps != null) {72 try {73 ps.close();74 } catch (SQLException e) {75 // TODO Auto-generated catch block76 e.printStackTrace();77 }78 }79 if(conn != null) {80 try {81 conn.close();82 } catch (SQLException e) {83 // TODO Auto-generated catch block84 e.printStackTrace();85 }86 }87 }88 89 }90 91 }
class Properties extends Hashtable
将properties属性文件的文件输入流加载到Properties对象
将Properties对象中的属性列表保存到输出流文件中
注意:第二个参数表示注释信息(注意:properties文件中不能用中文),在注释信息后面会自动添加一个时间信息
注意:新创建的文件在项目的根目录下面(问题:为什么在eclipse中没有,但是到文件夹中却能找到???)
获取属性值,参数是属性的键
修改属性值,参数1是属性的键,参数2是属性的新值
要求:读取properties配置文件总的属性值,将读取到的属性值进行修改后保存到另外一个properties配置文件中
1 package cn.xiangxu.entity; 2 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 import java.io.InputStream; 6 import java.util.Iterator; 7 import java.util.Properties; 8 9 public class Test {10 public static void main(String[] args) {11 try {12 Properties prop = new Properties(); // 创建Properties对象13 14 // prop.load(new FileInputStream("config.properties")); // 使用这种方式时,配置文件必须放在项目的根目录下15 InputStream is = Test.class.getClassLoader().getResourceAsStream("config/config.properties"); // 读取属性文件16 17 prop.load(is); // 加载属性列表18 19 Iterator<String> it=prop.stringPropertyNames().iterator(); // 将配置文件中的所有key放到一个可迭代对象中20 while(it.hasNext()){ // 利用迭代器模式进行迭代21 String key=it.next(); // 读取下一个迭代对象的下一个元素22 System.out.println(key+":"+prop.getProperty(key)); // 根据key值获取value值(获取属性信息)23 }24 25 is.close(); // 关闭输入流,释放资源26 27 FileOutputStream oFile = new FileOutputStream("b.properties", true);//创建一个输出流文件,true表示追加打开28 prop.setProperty("maxactive", "33"); // 修改属性信息29 prop.store(oFile, "zhe shi yi ge xin de shu xing pei zhi wen jian."); // 将Properties对象中的内容放到刚刚创建的文件中去30 oFile.close(); // 关闭输出流,释放资源31 32 } catch (Exception e) {33 // TODO Auto-generated catch block34 e.printStackTrace();35 } 36 }37 }
等待读取的properties配置文件的位置如下图所示
程序启动时就创建足够多的数据库连接,并将这些连接组成一个连接池,由程序自动地对池中的连接进行申请、使用、释放
》程序初始化时创建连接池
》需要操作数据库时向数据库连接池申请一个可用的数据库连接
》使用完毕后就将数据库连接还给数据库连接池(注意:不是关闭连接,而是交给连接池)
》整个程序退出时,断开所有连接,释放资源(即:管理数据库连接池的那个线程被杀死后才关闭所有的连接)
利用BasicDataSource对象实例化一个连接对象
将这个连接对象放到ThreadLocal对象中
从ThreadLocal对象中获取连接对象
清空ThreadLocal对象
判断连接对象是否释放
项目结构图
2 # deng hao liang bian mei you kong ge, mo wei mei you fen hao3 # hou mian bu neng you kong ge4 driverClassName=com.mysql.jdbc.Driver5 url=jdbc:mysql://localhost:3306/test6 username=root7 password=1828388 maxActive=1009 maxWait=3000
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 "> 2 <modelVersion>4.0.0</modelVersion> 3 <groupId>cn.xiangxu</groupId> 4 <artifactId>testJDBC</artifactId> 5 <version>0.0.1-SNAPSHOT</version> 6 <dependencies> 7 <dependency> 8 <groupId>mysql</groupId> 9 <artifactId>mysql-connector-java</artifactId>10 <version>5.1.37</version>11 </dependency>12 <dependency>13 <groupId>junit</groupId>14 <artifactId>junit</artifactId>15 <version>4.12</version>16 </dependency>17 <dependency>18 <groupId>commons-dbcp</groupId>19 <artifactId>commons-dbcp</artifactId>20 <version>1.4</version>21 </dependency>22 </dependencies>23 </project>
1 package cn.xiangxu.tools; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.sql.Connection; 6 import java.sql.SQLException; 7 import java.util.Properties; 8 9 import org.apache.commons.dbcp.BasicDataSource;10 11 public class DBUtil {12 /*13 * ThreadLocal用于线程跨方法共享数据使用14 * ThreadLocal内部有一个Map, key为需要共享数据的线程本身,value就是其需要共享的数据15 */16 private static ThreadLocal<Connection> tl; // 声明一个类似于仓库的东西17 private static BasicDataSource dataSource; // 声明一个数据库连接池对象18 19 // 静态代码块,在类加载的时候执行,而且只执行一次20 static {21 tl = new ThreadLocal<Connection>(); // 实例化仓库对象22 dataSource = new BasicDataSource(); // 实例数据库连接池对象23 24 Properties prop = new Properties(); // 创建一个Properties对象用(该对象可以用来加载配置文件中的属性列表)25 InputStream is = DBUtil.class.getClassLoader().getResourceAsStream("config/mysql.properties"); // 读取配置文件信息26 try {27 prop.load(is); // 加载配置文件中的属性列表28 29 String driverClassName = prop.getProperty("driverClassName"); // 获取属性信息30 String url = prop.getProperty("url");31 String username = prop.getProperty("username");32 String password = prop.getProperty("password");33 Integer maxActive = Integer.parseInt(prop.getProperty("maxActive"));34 Integer maxWait = Integer.parseInt(prop.getProperty("maxWait"));35 36 dataSource.setDriverClassName(driverClassName); // 初始化数据库连接池(即:配置数据库连接池的先关参数)37 dataSource.setUrl(url);38 dataSource.setUsername(username);39 dataSource.setPassword(password);40 dataSource.setMaxActive(maxActive);41 dataSource.setMaxWait(maxWait);42 43 is.close(); // 关闭输入流,释放资源44 } catch (IOException e) {45 // TODO Auto-generated catch block46 e.printStackTrace();47 } 48 49 }50 51 /**52 * 创建连接对象(注意:静态方法可以直接通过类名来调用)53 * @return 连接对象54 * @throws Exception55 */56 public static Connection getConnection() throws Exception { 57 try {58 Connection conn = dataSource.getConnection(); // 创建连接对象(利用数据库连接池进行创建)59 tl.set(conn); // 将连接对象放到仓库中60 return conn; 61 } catch (Exception e) {62 // TODO Auto-generated catch block63 e.printStackTrace();64 throw e;65 }66 }67 68 /**69 * 关闭连接对象(注意:静态方法可以通过类名直接调用)70 * @throws Exception71 */72 public static void closeConnection() throws Exception {73 Connection conn = tl.get(); // 从仓库中取出连接对象74 tl.remove(); // 清空仓库75 if(conn != null) { // 判断连接对象是否释放资源76 try {77 conn.close();78 } catch (Exception e) {79 // TODO Auto-generated catch block80 e.printStackTrace();81 throw e;82 }83 }84 }85 86 }
1 package testJDBC; 2 3 import java.sql.Connection; 4 import java.sql.PreparedStatement; 5 import java.sql.ResultSet; 6 7 import org.junit.Test; 8 9 import cn.xiangxu.tools.DBUtil;10 11 public class TestDBUtil {12 @Test13 public void test01() {14 try {15 Connection conn = DBUtil.getConnection(); // 创建连接对象16 String sql = "SELECT * FROM user "; // 拼接SQL语句17 PreparedStatement ps = conn.prepareStatement(sql); // 创建执行对象18 ResultSet rs = ps.executeQuery(sql); // 执行SQL语句19 while(rs.next()) { // 遍历结果集20 System.out.println(rs.getString("name"));21 }22 } catch (Exception e) {23 e.printStackTrace();24 } finally { // 关闭连接,释放资源25 try {26 DBUtil.closeConnection();27 } catch (Exception e) {28 e.printStackTrace();29 }30 }31 }32 }
以上がJDBC接続データベース例の説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。