您好,登錄后才能下訂單哦!
一、JDBC(Java Data Base Connectivity)
1、數據庫驅動:
數據庫廠商為了方便開發人員從程序中操作數據庫而提供的一套jar包,通過導入這個jar包就可以調用其中的方法操作數據庫,這樣的jar包就叫做數據庫驅動
2、JDBC:
sun定義的一套標準,本質上是一大堆的操作數據庫的接口,所有數據庫廠商為java設計的數據庫驅動都實現過這套接口,這樣一來,統一了不同數據庫驅動的方法,開發人員只需要學習JDBC就會使用任意數據庫驅動了。
六個步驟實現JDBC:
//1.注冊數據庫驅動
--由于mysql在Driver類的實現中自己注冊了一次,而我們又注冊了一次,于是會導致MySql驅動被注冊兩次。
--創建MySql的Driver對象時,導致了程序和具體的Mysql驅動綁死在了一起,在切換數據庫時需要改動java代碼。
//DriverManager.registerDriver(new Driver());
Class.forName("com.mysql.jdbc.Driver");
//2.從客戶端發出一個和數據庫服務端的連接,url=哪臺主機哪個端口哪個數據庫
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day10", "root", "root");
//3.獲取傳輸器對象。連接=路;傳輸器=卡車,載數據。
Statement stat = conn.createStatement();
//4.利用傳輸器傳輸sql語句到數據庫中執行,獲取結果集對象
ResultSet rs = stat.executeQuery("select * from user");
//5.遍歷結果集獲取查詢結果
//有一個小游標一行一行的指向結果集,最后一行沒東西了返回false
//ResultSet用于代表Sql語句的執行結果。封裝執行結果采用的類似于表格的方式。ResultSet 對象維護了一個指向表格數據行的游標,初始的時候,游標在第一行之前,第一次調用ResultSet.next() 方法,游標指向第一行數據,再次調用ResultSet.next()方法,指向下一行,也就是第二行數據。
while(rs.next()){ String name = rs.getString("name");
System.out.println(name);
}
//6.關閉資源
rs.close();
stat.close();
conn.close();
Connection對象,它是非常稀有的資源,用完后必須馬上釋放,如果Connection不能及時、正確的關閉,極易導致系統宕機。
為確保資源釋放代碼能運行,資源釋放代碼也一定要放在finally語句中。
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try{...... .......
}catch (Exception e) {
e.printStackTrace();
}finally{
//6.關閉資源
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
rs = null;
}
}
if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
stat = null;
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
conn = null;
}
}
}
config.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///day10
user=root
password=root
JDBCUtils.java
public class JDBCUtils {
private staticProperties prop = null;
private JDBCUtils() {
}
static{
try{
prop = new Properties();
prop.load(new FileReader(JDBCUtils.class.getClassLoader().getResource("config.properties").getPath()));
}catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
//連接
public static Connection getConn() throws ClassNotFoundException, SQLException{
// 1.注冊數據庫驅動
Class.forName(prop.getProperty("driver"));
// 2.獲取連接
return DriverManager.getConnection(prop.getProperty("url"), prop.getProperty("user"), prop.getProperty("password"));
//關閉
public static void close(ResultSet rs, Statement stat,Connection conn) {.......}
JDBCDemo2.java
@Test
public void update() {
Connection conn = null;
Statement stat = null;
try{
conn = JDBCUtils.getConn();
stat = conn.createStatement();
stat.executeUpdate("update user set password=999 where name='zhaoliu'");
}catch (Exception e) {
e.printStackTrace();
}finally{
JDBCUtils.close(null, stat, conn);
}
}
層與層耦合的概念,利用工廠類解耦,service如何用dao? DaoFactory.getFactory().getDao();
public class DaoFactory {
private static DaoFactory factory = new DaoFactory();
private static Properties prop = null;
static{ try{
prop = new Properties();
prop.load(new FileReader(DaoFactory.class.getClassLoader().getResource("config.properties").getPath()));
}catch (Exception e) { e.printStackTrace();
throw new RuntimeException(e); } }
private DaoFactory() { }
public static DaoFactory getFactory(){
return factory; }
public UserDao getDao(){
try{
String clazz = prop.getProperty("UserDao");
return (UserDao) Class.forName(clazz).newInstance();
}catch (Exception e) { e.printStackTrace();
throw new RuntimeException(e); } } }
由于dao中執行的SQL語句是拼接出來的,其中有一部分內容是由用戶從客戶端傳入,所以當用戶傳入的數據中包含sql關鍵字時,就有可能通過這些關鍵字改變sql語句的語義,從而執行一些特殊的操作,這樣的***方式就叫做sql注入***
利用預編譯的機制將sql語句的主干和參數分別傳輸給數據庫服務器,從而使數據庫分辨的出哪些是sql語句的主干哪些是參數,這樣一來即使參數中帶了sql的關鍵字,數據庫服務器也僅僅將他當作參數值使用,關鍵字不會起作用,從而從原理上防止了sql注入的問題
PreparedStatement主要有如下的三個優點:
1.可以防止sql注入
2.由于使用了預編譯機制,執行的效率要高于Statement
3.sql語句使用?形式替代參數,然后再用方法設置?的值,比起拼接字符串,代碼更加優雅.
數據庫中存儲的是大數據的路徑,大數據存在硬盤上,從數據庫讀大數據費時費力。
了解即可
*JDBC大數據
Text Blob
1.1設置Text類型
PreparedStatement.setCharacterStream(index, reader, length);
//注意length長度須設置,并且設置為int型
//當包過大時修改配置:[mysqld] max_allowed_packet=64M
1.2獲取Text類型
reader = resultSet. getCharacterStream(i);
2.1設置BLOB數據類型
PreparedStatement. setBinaryStream(i, inputStream, length);
2.1獲取BLOB類型
InputStream in = resultSet.getBinaryStream(i);
InputStream in = resultSet.getBlob(i).getBinaryStream();
public class BlobDemo1 {
@Test
public void findBlob(){
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
conn = JDBCUtils.getConn();
ps = conn.prepareStatement("select * from blobdemo");
rs = ps.executeQuery();
while(rs.next()){
String name = rs.getString("name");
InputStream in = rs.getBinaryStream("content");
OutputStream out = new FileOutputStream(name);
byte [] bs = new byte[1024];
int i = 0;
while((i=in.read(bs))!=-1){
out.write(bs,0,i);
}
in.close();
out.close();
}
}catch (Exception e) {
e.printStackTrace();
}finally{
JDBCUtils.close(rs, ps, conn);
}
}
@Test
public void addBlob(){
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
conn = JDBCUtils.getConn();
ps = conn.prepareStatement("insert into blobdemo values (null,?,?)");
ps.setString(1, "洛天依.mp3");
File file = new File("1.mp3");
ps.setBinaryStream(2, new FileInputStream(file),(int)file.length());
ps.executeUpdate();
}catch (Exception e) {
e.printStackTrace();
}finally{
JDBCUtils.close(rs, ps, conn);
}
}
}
業務場景:當需要向數據庫發送一批SQL語句執行時,應避免向數據庫一條條的發送執行,而應采用JDBC的批處理機制,以提升執行效率。
Statement.addBatch(sql) 執行批處理SQL語句
executeBatch()方法:執行批處理命令
clearBatch()方法:清除批處理命令
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtil.getConnection();
String sql1 = "insert into person(name,password,email,birthday)
values('kkk','123','abc@sina.com','1978-08-08')";
String sql2 = "update user set password='123456' where id=3";
st = conn.createStatement();
st.addBatch(sql1); //把SQL語句加入到批命令中
st.addBatch(sql2); //把SQL語句加入到批命令中
st.executeBatch();
} finally{
JdbcUtil.free(conn, st, rs);
}
采用Statement.addBatch(sql)方式實現批處理:
優點:可以向數據庫發送多條不同的SQL語句。
缺點:
SQL語句沒有預編譯。
當向數據庫發送多條語句相同,但僅參數不同的SQL語句時,需重復寫上很多條SQL語句。
PreparedStatement.addBatch()
conn = JdbcUtil.getConnection();
String sql = "insert into person(name,password,email,birthday) values(?,?,?,?)";
st = conn.prepareStatement(sql);
for(int i=0;i<50000;i++){
st.setString(1, "aaa" + i);
st.setString(2, "123" + i);
st.setString(3, "aaa" + i + "@sina.com");
st.setDate(4,new Date(1980, 10, 10));
st.addBatch();
if(i%1000==0){
st.executeBatch();
st.clearBatch();
}
}
st.executeBatch();
采用PreparedStatement.addBatch()實現批處理
優點:發送的是預編譯后的SQL語句,執行效率高。
缺點:只能應用在SQL語句相同,但參數不同的批處理中。因此此種形式的批處理經常用于在同一個表中批量插入數據,或批量更新表的數據。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。