接下來幾天的時間我將和大家一起學習java中數據庫的操作。內容有點多,爭取在國慶後全部更新完畢。知識點包括,jdbc基本操作、手動封裝jdbc的操作、在不適用框架下快速操作數據庫、簡單的mysql知識點(常見的sql語句,事務處理等等)、最後學習兩個持久層的框架,hibernate和MyBatis以及目前最爲火的Nosql----redis數據庫,後面兩個框架可以更新會很慢。(因爲我自己還沒有學習)其實寫了這麼多篇博文以後,我發現自己也在慢慢的進步,剛開始學習,倒是希望那些看了我博客的有緣人提出寶貴的意見,對於程序員來說,永遠不會找到自己的bug。總以爲自己的纔是最好的(hhh)
今天我們就簡單的瞭解jdbc的基本操作以及封裝jdbc工具類。
概念:jdbc、java database Connectivity 顧名思義就是java中連接數據庫使用的。
下面通過一個簡單的程序來看看怎麼使用jdbc連接數據庫的
package com.yxc.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
/**
* 測試數據庫能不能連接成功
* 在開發過程中階段性測試是很重要的的,不然寫了很多的代碼以後出錯,
* 根本找不到錯誤的位置
*/
public class ConnectionTest {
public static void main(String[] args) {
//測試數據庫能不能連接成功
//數據庫的基本信息
String url="jdbc:mysql://localhost:3306/jdbc"; //數據庫所在的位置 jdbc是你數據庫的名字
String root="root"; //用戶名
String password="123456"; //數據庫密碼
Connection conn=null; //定義一個數據庫連接對象
//加載驅動
try {
Class.forName("com.mysql.jdbc.Driver");
//獲取一個數據庫連接對象
conn = DriverManager.getConnection(url, root, password);
//測試數據庫能不能連接上
//如果返回一個對象,說明連接成功,我們可以進行下面的操作
//如果出錯,那麼我們要開始檢查錯誤的原因,數數據庫的基本信息出錯,還是驅動加載時報錯
System.out.println(conn);
} catch (Exception e) {
e.printStackTrace();
}finally{
//最後一定記得關閉資源
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
jdbc連接數據庫的基本步驟:
1、導入數據庫連接jar包
2、開始上面的測試代碼,測試是否可以連接到數據庫。(這裏說明一下,一定要在數據中新建數據庫,我上面數據庫名字爲jdbc)
3、如果連接成功,纔開始進行下面的操作
4、在數據庫中創建表
5、在java中設計與表對應的實體類,最好字段的名字都一樣
6、開始寫代碼
現在對於jdbc應該有初步的瞭解了吧!
數據庫最常見的就是增刪查改操作了,那麼接下來我們寫一個簡單的增刪查改功能。
package com.yxc.domain;
public class Student {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.yxc.jdbc;
import com.yxc.domain.Student;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* 下面我們通過一個案例來實現數據庫的基本操作增刪查改
* 使用數據庫名:jdbc 表名 stu 表中三個字段 id,name,age;
* 我們使用靜態方法,在主方法中測試。
*/
public class CRUD_Demo {
//因爲數據庫的一些基本信息是一樣的,所以我們定義成成員變量,讓整個類中都可以使用
//這樣減少了代碼量,到後面我們會把這些信息放在配置文件中,這樣對於開發更加高效、方便。
//數據庫的基本信息
public static String url="jdbc:mysql://localhost:3306/jdbc"; //數據庫所在的位置
public static String user="root"; //用戶名
public static String password="Y13627037792"; //數據庫密碼
public static String DriverName="com.mysql.jdbc.Driver"; //驅動名字
public static void main(String[] args) {
// //測試添加學生方法
//// Student stu=new Student();
//// stu.setId(2);
//// stu.setAge(22);
//// stu.setName("yangixn");
//// addStu(stu);
//測試刪除學生
//System.out.println(deleteStu(2));
//測試更新數據
//System.out.println(updateStu());
//測試查詢學生
//Student stu = findStu(1);
//System.out.println(stu);
//測試查詢所有學生
List<Student> allStudent = findAllStudent();
System.out.println(allStudent);
}
/**添加一個學生
*如果添加成功返回1,失敗返回0
* */
public static int addStu(Student stu1){
int result=0;
Connection conn =null;
Statement statement =null;
try {
Class.forName(DriverName);
DriverManager.getConnection(url, user, password);
String sql="insert into stu value("+stu1.getId()+",'"+stu1.getName()+"',"+stu1.getAge()+")";
statement = conn.createStatement();
result = statement.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
conn.close();
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return result;
}
/**根據id一位學生
* 刪除成功返回1 失敗返回0
* */
public static int deleteStu(int id){
int result=0;
Connection conn =null;
Statement statement =null;
try {
Class.forName(DriverName);
conn = DriverManager.getConnection(url, user, password);
String sql="delete from stu where id="+id+"";
statement = conn.createStatement();
result = statement.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
conn.close();
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return result;
}
/**更新數據
* 更新成功以後返回1,失敗返回0
* */
public static int updateStu(){
int result=0;
Connection conn =null;
Statement statement =null;
try {
Class.forName(DriverName);
conn = DriverManager.getConnection(url, user, password);
String sql="update stu set name='June' where id=1";
statement = conn.createStatement();
result = statement.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
}
finally{
try {
conn.close();
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return result;
}
/**查找學生 查到以後返回學生對象*/
public static Student findStu(int id){
Student stu=null;
Connection conn =null;
Statement statement =null;
ResultSet resultSet =null; //這是一個結果集對象,封裝了查詢出來的所有結果
try {
Class.forName(DriverName);
conn = DriverManager.getConnection(url, user, password);
String sql="select * from stu where id="+id+"";
statement = conn.createStatement();
resultSet = statement.executeQuery(sql);
while(resultSet.next()){
//如果有數據,就創建一個對象保存起來
stu=new Student();
stu.setId(resultSet.getInt("id"));
stu.setName(resultSet.getString("name"));
stu.setAge(resultSet.getInt("age"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
conn.close();
statement.close();
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return stu;
}
/**測試查詢所有學生的信息
* 返回一個學生集合
*/
public static List<Student> findAllStudent(){
List<Student> list=new ArrayList<>();
Connection conn =null;
Statement statement =null;
ResultSet resultSet =null;
try {
Class.forName(DriverName);
conn = DriverManager.getConnection(url, user, password);
String sql="select * from stu ";
statement = conn.createStatement();
resultSet = statement.executeQuery(sql);
while(resultSet.next()){
//如果有數據,就創建一個對象保存起來
Student stu=new Student();
stu.setId(resultSet.getInt("id"));
stu.setName(resultSet.getString("name"));
stu.setAge(resultSet.getInt("age"));
//每一次獲取的學生對象,保存在集合中
list.add(stu);
}
}catch (Exception e){
e.printStackTrace();
}finally{
try {
conn.close();
statement.close();
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//返回集合
return list;
}
}
這裏我將⑤種方法都放在一個類中了,可能一時代碼有點多,但是我們一個一個方法的看就會好很多。數據庫中表的信息很簡單,表名爲stu,只有三個字段,int id, String name, int age; 所以對應的實體類就是Student。然後就是測試類。這裏注意的就是測試的時候最好是一個個測試,不要一次性全部測試,因爲有些數據如果已經新增了,再一次新增是會報錯的,因爲在數據中設計了id爲主鍵的話,那麼就不允許重複,稍加註意就好。
上面代碼的不足之處:
1、在sql中有很多的字符串的拼接,很麻煩
2、很多相同的代碼,能不能重構一波
3、數據庫相關的信息我希望可以放在一個配置文件中,這樣我的項目發給別人的時候,它改動配置文件就可以了,而不要動我的源碼
4、對於查詢數據的時候,對於結果集的處理很麻煩
下面的代碼解決前三個不足,關於第四個不足的話,還需要在後面介紹。
db.properties(文件的後綴一定要是這個)
url=jdbc:mysql://localhost:3306/jdbc
user=root
password=123456
DriverName=com.mysql.jdbc.Driver
工具類裏面一般提供靜態方法,其它類可以直接調用
package com.yxc.utils;
import java.io.FileInputStream;
import java.sql.*;
import java.util.Properties;
/**
* 一個工具類,獲取連接對象以及資源的釋放操作
* 這個類裏面主要有兩個靜態方法,一個獲取數據庫連接對象,一個是關閉各種資源的方法
*/
public class JDBCUtils {
/**定義一個靜態方法獲取連接對象*/
public static Connection getConn() {
Connection conn=null;
FileInputStream in = null;
try {
//將配置文件中的信息讀取進來
in = new FileInputStream("src/db.properties");
//創建一個配置文件的對象
Properties p = new Properties();
//將配置文件中的內容加載進來
p.load(in);
//獲取配置文件的信息
Class.forName(p.getProperty("DriverName"));
//連接對象,將從配置文件中獲取的數據庫信息傳進去
conn=DriverManager.getConnection(p.getProperty("url"),p.getProperty("user"),p.getProperty("password"));
} catch (Exception e) {
e.printStackTrace();
}
//最終返回一個數據庫連接對象,外界的類通過這個方法就可以直接獲取一個數據庫連接對象
return conn;
}
/**關閉資源的方法 傳進三個常見的資源*/
public static void close(Connection conn, Statement st, ResultSet rs){
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
這個是增刪查改的類,可以對應最開始的類,顯然代碼乾淨了很多
package com.yxc.jdbc;
import com.yxc.domain.Student;
import com.yxc.utils.JDBCUtils;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* 下面我們通過一個案例來實現數據庫的基本操作增刪查改
* 使用數據庫名:jdbc 表名 stu 表中三個字段 id,name,age;
* 我們使用靜態方法,在主方法中測試。
*/
public class CRUD_Demo {
public static void main(String[] args) {
//測試添加學生方法
//Student stu=new Student();
//stu.setId(3);
//stu.setAge(22);
//stu.setName("yangixn");
//System.out.println(addStu(stu));
//測試刪除學生
//System.out.println(deleteStu(2));
//測試更新數據
//System.out.println(updateStu(3));
//測試查詢學生
Student stu = findStu(1);
System.out.println(stu);
//測試查詢所有學生
//List<Student> allStudent = findAllStudent();
//System.out.println(allStudent);
}
/**添加一個學生
*如果添加成功返回1,失敗返回0
* */
public static int addStu(Student stu1){
int result=0;
Connection conn =null;
PreparedStatement ps =null;
try {
//直接通過工具類獲取連接對象
conn=JDBCUtils.getConn();
//爲了不搞複雜拼接,我們先使用佔位符?
String sql="insert into stu value(?,?,?)";
//對於prepareStatement這個方法來說支持預編譯,先執行sql語句
ps = conn.prepareStatement(sql);
//設置參數的值,參數從下標1開始
ps.setInt(1,stu1.getId());
ps.setString(2,stu1.getName());
ps.setInt(3,stu1.getAge());
result = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.close(conn,ps,null);
}
return result;
}
/**根據id一位學生
* 刪除成功返回1 失敗返回0
* */
public static int deleteStu(int id){
int result=0;
Connection conn =null;
PreparedStatement ps =null;
try {
conn=JDBCUtils.getConn();
String sql="delete from stu where id=?";
ps=conn.prepareStatement(sql);
ps.setInt(1,id);
//注意下面這句話就不要將sql傳進去了,不然是會報錯的
result = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
JDBCUtils.close(conn,ps,null);
}
return result;
}
/**更新數據
* 更新成功以後返回1,失敗返回0
* */
public static int updateStu(int id){
int result=0;
Connection conn = null;
PreparedStatement ps = null;
try {
conn=JDBCUtils.getConn();
String sql="update stu set name='June' where id=?";
ps = conn.prepareStatement(sql);
ps.setInt(1,id);
result = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtils.close(conn,ps,null);
}
return result;
}
/**查找學生 查到以後返回學生對象*/
public static Student findStu(int id){
Student stu=null;
Connection conn =null;
PreparedStatement ps=null;
ResultSet resultSet =null;
try {
conn=JDBCUtils.getConn();
String sql="select * from stu where id=?";
ps = conn.prepareStatement(sql);
ps.setInt(1,id);
resultSet = ps.executeQuery();
while(resultSet.next()){
//如果有數據,就創建一個對象保存起來
stu=new Student();
stu.setId(resultSet.getInt("id"));
stu.setName(resultSet.getString("name"));
stu.setAge(resultSet.getInt("age"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
JDBCUtils.close(conn,ps,resultSet);
}
return stu;
}
/**測試查詢所有學生的信息
* 返回一個學生集合
*/
public static List<Student> findAllStudent(){
List<Student> list=new ArrayList<>();
Connection conn =null;
Statement statement =null;
ResultSet resultSet =null;
try {
conn=JDBCUtils.getConn();
String sql="select * from stu ";
statement = conn.createStatement();
resultSet = statement.executeQuery(sql);
while(resultSet.next()){
//如果有數據,就創建一個對象保存起來
Student stu=new Student();
stu.setId(resultSet.getInt("id"));
stu.setName(resultSet.getString("name"));
stu.setAge(resultSet.getInt("age"));
//每一次獲取的學生對象,保存在集合中
list.add(stu);
}
}catch (Exception e){
e.printStackTrace();
}finally{
JDBCUtils.close(conn,statement,resultSet);
}
//返回集合
return list;
}
}
當然這些只是簡單的重構,但是開發起來確實提高了很多的效率,對於db.peoperties和工具類,下次使用時就可以直接拷貝過去,如果數據庫改了,那麼在db,properties中修改一下即可,根本不需要修改源代碼。這樣我們就可以專心在數據庫的操作,這些相同代碼部分我們抽取出來就好。
當然這只是我們自己的封裝,其實開發人員早就有了更強大的封裝方法,我們下一篇文件再介紹。