JDBC——java datebase connectivity 数据库连接
execute相关资料:
execute():各种SQL语句都能发送,当数据库返回的是一个结果集的话,方法就会返回一个true,如果数据库返回的是受影响的行数或者没有返回东西,都会返回一个false
executeQuery():只能发送DQL语句,方法会返回查询出来的结果,并生产一个ResultSet对象,也就是一个结果集,如果没有就返回一个null值,所以,可以通过遍历Set的方法来取得ResultSet对象里面的相关内容
executeUpdate():只能发送DML/DDL语句,这两种语句数据库都不会返回内容,方法返回的是一个int类型的数据,代表数据库受影响的行数,0就代表没有改变行数
基本操作:
1、加载驱动:
1.1导包:在工程下面创建一个包专门存放导入的压缩包,通常名称叫lib-library,将支持连接MySQL的包放进去,然后右键点击Build Path创建路径,看到有牛奶瓶即可
1.2程序中加载:Class.forName("com.mysql.jdbc.Driver");运行这段程序,如果没有报错即代表加载驱动成功
2、获取数据库连接:
Connection con = DriverManager.getconnection("","","");
第一个冒号里面是jdbc:mysql://IP地址:端口号/数据库名称
第二个冒号是数据库的用户名
第三个冒号是数据库的密码
3、创建SQL语句:String sql = "";冒号里面写符合数据库语法的的语句
4、发送并获取结果集:
4.1发送:
statement state = con.createStatement();
ResultSet rs = state.execute(sql);
while(rs.next()){
String bookname = rs.getString("bookname")
}
但是这种通常容易受到注入式攻击,就是利用MySQL数据库的漏洞,当需要通过验证用户名和密码的时候,写入'or'1'='的时候,就不需要密码也能进入到数据库当中。所以现在已经很少用
预编译:
PreparedStatement ps = con.prepareStatement(sql);
使用预编译的好处是可以防止注入式攻击,但是sql语句需要特殊编写,例如:
sql="select*from users where name=?"
?是站位符,然后通过预编译的特殊方法,先预编译一遍后在发送SQL语句给数据库
ps.setString(1,e);
1的意思是代表第一个占位符
最后发送:
ps.execute();
4.2接收:
只有查询的SQL语句才有接受的内容,所以:
executeQuery(SQL)会返回一个ResultSet的对象
while(rs.next()){
//通过指针来获取集合Set里面的内容
rs.get各种数据类型()
//括号里面可以是int或者String
//如果是int,就代表数据库里面的第几列
//如果是String,就是代表数据库里面的那个字段名称,通常都是用String类型
}
5、关闭连接:
可以按后开先关的原则逐个关闭:
rs.close()
state.close()
con.close()
也可以一次过关闭:
con.close(),只需要关先开的那个即可。
浅度封装:
1、变量的定义:因为工具类里面的方法都未静态方法,当方法调用变量时,变量也应该为静态变量才行,而且JDBC的连接所使用的变量通常涉及到数据库的密码,路径等,所以需要设置私有属性,不能被别人随意调用改变或看到,因此:
private static String clasName="";里面是驱动的路径:com.mysql.jdbc.Driver,其他数据对应不同的驱动
private static String url = "";里面是IP地址,域名与数据库的名称
private static String user = "";里面是数据库的用户名
private static String password= "";里面是数据库的密码
2、加载驱动:加载驱动,应该在静态代码块里面,因为静态代码块最先运行,并且存在于整个包中,所以:
static{
try{
Class.forName(clsName);
}catch(Exception e){
sysout("驱动加载失败!");
}
}
3、获取连接:获取连接,需要将取得的连接返回
public static Connection getConnection(){
Connection connection = null;
try{
connection = DriverManager.getConnection(url,user,password);
}catch(Exception e){
sysout("获取连接失败");
}
return connection;
}
注意:
1.因为连接的对象要先定义在try外面,如果定义在try里面,就会成为try方法里面的成员变量,而导致不能返回连接
2.普通的方法当需要报异常的时候都是抛出,谁调用该方法谁就处理,但是因为是工具类里面的方法,通常都是直接处理,而不会抛出,所以这里直接trycatch了
调用connection对象去发送sql语句并获取结果集。
4、关闭连接:因为在获取连接的时候,有可能连接失败了,返回的是一个空值,所有防止报空指向异常,需要判断得到的连接是都为空,不为空再关闭连接
public static void closeConnetion(Connection connection){
try{
if(connection != null){
connection.close();
}catch(Exceptino e){
sysout("关闭连接失败");
}
}
}
深度封装+单一连接对象:
1、创建配置文件:在所在的工具包创建properties配置文件,将加载驱动的路径,连接数据库的路径,数据库用户名和密码,连接池初始化的常量都写在里面,顺便建立并build相关的jar包,如图:
2、加载驱动:加载驱动一开始就要运行,所以写在静态代码块中,还需要将流的声明写在try外面,在finally里面关闭流,其实在jdbc4.0之后的版本其实都可以不用加载,在获取连接的时候,就自动加载了
2.1属性声明:
private static String clsName = null;
private static String url = null;
private static String user = null;
private static String password = null;
2.2获取配置文件的路径:
String path=本类名.class.getResource("").getPath()+"配置文件名";//配置文件名就是上面的db.properties,这里是通过反射找到文件的路径,db.properties需要放在于这个类相同的目录下
2.3URL解码与流:
path=URLDecoder.decode(path,"utf-8");
//使用Properties和文件流将配置读取出来
Properties prop=new Properties();
fis=new FileInputStream(new File(path));
prop.load(fis);
因为要finally关流,所以fis的声明要放在try外面
2.4获取各项参数:
//调用Properties的方法
clsName=prop.getProperty("claName");
url=prop.getProperty("url");
user=prop.getProperty("user");
password=prop.getProperty("password");
2.5加载驱动:
Class.forName(clsName);
3、获取连接
public static Connection getCon() { Connection con = null; try { con = DriverManager.getConnection(url, user, password); } catch (SQLException e) { System.err.println("获取连接失败!"); e.printStackTrace(); } return con; }
4、关闭连接:
public static void close(Connection con) { try { if(con!=null) { con.close(); } } catch (SQLException e) { System.err.println("关闭连接失败!"); e.printStackTrace(); } }
深度封装+c3p0连接池:
连接池:一次过生成多个连接对象放在连接池里面,节省加载资源常用C3p0,还有Druid
1、创建配置文件:在所在的工具包创建properties配置文件,将加载驱动的路径,连接数据库的路径,数据库用户名和密码,连接池初始化的常量都写在里面,顺便建立并build jar包
2、加载驱动:在静态代码块里面加载驱动
2.1通过反射找路径:
通过反射找到配置文件
反射:类名.class.getResource("").getPath+"配置文件名称"例如:
String path =JDBCutil.class.getResource("").getPath() + "db.properties";
2.2通过流读取内容
通过输入流将配置文件的内容读取出来
1.fis = new FileInputStream(new File(path));
2.通过Properties这个类将流里面的内容读出来
Properties prop = new Properties();
prop.load(fis);
2.3设置连接池配置:
先实例化一个连接池的对象,声明在外头,因为获取连接时还需要该对象,例如c3p0
ds = new ComboPooledDataSource();
1.配置基本信息
ds.setDriverClass(prop.getProperty("clsName"))
ds.setJdbcUrl(prop.getProperty("url"))
ds.setUser(prop.getProperty("user"))
ds.setPassword(prop.getProperty("password"));
2.//配置常量
//初始化连接数
ds.setInitialPoolSize(Integer.parseInt(prop.getProperty("initialPoolSize")));
//最少连接数
ds.setMinPoolSize(Integer.parseInt(prop.getProperty("minPoolSize")));
//最大连接数
ds.setMaxPoolSize(Integer.parseInt(prop.getProperty("maxPoolSize")));
//最大空闲时间
ds.setMaxIdleTime(Integer.parseInt(prop.getProperty("maxIdleTime")));
//新建连接数
ds.setAcquireIncrement(Integer.parseInt(prop.getProperty("acquireIncrement")));
3、获取连接:
public static Connection getConnection() { Connection connection = null; try { connection = ds.getConnection(); } catch (SQLException e) { // TODO Auto-generated catch block System.out.println("获取连接失败!"); e.printStackTrace(); } return connection; }
4、关闭连接:
public static void closeConnection(Connection connection) { try { if (connection != null) connection.close(); } catch (SQLException e) { // TODO Auto-generated catch block System.out.println("关闭连接失败!"); e.printStackTrace(); } }