回顧
1. MySQL性能
數(shù)據(jù)庫類型
查詢密集型
修改密集型
查詢sql執(zhí)行次數(shù)(innodb存儲(chǔ)引擎)
慢查詢?nèi)罩颈O(jiān)控(我們需要手動(dòng)開啟)
2. MySQL索引
索引=排好序的數(shù)據(jù)結(jié)構(gòu)
數(shù)據(jù)結(jié)構(gòu)
二叉樹
紅黑樹
BTree
B+Tree
hash
創(chuàng)建表時(shí)指定索引
create table 表名(
id int primary key auto_increment,
`name` varchar(32),
`telephone` varchar(11),
index(`name`),
unique(`telephone`)
);
索引創(chuàng)建原則
1)內(nèi)容可識(shí)別度不低于70%
2)作為條件查詢的字段
3)作為表連接字段(主鍵寓盗、外鍵)
4)經(jīng)常排序的字段
數(shù)據(jù)庫存儲(chǔ)引擎
myisam:非聚集索引
innodb:聚集索引
mycat:數(shù)據(jù)庫中間件
JDBC
今日目標(biāo)
1. JDBC基礎(chǔ)
2. 用戶登錄案例【大作業(yè)】
B/S架構(gòu)弟胀,編寫用戶登錄案例
一 JDBC基礎(chǔ)
1.1 概述
Java 數(shù)據(jù)庫連接(Java DataBase Connectivity)
作用:通過Java語言操作數(shù)據(jù)庫
本質(zhì):是官方(sun公司)定義的一套操作所有關(guān)系型數(shù)據(jù)庫的規(guī)則(接口)丘喻。各個(gè)數(shù)據(jù)庫廠商去實(shí)現(xiàn)這套接口沦辙,提供數(shù)據(jù)庫驅(qū)動(dòng)jar包踩窖。我們可以使用這套接口(JDBC)編程势就,運(yùn)行時(shí)的代碼其實(shí)是驅(qū)動(dòng)jar包中的實(shí)現(xiàn)類杀饵。
1.2 快速入門
需求
通過java代碼向數(shù)據(jù)庫user表插入一條記錄
① 準(zhǔn)備數(shù)據(jù)庫和表
② 創(chuàng)建java工程,導(dǎo)入MySQL驅(qū)動(dòng)jar包
③ 編寫插入代碼
// 1.注冊(cè)驅(qū)動(dòng)
// 2.建立連接
// 3.編寫sql
// 4.獲取sql執(zhí)行對(duì)象
// 5.執(zhí)行sql并返回結(jié)果
// 6.處理結(jié)果
// 7.釋放資源
public class JDBCQuick {
public static void main(String[] args) throws Exception {
// 1.注冊(cè)驅(qū)動(dòng)
DriverManager.registerDriver(new Driver());
// 2.建立連接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day23", "root", "root");
// 3.編寫sql(在java編寫sql 結(jié)尾咙鞍;可以省略)
String sql = "insert into user values(null,'lucy','666')";
// 4.獲取sql執(zhí)行對(duì)象
Statement statement = connection.createStatement();
// 5.執(zhí)行sql并返回結(jié)果
int i = statement.executeUpdate(sql);
// 6.處理結(jié)果
if (i>0) {
System.out.println("添加成功");
}else{
System.out.println("添加失敗");
}
// 7.釋放資源
statement.close();
connection.close();
}
}
1.3 API介紹
sun公司提供的:java.sql包下
DriverManager:驅(qū)動(dòng)管理對(duì)象
1. 注冊(cè)驅(qū)動(dòng)
1)【了解】
static void registerDriver(Driver driver)
我們通過翻看MySQL Driver實(shí)現(xiàn)類的源碼發(fā)現(xiàn)內(nèi)部的靜態(tài)代碼已經(jīng)提供了注冊(cè)驅(qū)動(dòng)功能
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
2)反射【掌握】
Class.forName("com.mysql.jdbc.Driver");
3)SPI 服務(wù)提供接口 【Service Provider Interface】
2. 建立連接
static Connection getConnection(String url, String user, String password)
參數(shù)說明:
url:連接指定數(shù)據(jù)庫地址【固定格式】
格式:jdbc:mysql://ip地址+端口/數(shù)據(jù)庫名
實(shí)例:
jdbc:mysql://localhost:3306/day23
jdbc:mysql:///day23
user:用戶名
password:密碼
Connection:數(shù)據(jù)庫連接對(duì)象
1. 獲取sql執(zhí)行對(duì)象【小貨車】
Statement createStatement() 【今天】
PreparedStatement prepareStatement(String sql) 【后天】
2. 事務(wù)管理
1)關(guān)閉自動(dòng)提交(開啟事務(wù))
void setAutoCommit(boolean autoCommit)
參數(shù):
true:自動(dòng)提交【默認(rèn)值】
false:手動(dòng)提交
2)提交事務(wù)
void commit()
3)回滾事務(wù)
void rollback()
Statement:執(zhí)行sql的對(duì)象
1. 執(zhí)行所有類型sql語句【了解】
boolean execute(String sql)
----------------------------------
2. 僅執(zhí)行DML類型sql語句
int executeUpdate(String sql)
參數(shù):dml類型sql(insert房官、update、delete)
返回值:影響行數(shù)
3. 僅執(zhí)行DQL類型sql語句
ResultSet executeQuery(String sql)
參數(shù):dql類型sql(select)
返回值:結(jié)果集
ResultSet:結(jié)果集對(duì)象,封裝查詢結(jié)果
1. 指針下移
boolean next()
返回值:
true:表示此行有數(shù)據(jù)
false:表示此行沒有數(shù)據(jù)
2. 獲取數(shù)據(jù)
T getXxx(int 列編號(hào))
T getXxx(String 列名)
補(bǔ)充:獲取所有類型
Object getObject(String 列名)
String getString(String 列名)
1.4 CRUD操作【2续滋、3翰守、4遍...】
// 1.注冊(cè)驅(qū)動(dòng)
// 2.建立連接
// 3.編寫sql
// 4.獲取sql執(zhí)行對(duì)象
// 5.執(zhí)行sql并返回結(jié)果
// 6.處理結(jié)果
// 7.釋放資源
user表 添加一條記錄
// 新增:課下作業(yè)
@Test
public void testInsert()throws Exception{
}
user表 修改一條記錄
// 修改
@Test
public void testUpdate()throws Exception{
// 1.注冊(cè)驅(qū)動(dòng)
Class.forName("com.mysql.jdbc.Driver");
// 2.建立連接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day23", "root", "root");
// 3.編寫sql
String sql = "update user set username = '勒布朗' where id = 5";
// 4.獲取sql執(zhí)行對(duì)象
Statement statement = connection.createStatement();
// 5.執(zhí)行sql并返回結(jié)果
int i = statement.executeUpdate(sql);
// 6.處理結(jié)果
if (i>0) {
System.out.println("修改成功");
}else{
System.out.println("修改失敗");
}
// 7.釋放資源
statement.close();
connection.close();
}
user表 刪除一條記錄
// 刪除
@Test
public void testDelete()throws Exception{
// 1.注冊(cè)驅(qū)動(dòng)
Class.forName("com.mysql.jdbc.Driver");
// 2.建立連接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day23", "root", "root");
// 3.編寫sql
String sql = "delete from user where id = 7";
// 4.獲取sql執(zhí)行對(duì)象
Statement statement = connection.createStatement();
// 5.執(zhí)行sql并返回結(jié)果
int i = statement.executeUpdate(sql);
// 6.處理結(jié)果
if (i>0) {
System.out.println("刪除成功");
}else{
System.out.println("刪除失敗");
}
// 7.釋放資源
statement.close();
connection.close();
}
user表 查詢所有記錄
// 查詢
@Test
public void testFindAll() throws Exception {
// 1.注冊(cè)驅(qū)動(dòng)
Class.forName("com.mysql.jdbc.Driver");
// 2.建立連接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day23", "root", "root");
// 3.編寫sql
String sql = "select * from user";
// 4.獲取sql執(zhí)行對(duì)象
Statement statement = connection.createStatement();
// 5.執(zhí)行sql并返回結(jié)果
ResultSet resultSet = statement.executeQuery(sql);
// 6.處理結(jié)果
while (resultSet.next()) {
// 獲取數(shù)據(jù)
int id = resultSet.getInt("id");
String username = resultSet.getString("username");
String password = resultSet.getString("password");
System.out.println("編號(hào):" + id + " 用戶名:" + username + " 密碼:" + password);
}
// 7.釋放資源
resultSet.close();
statement.close();
connection.close();
}
1.5 工具類【抄一遍...】
? 通過上面案例需求我們會(huì)發(fā)現(xiàn)每次去執(zhí)行SQL語句都需要注冊(cè)驅(qū)動(dòng),獲取連接疲酌,得到Statement蜡峰,以及釋放資源。發(fā)現(xiàn)很多重復(fù)的勞動(dòng)朗恳,我們可以將重復(fù)的代碼定義到一個(gè)工具類中湿颅。
目的:簡(jiǎn)化書寫,一勞永逸
步驟分析
public class JdbcUtils{
// 1.注冊(cè)驅(qū)動(dòng)【保證一次】
static{
}
// 2.提供獲取連接的靜態(tài)方法
public static Connection getConnection(){
return null;
}
// 3.提供釋放資源的方法
public void close(){
}
}
1.5.1 版本一
public class JdbcUitls1 {
// 1.注冊(cè)驅(qū)動(dòng)【保證一次】
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// e.printStackTrace();
throw new RuntimeException("加載mysql驅(qū)動(dòng)失敗");
}
}
// 2.提供獲取連接的靜態(tài)方法
public static Connection getConnection()throws SQLException {
return DriverManager.getConnection("jdbc:mysql://localhost:3306/day23", "root", "root");
}
// 3.提供釋放資源的方法
public static void close(ResultSet resultSet, Statement statement,Connection connection) {
if (resultSet!=null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement!=null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection!=null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// 重載關(guān)閉方法
public static void close(Statement statement,Connection connection){
close(null, statement, connection);
}
}
1.5.2 版本二
抽取配置文件
編寫工具類
public class JdbcUitls {
// 聲明變量
private static String driver = null;
private static String url = null;
private static String user = null;
private static String password = null;
// 加載jdbc.properties配置文件僻肖,初始化變量
static {
// SE階段所學(xué)
// new Properties().load();
// sun公司專門提供了一從src目錄下加載properties類型的工具類 ResourceBundle
ResourceBundle jdbc = ResourceBundle.getBundle("jdbc");
driver = jdbc.getString("jdbc.driver");
url = jdbc.getString("jdbc.url");
user = jdbc.getString("jdbc.user");
password = jdbc.getString("jdbc.password");
}
// 1.注冊(cè)驅(qū)動(dòng)【保證一次】
static {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
// e.printStackTrace();
throw new RuntimeException("加載mysql驅(qū)動(dòng)失敗");
}
}
// 2.提供獲取連接的靜態(tài)方法
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, user, password);
}
// 3.提供釋放資源的方法
public static void close(ResultSet resultSet, Statement statement, Connection connection) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// 重載關(guān)閉方法
public static void close(Statement statement, Connection connection) {
close(null, statement, connection);
}
}
1.6 事務(wù)操作
* 事務(wù)
如果一個(gè)包含多個(gè)步驟的業(yè)務(wù)操作肖爵,被事務(wù)管理卢鹦,那么這些操作要么同時(shí)成功臀脏,要么同時(shí)失敗。
* MySQL操作
1.開啟事務(wù)
begin | start transaction;
2.提交事務(wù)
commit;
3.回顧事務(wù)
rollback;
* java操作(使用Connection對(duì)象)
1.關(guān)閉自動(dòng)提交(開啟事務(wù))
void setAutoCommit(false);
2.提交事務(wù)
void commit();
3.回顧事務(wù)
void rollback();
需求
? 通過java代碼實(shí)現(xiàn)轉(zhuǎn)賬案例
① 導(dǎo)入賬戶表
② 編寫轉(zhuǎn)賬代碼
public class TXDemo{
@Test
public void testTX(){
try{
// 1.獲取連接【JdbcUtils工具類】
// 2.開啟事務(wù)
// 3.羅志祥扣錢
// 機(jī)器故障
// 4.蝴蝶姐加錢
// 5.提交事務(wù)
}catch(Exception e){
// 6.回滾事務(wù)
}finally{
// 7.釋放資源
}
}
}
public class TXDemo {
@Test
public void testTX() {
Connection connection = null;
Statement statement = null;
try {
// 1.獲取連接【JdbcUtils工具類】
connection = JdbcUitls.getConnection();
// 2.開啟事務(wù)
connection.setAutoCommit(false);
tatement = connection.createStatement();
// 3.羅志祥扣錢
// 機(jī)器故障
// 4.蝴蝶姐加錢
// 5.提交事務(wù)
connection.commit();
} catch (Exception e) {
try {
// 6.回滾事務(wù)
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
// 7.釋放資源
JdbcUitls.close(statement, connection);
}
}
}
public class TXDemo {
@Test
public void testTX() {
Connection connection = null;
Statement statement = null;
try {
// 1.獲取連接【JdbcUtils工具類】
connection = JdbcUitls.getConnection();
// 2.開啟事務(wù)
connection.setAutoCommit(false);
statement = connection.createStatement();
// 3.羅志祥扣錢
String xiangSql = "update account set money = money-100 where id = 2";
int xiangResult = statement.executeUpdate(xiangSql);
if (xiangResult > 0) {
System.out.println("羅志祥支付成功~~~");
}
// 機(jī)器故障
int a = 1 / 0;
// 4.蝴蝶姐加錢
String dieSql = "update account set money = money + 100 where id = 1";
int dieResult = statement.executeUpdate(dieSql);
if (dieResult > 0) {
System.out.println("蝴蝶姐收款成功~~~");
}
// 5.提交事務(wù)
connection.commit();
} catch (Exception e) {
e.printStackTrace();
try {
// 6.回滾事務(wù)
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
// 7.釋放資源
JdbcUitls.close(statement, connection);
}
}
}
二 案例:用戶登錄【大作業(yè)】
需求
用戶輸入賬號(hào)和密碼冀自,實(shí)現(xiàn)登錄網(wǎng)站功能
2.1 需求分析
2.2 代碼實(shí)現(xiàn)
① 創(chuàng)建web工程揉稚,并導(dǎo)入jar包
② 導(dǎo)入頁面資源
③ 復(fù)制JdbcUtils工具類
④ LoginServlet
表單提交
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 統(tǒng)一編碼
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
// 1.接收請(qǐng)求
String username = request.getParameter("username");
String password = request.getParameter("password");
try {
// 2.操作JDBC
// 2.1 獲取連接
Connection connection = JdbcUitls.getConnection();
// 2.2 編寫sql
// String sql = "select * from user where username ='admin' and password ='123'";
String sql = "select * from user where username ='" + username + "' and password ='" + password + "'";
System.out.println(sql);
// 2.3 獲取sql執(zhí)行對(duì)象
Statement statement = connection.createStatement();
// 2.4 執(zhí)行sql并返回結(jié)果
ResultSet resultSet = statement.executeQuery(sql);
// 3.判斷是否登錄成功
if (resultSet.next()) {// 成功
String loginUsername = resultSet.getString("username");
request.getSession().setAttribute("loginUsername", loginUsername);
response.sendRedirect(request.getContextPath() + "/list.jsp");
} else {// 失敗
request.setAttribute("error", "用戶名或密碼錯(cuò)誤");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
⑤ list.jsp
⑥ login.jsp
老師晚上總結(jié)
疑惑|拓展
-
mysql練習(xí)錯(cuò)題說明
-
昨晚有同學(xué)反饋《索引與函數(shù)加強(qiáng)題目》第四、第五道題錯(cuò)誤.
說明:
- 第四題: 答案是沒有錯(cuò)的熬粗,只不過我們復(fù)制答案的時(shí)候千萬不要讓字符串換行.
- 第五題: 答案是沒有錯(cuò)的
-- 查詢學(xué)過“李平老師”所教的所有課的同學(xué)的學(xué)號(hào)搀玖、姓名 -- 1. 找到李平老師的tid SELECT tid FROM teacher WHERE tname='李平老師'; -- 2. 到李平老師教的所有課程cid 2 4 SELECT cid FROM course WHERE teacher_id=(SELECT tid FROM teacher WHERE tname='李平老師'); -- 3. 找到李平老師教的所有課程數(shù)量 SELECT COUNT(cid) FROM course WHERE teacher_id=(SELECT tid FROM teacher WHERE tname='李平老師'); -- 4. 找到所有學(xué)習(xí)李平老師課程的學(xué)生student_id SELECT s.`student_id` FROM score s WHERE s.`course_id` IN (SELECT cid FROM course WHERE teacher_id=(SELECT tid FROM teacher WHERE tname='李平老師')); -- 5. 找到所有選擇了李平老師所有課程的學(xué)生student_id SELECT s.`student_id` FROM score s WHERE s.`course_id` IN (SELECT cid FROM course WHERE teacher_id=(SELECT tid FROM teacher WHERE tname='李平老師')) GROUP BY s.`student_id` HAVING COUNT(s.`student_id`) =(SELECT COUNT(cid) FROM course WHERE teacher_id=(SELECT tid FROM teacher WHERE tname='李平老師')); -- 6. 找到學(xué)生的信息(學(xué)號(hào)和姓名) SELECT s.`sid`,s.`sname` FROM student s WHERE s.`sid` IN (SELECT s.`student_id` FROM score s WHERE s.`course_id` IN (SELECT cid FROM course WHERE teacher_id=(SELECT tid FROM teacher WHERE tname='李平老師')) GROUP BY s.`student_id` HAVING COUNT(s.`student_id`) =(SELECT COUNT(cid) FROM course WHERE teacher_id=(SELECT tid FROM teacher WHERE tname='李平老師')));
-
-
jdbc的操作步驟
package com.itheima.test; import org.junit.Test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; public class Demo1 { @Test public void test01() throws Exception { //1. 加載驅(qū)動(dòng) Class.forName("com.mysql.jdbc.Driver"); //2. 獲取連接 Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day21", "root", "abc123"); //3. 創(chuàng)建sql的運(yùn)輸器 Statement st = connection.createStatement(); //4. 準(zhǔn)備sql語句 , 執(zhí)行sql String sql ="insert into account(name,balance) values ('狗娃',1000)"; int row = st.executeUpdate(sql); System.out.println("受影響的行數(shù):"+row); //5. 關(guān)閉資源 st.close(); connection.close(); } }
-
注冊(cè)驅(qū)動(dòng)的代碼感覺沒用, 該語句雖然可以不寫驻呐,但是建議同學(xué)還是寫灌诅,符合市場(chǎng)的習(xí)慣
@Test public void test01() throws Exception { //1. 加載驅(qū)動(dòng), 感覺該語句沒啥用芳来,為什么會(huì)有這種感覺呢,因?yàn)樵撜Z句和代碼下面的所有語句都沒有任何關(guān)聯(lián)猜拾。 //答案: 其實(shí)是有關(guān)聯(lián)的即舌, 因?yàn)槟慵虞dDriver類的時(shí)候會(huì)執(zhí)行靜態(tài)代碼塊,靜態(tài)代碼塊的代碼中出現(xiàn)了DriverManager //以前DriverManager比較笨挎袜,它不知道從哪里去尋找驅(qū)動(dòng)類顽聂,所以需要你注冊(cè)。 //從mysql5.0開始DriverManager就變得聰明了盯仪,該語句可以省略紊搪。 // Class.forName("com.mysql.jdbc.Driver"); //2. 獲取連接 Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day21", "root", "abc123"); //3. 創(chuàng)建sql的運(yùn)輸器 Statement st = connection.createStatement(); //4. 準(zhǔn)備sql語句 , 執(zhí)行sql String sql ="insert into account(name,balance) values ('狗剩',1000)"; int row = st.executeUpdate(sql); System.out.println("受影響的行數(shù):"+row); //5. 關(guān)閉資源 st.close(); connection.close(); }
-
為什么需要關(guān)閉連接, 關(guān)閉的作用是干嘛呢?
以前你們學(xué)過io流全景,那么請(qǐng)問io流關(guān)閉資源的目的是什么耀石? io關(guān)閉資源的目的就是釋放文件資源,因?yàn)槲募Y源是有限的爸黄。 * 凡是有限的資源我們用完之后都應(yīng)該馬上是否娶牌。 jdbc的close方法的作用就是釋放連接Connection對(duì)象。 因?yàn)閏onnection代表 java程序與mysql數(shù)據(jù)庫連接馆纳,這種連接數(shù)是有限的诗良,默認(rèn)情況mysql最高的并發(fā)connection數(shù)量是100, 所以用完畢之后一定要釋放資源鲁驶。
-
增刪改使用的方法鉴裹,查詢使用的方法?
增刪改: executeupdate()
查詢: executequery()
-
Statement的execute方法的誤區(qū)
//execute方法一般我們用于創(chuàng)建表 @Test public void test03() throws Exception { //2. 獲取連接 Connection connection = DriverManager.getConnection("jdbc:mysql:///day21", "root", "abc123"); //3. 創(chuàng)建sql的運(yùn)輸器 Statement st = connection.createStatement(); //4. 準(zhǔn)備sql語句 , 執(zhí)行sql String sql ="insert into account(name,balance) values ('鐵蛋',1000)"; sql ="select * from account"; //execute方法的返回值:如果你執(zhí)行的sql是查詢語句返回true钥弯,其他語句一律是false径荔,所以該返回值沒有任何的意義 boolean flag = st.execute(sql); // execute() 方法的返回值是boolean。 System.out.println("執(zhí)行的結(jié)果:"+ flag); //5. 關(guān)閉資源 st.close(); connection.close(); }
-
ResultSet結(jié)果集的使用, 結(jié)果集常見的錯(cuò)誤
@Test public void test04() throws Exception { //2. 獲取連接 Connection connection = DriverManager.getConnection("jdbc:mysql:///day21", "root", "abc123"); //3. 創(chuàng)建sql的運(yùn)輸器 Statement st = connection.createStatement(); //4. 準(zhǔn)備sql語句 , 執(zhí)行sql String sql = "select name,balance from account"; // resultSet是一個(gè)結(jié)果集,這個(gè)結(jié)果集會(huì)把本次sql查詢的數(shù)據(jù)全部加載到ResultSet中脆霎。 ResultSet rs = st.executeQuery(sql); //next() 游標(biāo)向下移動(dòng)一個(gè)單位总处,并且返回是否還有數(shù)據(jù),如果游標(biāo)沒法向下移動(dòng)代表已經(jīng)是數(shù)據(jù)末尾。 while(rs.next()) { System.out.println("姓名:" + rs.getString("name") + " 余額:" + rs.getDouble("balance")); } //5. 關(guān)閉資源 st.close(); connection.close(); }
-
工具類的Connection什么時(shí)候?yàn)閚ull睛蛛,不明白為什么需要非空判斷.
@Test public void test05() throws Exception { Connection connection = null; Statement st = null; ResultSet rs =null; try { //2. 獲取連接 connection = JdbcUitls.getConnection(); // 執(zhí)行該語句的時(shí)候就會(huì)出現(xiàn)異常, //3. 創(chuàng)建sql的運(yùn)輸器 st = connection.createStatement(); //4. 準(zhǔn)備sql語句 , 執(zhí)行sql String sql = "select name,balance from account"; // resultSet是一個(gè)結(jié)果集,這個(gè)結(jié)果集會(huì)把本次sql查詢的數(shù)據(jù)全部加載到ResultSet中鹦马。 rs = st.executeQuery(sql); //next() 游標(biāo)向下移動(dòng)一個(gè)單位,并且返回是否還有數(shù)據(jù),如果游標(biāo)沒法向下移動(dòng)代表已經(jīng)是數(shù)據(jù)末尾忆肾。 if(rs.next()) { System.out.println("姓名:" + rs.getString("name") + " 余額:" + rs.getDouble("balance")); } } catch (Exception e){ e.printStackTrace(); }finally { //出現(xiàn)異常的時(shí)候資源還是還關(guān)閉荸频,沒因?yàn)樵趂inally塊中 JdbcUitls.close(rs,st,connection); }
重點(diǎn)
- jdbc實(shí)現(xiàn)對(duì)數(shù)據(jù)的CURD
- 完成jdbc工具類的抽取
- 事務(wù)的操作
- 完成登陸案例,最好使用三層架構(gòu)的方式實(shí)現(xiàn)
學(xué)習(xí)反饋
反饋 | 答案 |
---|---|
關(guān)于resultset希望老師可以再講講客冈。 | 剛剛老師已經(jīng)和大家講解了 |
快開學(xué)吧 | 好的 |
答疑區(qū)
疑問 | 答案 |
---|---|
這個(gè)SQL執(zhí)行對(duì)象是怎么實(shí)現(xiàn)的旭从?通過協(xié)議傳輸數(shù)據(jù)包嗎? | 數(shù)據(jù)庫其實(shí)也是一個(gè)服務(wù)器,跟我們學(xué)習(xí)的tomcat一樣,可以接受客戶端的連接,通過這個(gè)連接執(zhí)行sql語句.底層使用網(wǎng)絡(luò)編程來傳輸數(shù)據(jù). |
jdbc是不是用到了模板設(shè)計(jì)模式? | 是的 |
建立連接的那個(gè)地址是怎么來的呢? | url的是固定中和悦,其中有些參數(shù)是可以改變的退疫,例如ip地址,端口號(hào)鸽素,項(xiàng)目名稱蹄咖,后面會(huì)詳細(xì)講解. |
3306是固定的嗎? | mysql默認(rèn)端口是3306,可以在my.ini配置文件中修改 |
java代碼能直接創(chuàng)建庫,創(chuàng)建表嗎 | 可以付鹿,但是我們一般只是用jdbc來操作數(shù)據(jù)庫的數(shù)據(jù)澜汤,增刪改查。 |
這個(gè)idea到數(shù)據(jù)庫是不是c/s結(jié)構(gòu)舵匾,底層連接用的tcp協(xié)議俊抵,通過3次握手建立連接,4次揮手?jǐn)嚅_連接坐梯,并且中間傳輸內(nèi)容沒有限制徽诲。(他的3次握手建立連接是封裝到底層了嗎?4次揮手代表的是釋放資源嗎吵血?) | 不是 他用的是jdbc協(xié)議的封裝谎替,這個(gè)暫時(shí)不要研究,先把課上的重點(diǎn)弄明白了蹋辅,這個(gè)可以作為擴(kuò)展自己去搜一下 |
注冊(cè)驅(qū)動(dòng)是不是也可以用class.forName(); 這兩個(gè)有什么區(qū)別 | 是的钱贯,兩種都可以注冊(cè),但是Class.forname這種我們可以把驅(qū)動(dòng)類的類名編寫在配置文件中侦另,不需要寫死秩命,更加靈活 |
注冊(cè)驅(qū)動(dòng)那里為什么不用反射直接注冊(cè)?如果用DriverManager.registerDriver注冊(cè)的話,里面的靜態(tài)代碼塊不也執(zhí)行了嗎,這不相當(dāng)于注冊(cè)了兩次? | 是的,等會(huì)說講倒 |
請(qǐng)問老師們褒傅,有些項(xiàng)目里弃锐,sql語句中數(shù)據(jù)位置用的是?殿托,這個(gè)霹菊?是占位符嘛?怎么理解呢 | 明天會(huì)講到 |
Driver.Class為什么有耦合呢支竹? | 需要直接使用 驅(qū)動(dòng)包里面的 類 Driver旋廷。 而不是jdbc‘接口⊥倨荩’ |
.class有耦合柳洋,那getClass可以用嗎 | 目前咱們的代碼都有耦合, 待會(huì)會(huì)講到如何解耦 |
為什么要 注冊(cè)驅(qū)動(dòng)呢, 以前不都是導(dǎo)入jar包, 然后就可以直接使用jar包中定義的靜態(tài)方法或者可以使用定義好的獲取抽象方法的實(shí)現(xiàn)類,在通過實(shí)現(xiàn)類對(duì)象調(diào)用方法就行了. 不太理解為什么要注冊(cè)驅(qū)動(dòng)呢 | 這就涉及到JDBC的代碼設(shè)計(jì)思想: 面向接口編程 如果你有認(rèn)真觀察, 你就發(fā)現(xiàn)課上的這個(gè)入門案例中, 只有第一個(gè)步驟(注冊(cè)驅(qū)動(dòng))跟mysql的驅(qū)動(dòng)jar包耦合.其它代碼都是面向接口的寫法, 而這些接口是sun公司制定的. 如果沒有注冊(cè)驅(qū)動(dòng)這步, 我們的jdbc根本不知道是使用了哪家數(shù)據(jù)庫軟件的驅(qū)動(dòng)(是mysql還是oracle) 那么注冊(cè)驅(qū)動(dòng)是什么作用呢? 實(shí)際上第二步的Connection連接是由Driver對(duì)象來獲取的(在DriverManager的底層), 第一步注冊(cè)驅(qū)動(dòng)的作用就是設(shè)置 mysql驅(qū)動(dòng)包的Driver實(shí)現(xiàn)類, 在第二步獲取連接時(shí)使用. |
password沒密碼直接="",就可以么 | 可以的待诅,但是建議給數(shù)據(jù)庫設(shè)置下密碼 |
能大致講一講這個(gè)底層jdbc協(xié)議網(wǎng)絡(luò)編程嗎 | |
JDBC 和數(shù)據(jù)庫的連接時(shí)間是多久叹坦,什么時(shí)候或者什么情況下斷開連接?查詢的時(shí)候指針是直接從數(shù)據(jù)庫中獲取到的數(shù)據(jù)嗎卑雁? | 使用完畢我們會(huì)關(guān)閉連接募书,查詢數(shù)據(jù)的時(shí)候绪囱,數(shù)據(jù)會(huì)被封裝到ResultSet結(jié)果中,我們是從ReusltSet結(jié)果集中獲取數(shù)據(jù) |
resultset executeQuery(string sql)這個(gè)方法是不是把返回的表格中的數(shù)據(jù)從字符串形式(返回每一行字符串?dāng)?shù)據(jù)都映射成了java對(duì)象莹捡,再把這些對(duì)象封裝到resultset集對(duì)象里面鬼吵。 | 結(jié)果集里面都是字符串類型.你可以在獲取的時(shí)候調(diào)用rs.getXXX類型進(jìn)行轉(zhuǎn)型. |
ResultSet是個(gè)set集合嗎?如果查詢的結(jié)果集中存在重復(fù)的行的話,會(huì)重復(fù)顯示嗎?假如確實(shí)需要對(duì)這些重復(fù)的數(shù)據(jù)單獨(dú)處理的話,而不是只顯示一個(gè)的話 | ResultSet不是Set集合,該類的內(nèi)部維護(hù)了集合用于存儲(chǔ)查詢到的數(shù)據(jù) |
resultset封裝的數(shù)據(jù)好像是一種特殊形式,有個(gè)方法可以getxxx(int 列號(hào))列號(hào)這個(gè)東西就很秀了篮赢,如果是封裝的字符串類型怎么有列號(hào)這個(gè)東西齿椅,好像就是把整個(gè)表映射到集合里面。但是網(wǎng)絡(luò)傳輸協(xié)議傳輸?shù)闹皇莝tring類型启泣, 結(jié)果有列號(hào)證明分列了涣脚,是這個(gè)內(nèi)部進(jìn)行分列,還是傳過來就分好了寥茫? | 這都是resultset內(nèi)部做的處理.我們只需要知道resultset干了啥.怎么用就好.不需要去研究resultset是怎么實(shí)現(xiàn)的.當(dāng)然猜一下也是可以的.如果我們把精力都放在研究底層.不太適合我們現(xiàn)在這個(gè)階段該干的事. |
resultSet結(jié)果集的數(shù)據(jù) 是不是根據(jù) 查詢條件 select * from 一致遣蚀, 得到所有 就取所有 得到具體的字段 就只能取某個(gè)具體的數(shù)據(jù) | 是的,比如:select name,age from 表名纱耻,那么resultSet結(jié)果集只有name與age兩個(gè)字段的數(shù)據(jù)芭梯。 |
建立連接通道那個(gè)異常不拋,使用jdk7的try()catch 把所有語句都寫到這里 可以嗎 是不是就可以省略釋放資源了 | 是的弄喘,完全可以 |
事務(wù)開啟了玖喘,事務(wù)什么時(shí)候關(guān)閉呢 | 執(zhí)行完畢提交事務(wù),出現(xiàn)異衬⒅荆回滾事務(wù)芒涡,提交或者回滾都是結(jié)束事務(wù) |
可以一條事務(wù) 開一輛車嗎 就是羅志祥一個(gè)createStatement,蝴蝶姐一個(gè)createStatement | 一個(gè)事務(wù)中創(chuàng)建多個(gè)statement是可以的卖漫。 但是多個(gè)用戶是用不了一個(gè)事務(wù)的费尽。 |