java-jdbc

##JDBC Java DataBase Connectivity: Java数据库连接

一套连接数据库的API(Application Program Interface 应用程序编程接口)

*为什么使用JDBC:

因为java编程语言有可能需要连接多种数据库, ​ 如果没有JDBC,java程序员连接每一种数据库都需要学习一条对应方法调用, ​ 为了避免java程序员学习多套操作数据的方法,sun公司提供jdbc接口, ​ 让各个数据厂商根据此接口写实现类(驱动), ​ 这样的话java程序员只需要掌握jdbc接口中的方法的调用, ​ 就可以访问任何数据,而且换数据时代码不需要做任何的改动

*JDBC连接Mysql数据库:

在maven里下载第三方的jar包--mysqlconnector--下载jar包(连接数据库)

将jar包放到项目里

把jar包集成到项目中(正常jdk里面没有这些类 是第三方提供的)

*连接数据库:

1.加载驱动 ​ 2.获取连接 ​ 3.获取操作数据库对象 ​ 4.操作数据库

代码:

//加载数据库 ​ Connection conn = null; ​ try { ​ //1.加载驱动 在com.mysql.jdbc这个包下面有一个Driver类 ​ Class.forName("com.mysql.jdbc.Driver");

Jdbc程序中的Connection,它用于代表数据库的链接,
Collection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,
​
这个对象的常用方法:
​
•           方法                                      描述
createStatement()                   创建向数据库发送sql的statement对象。
prepareStatement(sql)           创建向数据库发送预编译sql的PrepareSatement对象。
prepareCall(sql)                        创建执行存储过程的callableStatement对象。
setAutoCommit(boolean autoCommit)   设置事务是否自动提交。
commit()                                    在链接上提交事务。
rollback()                                  在此链接上回滚事务。

//2.获取链接

    conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");
      url:连接哪个数据库(数据库在哪) jdbc:mysql:  连接数据库的协议
•     dbc:mysql://localhost:3306/test  连接本机的数据库 3306:默认端口号
​
========
常用数据库URL地址的写法:
​
Oracle:jdbc:oracle:thin:@localhost:1521:shen
​
SqlServer:jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=shen
​
MySql:jdbc:mysql://localhost:3306/shen
​
========
​
•     user:数据库用户名  password:数据库密码

//3.获取操作数据库的对象

Statement s = conn.createStatement(); ​ String SQL = "create table t_jdbctest(id int(11),name varchar(12))"; ​ s.execute(SQL);//返回值为布尔类型, true表示有结果返回 false表示没有返回 它可以执行所有的sql语句

 Jdbc程序中的Statement对象用于向数据库发送SQL语句,创建方法为:
​
•             Statement st = conn.createStatement();
​
 Statement对象常用方法:
​
•          方法                                       含义
executeQuery(String sql)                    用于向数据发送查询语句。 返回值类型ResultSet,里面装着查询到的所有数据 
•                                           可以通过以下两种方法查询:
•                                           通获取数据库查询出来的字段的值(通过列名):
                                            int deptno=   rs.getInt("deptno");
•                                           通过第几列获取数据库查询出来的值   :  
                                            int deptno=   rs.getInt(1);
​
executeUpdate(String sql)                   用于向数据库发送insert、update或delete语句  
                                            返回值为int类型,代表生效的行数
execute(String sql)                         用于向数据库发送任意sql语句  返回值是布尔值类型,代表是否有结果集  
                                            true表示有结果返回 false表示没有返回  它可以执行所有的sql语句
addBatch(String sql)                        把多条sql语句放到一个批处理中。
executeBatch()                              向数据库发送一批sql语句执行。
​
​
execute(sql)  当执行数据库相关和表相关的SQL语句时使用该方法,
​
executeUpdate(sql) 执行增删改相关SQL使用此方法,
​
executeQuery(sql) 执行查询的sql语句时使用此方法,
返回值类型ResultSet,里面装着查询到的所有数据 
可以通过以下两种方法查询:
通获取数据库查询出来的字段的值(通过列名)  :   
int deptno=   rs.getInt("deptno");
通过第几列获取数据库查询出来的值   : 
int deptno=   rs.getInt(1);
​

} catch (Exception e) { ​ e.printStackTrace(); ​ }finally { ​ try { ​ conn.close(); ​ } catch (SQLException e) { ​ e.printStackTrace(); ​ } ​ }

*PreperedStatement:

PreperedStatement是Statement的孩子,它的实例对象可以通过调用:

             PreperedStatement st =  conn.preparedStatement()

*比较:

相对于Statement对象而言PreperedStatement可以避免SQL注入的问题。 Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement 可对SQL进行预编译,从而提高数据库的执行效率。并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。

*获取结果:

Jdbc程序中的ResultSet用于代表Sql语句的执行结果。Resultset封装执行结果时,采用的类似于表格的方式,ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据。

1、获取行
ResultSet提供了对结果集进行滚动的方法:
​
next():移动到下一行
Previous():移动到前一行
absolute(int row):移动到指定行
beforeFirst():移动resultSet的最前面。
afterLast() :移动到resultSet的最后面。
2、获取值
ResultSet既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法:
​
获取任意类型的数据
getObject(int index)
​
getObject(string columnName)
​
获取指定类型的数据,例如:
getString(int index)
​
getString(String columnName)

附加:
​
常用数据类型转换:
​
SQL类型                   Jdbc对应方法                     返回类型
bit(1),bit(n)           getBoolean,getBytes()          Boolean,byte[]
tinyint                 getByte()                   Byte
smallint                getShort()                  Short
int                     getInt                      Int
bigint                  getLong()                   Long
char,varchar,longvarchar    getString               String
text(clob) blob getClob(),getblob() Clob,blob
date                    getDate()                   java.sql.Date
time                    getTime()                   java.sql.Time
timestamp               getTimestamp                java.sql.Timestamp

*关闭资源:

Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象。

注意:为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。

*通过配置文件读取:

配置文件:不改源代码 就可以修改数据库信息 通过流的形式读出来 想改的时候直接改配置文件就行了

1.创建类资源路径文件夹 2.需要把配置文件放到类资源路径中 3.在项目下创建一个普通的文件夹--将这个普通的文件夹改成resource文件夹 4在里面创建一个以.properties结尾的文件夹(以k-v的形式存储)

  *前面加db. 是为了以后读数据的时候不读串  代表着数据库的东西

5.用流来读取配置文件中的信息 替换掉之前写的语句(url driver 等等)

 *用Properties来读取配置文件(key-value)

  Properties p=new Properties();
  InputStream is=Demo01.class.getClassLoader().getResourceAsStream("db.properties");
  返回一个is对象	      类加载器			调用这个对象	   传配置文件
  传配置文件时直接写相对路径就行了

*写一个工具类来连接数据库:

工具类: 每一次链接都是重复的 所以写一个工具类来提供数据库连接 提供一个获取数据库连接的方法 返回连接 *封装连接数据库的方法--配置文件获取数据库信息--

###数据库连接池DBCP(DataBaseConnectionPool)

*解决依赖jar包的问题:用maven工程来管理jar包  pom文件就是管理jar包的 把路径拷进去

file--settings--搜索maven

  • 为什么使用连接池: 如果不使用连接池,一万次业务请求需要和数据库服务器建立1万次连接,需要一万次的开关连接,这样会非常浪费资源,通过数据库连接池可以将连接重用,避免资源的浪费

  • 如何使用连接池:

    1. 引入dbcp相关jar包

      <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency>

    2. 通过以下代码创建数据库连接池对象并获取连接

      //创建连接池对象 BasicDataSource ds = new BasicDataSource(); //设置连接信息 ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/newdb3"); ds.setUsername("root"); ds.setPassword("root"); //设置初始连接数量 ds.setInitialSize(3); //设置最大连接数量 ds.setMaxActive(5); //获取连接 异常抛出 Connection conn = ds.getConnection(); System.out.println(conn); ###实现登录流程 create table user2(id int primary key auto_increment,username varchar(10),password varchar(10)); insert into user2 values(null,'zhangsan','123456'),(null,'lisi','admin'); select * from user;

  • 登录的SQL: select count(*) from user where username='lisi' and password='admin';

select count(*) from user where username='asdoifjs' and password='' or '1'='1'

  • SQL注入:用户输入值的地方,输入进去了SQL语句导致原SQL语句的逻辑发生改变称为SQL注入。

    ###PreparedStatement 预编译的SQL执行对象

  • 好处:

    1. 代表结构整洁不用拼接字符串,避免了拼接出错

    2. 可以避免SQL注入: 因为在创建SQL执行对象时就已经对SQL语句进行编译,将SQL的逻辑锁死,不会被用户输入的内容影响原有逻辑。

    ###批量执行

  • 将多条SQL语句的多次数据传输,合并成一次数据传输,目的为了提高执行效率

  • 是Statement的方法

  • stat.addBatch(sql1); stat.addBatch(sql2); stat.addBatch(sql3); //执行批量操作 stat.executeBatch();

  • for (int i = 1; i <= 100; i++) { ps.setInt(1, 10000+i); ps.setString(2, "name"+i); //添加到批量操作 ps.addBatch();//PreparedStatement 批量操作

    //为了避免内存溢出 每20次执行一次 ​ if(i%20==0) { ​ //执行批量操作 ​ ps.executeBatch(); ​ } ​ }

    		#### ###分页查询 limit    (n-1)*m,m
  •     Scanner sc = new Scanner(System.in);
    		System.out.println("请输入查询的页数");
    		int page = sc.nextInt();
    		System.out.println("请输入查询的条数");
    		int count = sc.nextInt();
    		//1. 获取连接
    		//2. 创建sql语句 
    		//3. 创建预编译的sql执行对象
    		//4. 将用户输入的页数和条数替换掉sql里面的?
    		//5. 执行SQL语句 得到ResultSet
    		//6. 遍历resultset 
    		//7. 取出员工编号和姓名 在控制台输出
    		//获取连接 并自动关闭
    		try (Connection conn = DBUtils.getConn()) {//jdk7的约束
    			String sql = 
    					"select * from emp limit ?,?";
    			PreparedStatement ps = 
    					conn.prepareStatement(sql);
    			ps.setInt(1, (page-1)*count);
    			ps.setInt(2, count);
    			ResultSet rs = ps.executeQuery();
    			while(rs.next()) {
    				int empno = rs.getInt("empno");
    				String name = rs.getString("ename");
    				System.out.println(name+":"+empno);
    			}
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    		
     

###获取自增主键的值

create table team(id int primary key auto_increment,name varchar(10)) charset=utf8; create table player(id int primary key auto_increment,name varchar(10),team_id int) charset=utf8;

		 String sql = "insert into user values"
		 		+ "(null,?,?)";
		 //创建SQL执行对象 并设置获取自增主键值
		 PreparedStatement ps = 
				 conn.prepareStatement(sql,
						 Statement.RETURN_GENERATED_KEYS);
		 ps.setString(1, "libai");
		 ps.setString(2, "123456");
		 ps.executeUpdate();
		 //获取自增的主键值
		 ResultSet rs = ps.getGeneratedKeys();
		 while(rs.next()) {
			 //由于只有一个返回的数值
			 int key = rs.getInt(1);
			 System.out.println(key);
		 }

###获取元数据

  1. 数据库的元数据 //获取数据库元数据对象 DatabaseMetaData dbmd = conn.getMetaData(); System.out.println("数据库名:"+ dbmd.getDatabaseProductName()); System.out.println("驱动版本:"+ dbmd.getDriverVersion()); System.out.println("用户名:"+ dbmd.getUserName());

  2. 表的元数据

    //获取表的元数据
    	Statement stat = conn.createStatement();
    	String sql = "select * from emp";
    	ResultSet rs = stat.executeQuery(sql);
    	//得到表元数据对象
    	ResultSetMetaData rsmd = rs.getMetaData();
    	//获取表字段数量
    	int count = rsmd.getColumnCount();
    	//获取表字段名称和类型
    	for (int i = 0; i < count; i++) {
    		String name = rsmd.getColumnName(i+1);
    		String type = rsmd.getColumnTypeName(i+1);
    		System.out.println(name+":"+type);
    	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值