前提下載:mysql-connector-java,工程下建立lib文件夾將壓縮包放入,右鍵壓縮包build path 把jar包導入
這個壓縮包用于java和mysql的連接(mysql的JDBC)
建立簡單JDBC的連接
1.數據庫的driver向java的DriverManager注冊
2.java的DriverManager連接數據庫(上一步的意義就是讓這步知道應該連接哪一個數據庫)
3.這時候數據庫和java連接上了,但是如果想要傳輸數據你必須要還要在連接上獲得傳輸器
String driver="com.mysql.jdbc.Driver";//驅動路徑(Driver類的全類名)
String url="jdbc:mysql://localhost:3306/數據庫名";//數據庫地址
String user="root";//訪問數據庫的用戶名
String password="123456";//用戶密碼
try {
//1、加載驅動
Class.forName(driver); //實例化Driver類
//對于系統說并不確定用的是哪一個數據庫,java提供一個大管家,用于管理當前使用的是哪個數據庫的連接,這個大管家就是DriverManager。想要和某個數據庫相連,就要向這個數據庫注冊一下,告訴它想要和那個數據庫相連。實例化過程自動向DriverManager注冊使用哪個driver,不需要顯示調用DriverManager.registerDriver方法(將數據庫的Driver向java的DriverManager注冊,注冊后java和mysql就處于準備連接階段)
//2、連接數據庫
Connection con = DriverManager.getConnection(url, user, password);
if(!con.isClosed()){//判斷數據庫是否鏈接成功
System.out.println("已成功鏈接數據庫!");
//3、建立傳輸器(Statement對象)
Statement st = con.createStatement();
//4、執行sql語句
String sql="select *from user";//查詢user表的所有信息
ResultSet rs = st.executeQuery(sql);//查詢之后返回結果集
//ResultSet用來存儲從數據庫中查詢的結果
//5、打印出結果
while(rs.next()){
//next()方法,類似一個游標,從0數據開始,每調用一次就指向rs的下一個數據,也就是表里的下一行 System.out.println(rs.getString("Id")+"\t"+rs.getString("name")+"\t"+rs.getString("password"));
//rs.getString("Id")表示將rs里的id字段的數據當做字符串取出,與實際字段數據類型無關
也可以使用rs.getString(1)表示獲取第一個字段值
}
}
rs.close();//關閉資源
con.close();//關閉數據庫
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
executeQuery(sql) 用于執行select語句
executeUpdate(sql)用于執行select以外語句 (返回值>0修改成功 <0插入失敗)
解決中文亂碼問題
若想往數據庫里插入漢字首先保證數據庫和eclipse的編碼一致 然后 在url尾部加上 ?characterEncoding=utf8 并且設置編輯器的編碼為utf-8(有時候需要專門更改某個字段的編碼)
注:實際開發過程應該先檢查能否插入漢字(必須統一開發工具版本!!)
以上是一個初級的JDBC程序,若完善,需要改成以下
2.獲取JDBC的連接和關閉連接的工具類(通過配置文件進行連接)
配置文件存在src目錄下,因為ecplise會把src下目錄的文件當做是當前目錄
public class JDBCTools {
private static String driver;
private static String url;
private static String username;
private static String password;
private static Properties prop=new Properties(); //類似Map集合
static{ //靜態初始化塊
InputStream in=null; //建立一個輸入流
try {
in=JDBCTools.class.getClassLoader().getResourceAsStream("db.properties");
/*getResourceAsStream()是用來獲取文件中資源
JDBCTools.class.getClassLoader()代碼的意思是
先得到JDBCtools的Class對象,然后得到這個類的加載器,
最后用這個加載器去加載需要的資源文件
其實也可以使用FileInputStream讀取文件
*/
prop.load(in); //將輸入流裝在到Properties集合類中
//得到key對應的value
driver=prop.getProperty("jdbc.driver");
url=prop.getProperty("jdbc.url");
username=prop.getProperty("jdbc.username");
password=prop.getProperty("jdbc.password");
Class.forName(driver); //加載驅動
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Connection getConnection(){ //獲取連接的方法
Connection conn=null;
try {
conn=DriverManager.getConnection(url,username,password);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
public static void closeConnection(Connection conn,Statement stmt,ResultSet rs){
try { //關閉連接的方法
if(rs != null)
rs.close();
if(stmt != null)
stmt.close();
if(conn != null)
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3.PreparedStatement(實際開發用的)
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Demo1 {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
String url="jdbc:mysql://localhost:3306/sunhao?characterEncoding=utf8";
//解決中文亂碼的問題
String username="root";
String password="123456";
String driver="com.mysql.jdbc.Driver";
try {
Class.forName(driver);
conn=DriverManager.getConnection(url,username,password);
String sql="select *from emp where empno=?";
ps=conn.prepareStatement(sql); //預編譯
ps.setInt(1,7369); //賦參數,為第一個問號位置賦值7369
rs=ps.executeQuery(); //執行sql
if(rs.next()){
System.out.println(rs.getString("ename"));
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4.利用preparedStatement實現登陸注冊
public class UserDaoImpl {
public User login(User u){ //因為一般登陸有后續操作所以如果數據庫中有這么個人,就返回他
User u1=null;
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
conn=JDBCTools.getConnection();
String sql="select * from t_user where username=? and password=?";
try {
ps=conn.prepareStatement(sql);
ps.setString(1, u.getUsername());
ps.setString(2, u.getPassword());
rs=ps.executeQuery();
if(rs.next()){
u1=new User(rs.getString("username"),rs.getString("password"));
return u1;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return u;
}
public void register(User u) throws SQLException{
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
conn=JDBCTools.getConnection();
String sql="insert into t_user values(?,?)";
ps=conn.prepareStatement(sql);
ps.setString(1, u.getPassword());
ps.setString(2, u.getPassword());
int falg=ps.executeUpdate();
if(falg>0){
System.out.println("插入成功");
}else{
System.out.println("插入失敗");
}
}
}
注意模糊查找的時候不能在預編譯的sql語句里使用%?%而應該是 ? 在參數里為?賦值為模糊查找%張 %
模擬DButils工具包的方法
1.建立可以插入可變參數的數據增刪改方法。update(String sql,Object...obj)
public class UTl {
public void update(String sql,Object...obj) throws SQLException{
Connection conn=null; //可變參數的obj的長度就是sql里占位符個數,用于替換占位符
PreparedStatement ps=null;
conn=JDBCTools.getConnection();
ps=conn.prepareStatement(sql); //sql是具有占位符的語句
for(int i=0;i<obj.length;i++){ //將sql語句里的占位符替換為實參
ps.setObject(i+1, obj[i]);
}
int flag=ps.executeUpdate();
if(flag>0){
System.out.println("插入成功");
}
}
2.建立一個完成查詢的工具方法,
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.sql.ResultSetMetaData;
import com.qianfeng.demo1.JDBCTools;
public class DDD {
/*為什么查詢不用和增刪改類似的方法?
因為增刪改的時候,是往數據庫里操作,
而查是將數據庫里的內容存在對象里,
這時你不知道表和類中到底有哪些屬性,所以需要調用方法獲取數據庫的字段和值
然后將字段值存到對象的對應屬性里
在此過程就需要 有獲得數據庫字段的方法,
而此時返回值應該是存完值后的類對象,但是由于是萬能查找,
你不知道你查找的數據庫應該返回的是什么類,返回值就設置成了泛型
傳遞一個泛型類的反射的原因是,普通類是無法給一個不確定的字段進行賦值的
而類的反射卻可以給不確定的私有屬性進行賦值
(獲取數據庫的字段名,然后調用反射的cls.getDeclaredField(fileName);方法就可以得到類中屬性的名字,再通過field.set(obj, fileValue);就可以把值存給對應屬性了)
*/
/*1.獲取鏈接
2.獲取PreparedStatement
3.獲取結果集
4.獲取結果集元數據(字段)
5.把數據存入map集合
6.遍歷map集合存入對象(其實此時完全可以直接把字段—字段值存入對象,多次一舉,只是為了易于理解)
*/
public <T>T find(Class<T> cls,String sql,Object...obj) throws SQLException, InstantiationException, IllegalAccessException{
/*第一個參數是一個反射對象,泛型表示的是這個泛型對象反射的是哪一個類,反射哪個類返回值就是哪個類*/
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
conn=JDBCTools.getConnection();//1.獲取鏈接
ps=conn.prepareStatement(sql);//2.獲取PreparedStatement
for(int i=0;i<obj.length;i++){
ps.setObject(i+1, obj[i]);
}
rs=ps.executeQuery();//3.獲取結果集
//結果集也是一個表,得到表結構的方法使用getMetaData(),得到表結構你就可以得到表的字段了
ResultSetMetaData rmd=rs.getMetaData();
//得到結果集的結構,rmd對象代表表結構
//String 是字段名 Object是字段值
Map<String,Object>map=new HashMap<>();
if(rs.next()){ //4.獲取表的元數據(字段)
for(int i=0;i<rmd.getColumnCount();i++){ rmd表結構對象調用方法獲取字段個數
//注意數據庫里字段是從1開始
String columnName=rmd.getColumnLabel(i+1);
Object columnValue=rs.getObject(columnName);
map.put(columnName, columnValue);//5.把數據存入map集合
}
}
T t=cls.newInstance(); //建立對象,注意類必須擁有一個無參構造器
Iterator it=map.entrySet().iterator();
while(it.hasNext()){ //遍歷map集合
Entry <String,Object>entry=(Entry<String,Object>)it.next();
String fileName=entry.getKey();
Object fileValue=entry.getValue();
set(t,fileName,fileValue);//6.遍歷map集合存入對象
}
System.out.println(map);
return t;
}
private void set(Object obj,String fileName, Object fileValue) {
// TODO Auto-generated method stub
try {
Class cls=obj.getClass();
/*此時使用反射的意義在于,直接知道obj的直接類,而且用反射可以給私有指定字段進行賦值*/
Field field=cls.getDeclaredField(fileName);
field.setAccessible(true);//設置為true后可以直接給私有屬性賦值而不調用方法
field.set(obj, fileValue);
} catch (NoSuchFieldException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/*注意1.當數據庫字段和類屬性類型不同,統一屬性
* 2.基本類型存在null時不可賦值,將類中屬性改為包裝類
* */
7.jdbc進行批處理:批量增刪改
public class TestBatch {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement ps=null;
try {
conn=JDBCTools.getConnection();
String sql="insert into a values(?)";
ps=conn.prepareStatement(sql);
for(int i=0;i<102;i++){
ps.setInt(1, i);
ps.addBatch(); //添加到緩沖區
if(i%10==0){
ps.executeBatch(); //將添加到緩沖區的數據批量更新到數據庫
ps.clearBatch(); //將緩沖區中更新完的數據清空
}
}
ps.executeBatch(); //將沒更新的緩沖區更新
ps.clearBatch();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
8.DBCP連接池
commons-dbcpxxx.jar
commons-poolxxx.jar
public class TestDBCPpool {
//第一種鏈連接方式(無配置文件)
@Test
public void test1(){
BasicDataSource dataSource = new BasicDataSource();
//必要屬性
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/sunhao");
dataSource.setUsername("root");
dataSource.setPassword("123456");
//常用屬性
dataSource.setMinIdle(5); //最小空閑連接
dataSource.setMaxIdle(50); //最大空閑連接
dataSource.setInitialSize(10); //初始化連接
dataSource.setMaxActive(200); //最大連接數
dataSource.setMaxWait(5000); //最大等待時間
//獲取鏈接
Connection conn=null;
try {
conn=dataSource.getConnection();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//第二種連接方式(有配置文件)
@Test
public void test2() throws Exception{
Properties prop=new Properties();
prop.load(new FileInputStream("db.properties"));
//配置文件必須符合特定的規則才能正確讀取
DataSource dataSource = BasicDataSourceFactory.createDataSource(prop);
Connection conn=null;
conn=dataSource.getConnection();
//這時候常用屬性可以設置到配置文件中,當連接后就自動獲取了常用屬性
}
}
9.c3p0連接池(常用此連接池)
//1.構造函數不寫name值就要,想dbcp一樣
public class C3P0Utils {
//1、提供私有化的數據源 使用默認設置 (也可以先定義用靜態代碼塊加載配置文件)
private static ComboPooledDataSource datasource=new ComboPooledDataSource();
//使用命名配置 (如果配置文件中有多條配置信息,就要使用下面這種方法,確定創建的是哪個數據源)
//private static ComboPooledDataSource datasource =new ComboPooledDataSource("itheima");
//2.提供對外的數據源
public static DataSource getDataSource(){
return datasource;
}
//3.提供對外的鏈接
public static Connection getConnection() throws SQLException{
return datasource.getConnection();
}
}
public static void closeConnection(Connection conn,Statement stmt,ResultSet rs){
try {
if(rs != null)
rs.close();
if(stmt != null)
stmt.close();
if(conn != null)
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}