关闭

java程序员第十七课 -JDBC01

标签: 数据库javac语言程序员函数
194人阅读 评论(0) 收藏 举报
分类:

课程回顾:MySQL多表

分组

1.MySQL分组的,使用关键字 group by,如果有条件可以使用having 条件。可以使用聚集函数。
2.不使用group by,默认是一组。

3.总结:select … from … where … group by … having … order by
表的约束

1.主键约束,把某个字段声明成主键,特点:唯一、非空和被引用。代表当前该条记录。
* 关键字 primary key
* 自动增长:auto_increment

2.唯一约束:值是唯一的,允许存入null值。使用关键字unique。
3.非空约束:值不能为空,关键字not null

4.外键约束:保证数据的完整性。
* 使用关键字 foreign key (dno) references 表 (did);
数据库表结果的设计

1.一对多
* 一个部门下有多个员工。
* 建表原则:在多方表(员工表)中,新创建一个字段,但是该字段声明外键指向一方表(部门表)的主键。

2.多对多
* 一个学生可以选择多门课程,一门课程可以被多个学生选择。
* 建表原则:创建一个中间表,中间表至少包含两个字段,分别声明成外键指向原来多方表(学生和课程表)的主键。

3.一对一
* 一个公司有一个地址。
* 主键对应。唯一外键对应。
多表查询

1.了解笛卡尔积
2.内连接查询
* 普通内连接:表1 inner join 表2 on 表1.字段 = 表2.字段
* 隐式内连接:select * from 表1,表2 where 表1.字段 = 表2.字段

3.外链接查询
* 左链接:表1 left join 表2 on 表1.字段 = 表2.字段
* 右链接:表1 right join 表2 on 表1.字段 = 表2.字段

4.左链接:看左表,把左表所有的数据全部都查询出来,还查询两张表有关联的数据。
5.右链接:看右表,把右表所有的数据全部都查询出来,还查询两张表有关联的数据。

6.子查询:一个查询的语句,需要依赖另外一条查询语句。
* >any :大于最小的值
* >all :大于最大的值
今天的课程内容:JDBC第一天

JDBC的概述

1.JDBC的概述:使用Java代码来操作数据库。(数据的增删改查的操作)
2.MySQL数据库的生厂商提供了MySQL的JDBC接口的实现类(jar包),先导入MySQL驱动包。
3.JDBC的入门的步骤(开发步骤比较固定的)
* 看图。
JDBC的快速入门

1.编写的查询的代码。
* 创建的WEB项目,导入MySQL驱动的jar包。
* 先创建一个数据库和表结构,添加一些数据。
* 进行开发了。

2.创建数据库
create database day17;
use day17;
create table t_user(
id int primary key auto_increment,
username varchar(50),
password varchar(50)
);

insert into t_user values (null,'美美','123');
insert into t_user values (null,'小凤','456');
insert into t_user values (null,'小花','789');
insert into t_user values (null,'aaa','111');
insert into t_user values (null,'bbb','222');

3.代码
public class JdbcDemo1 {
@Test
public void run() throws SQLException{
/**
* 1.加载驱动
* 2.获取链接
* 3.执行SQL语句
* 4.如果有返回结果,遍历之。
* 5.释放资源
*/
// 加载驱动
DriverManager.registerDriver(new Driver());
// 获取链接对象
Connection conn = DriverManager.getConnection(“jdbc:mysql://localhost:3306/day17”, “root”, “root”);
// 先编写sql语句
String sql = “select * from t_user”;
// 执行该sql语句,先获取能执行该sql语句的对象(Statement)
Statement stmt = conn.createStatement();
// 执行SQL语句
ResultSet rs = stmt.executeQuery(sql);
// 可以进行循环遍历了
while(rs.next()){
// 获取内容
int id = rs.getInt(“id”);
String username = rs.getString(“username”);
String password = rs.getString(“password”);
System.out.println(id+” “+username+” “+password);
}
// 释放资源
rs.close();
stmt.close();
conn.close();
}
}
JDBC相关的接口和API

DriverManager类(驱动)

1.注册驱动
* DriverManager.registerDriver(new Driver());
* 上面这行代码有两个不好的地方
* 过于依赖某一个驱动的类(切换数据库的驱动,不是很方便)
* 驱动默认加载了两次(通过看源码)
* 解决上述的两个问题
* Class.forName(“com.mysql.jdbc.Driver”);

2.获取链接的对象
* Connection conn = DriverManager.getConnection(“jdbc:mysql://localhost:3306/day17”, “root”, “root”);
* getConnection方法的参数
* url – 数据库的链接地址
* jdbc:mysql://localhost:3306/day17
* jdbc – jdbc数据库的链接的协议
* mysql – 数据库链接协议的子协议
* localhost – 链接数据库的地址(服务器的地址)
* 3306 – MySQL默认端口号
* day17 – 数据库的名称
* 如果你现在链接的本地的MySQL,有简写的方式
* jdbc:mysql:///day17

    * user          -- 数据库的用户
    * password      -- 你的数据库的密码

Connection接口(链接)

1.创建能执行SQL语句的对象
* Statement createStatement() – 创建能执行SQL语句的对象
* PreparedStatement prepareStatement(String sql) – 创建能执行SQL语句的对象,可以进行预编译操作,防止SQL注入
* CallableStatement prepareCall(String sql) – 创建能执行SQL语句的对象,但是创建执行存储过程的。

2.管理事物
* 事物:要么成功要么失败。
* void setAutoCommit(boolean autoCommit) – 开启事物(传入false)
* void commit() – 提交事物
* void rollback() – 回滚事物
Statement接口(能执行SQL语句)

1.能执行SQL语句
* ResultSet executeQuery(String sql) – 执行查询的语句,如果有返回的结果,返回ResultSet
* int executeUpdate(String sql) – 执行增删改的SQL,返回值是int,影响了几行。
* boolean execute(String sql) – 能执行增删改查的SQL,返回值是boolean(如果第一个结果为 ResultSet 对象,则返回 true;如果其为更新计数或者不存在任何结果,则返回 false)

2.能执行批处理(MySQL默认不开启批处理,需要使用参数进行设置)
* 批处理:批量插入或者删除数据。(Excel表格,导入Excel表格的数据到数据库中)
* void addBatch(String sql) – 加入批处理
* int[] executeBatch() – 执行批处理
* void clearBatch() – 清空批处理
ResultSet接口(代表结果集)

1.ResultSet代表的结果集。内部有一个游标,调用rs.next()方法来移动游标。获取数据。
2.哪些数据方法获取数据
* getInt()
* getString()
* getDouble()
* getObject()
* getXXX()

3.这些方法包含重载的方式
* getInt(int index) – 通过下表值获取字段的值
* getInt(String 字段名称) – 通过字段的名称或者字段的值(使用)

4.游标默认只能向下移动,如果你想让游标任意的移动,需要设置滚动的结果集(了解)
设置滚动的结果集(了解)

1.游标只能默认向下
2.常用的结果集类型
TYPE_FORWARD_ONLY :结果集只能向下
TYPE_SCROLL_INSENSITIVE :可以滚动,不能修改记录
TYPE_SCROLL_SENSITIVE :可以滚动,可以修改记录
常用的并发策略
CONCUR_READ_ONLY :只读的,不能修改
CONCUR_UPDATABLE :结果集可以修改

3.组合
TYPE_FORWARD_ONLY CONCUR_READ_ONLY 默认的结果集,只能向下,不能修改记录
TYPE_SCROLL_INSENSITIVE CONCUR_READ_ONLY 可以滚动,不能修改记录
TYPE_SCROLL_SENSITIVE CONCUR_UPDATABLE 可以滚动,也可以修改记录

4.模拟(结果集即可以滚动又可以修改)
释放资源

1.需要释放的接口(ResultSet接口、Statement接口、Connection接口)
2.释放的方法:rs.close();
3.释放资源的代码放在什么位置?
* 可以把释放资源代码放在finally代码块中。

4.代码
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
// rs赋值null
rs = null;
}
JDBC增删改查

1.针对t_user表结构增删改查的方法。
JDBC的工具类编写

1.代码:
package cn.itcast.utils;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * JDBC的工具类
 * @author rt
 */
public class MyJdbcUtil {

    public static final String DRIVERCLASS;
    public static final String URL;
    public static final String USERNAME;
    public static final String PASSWORD;

    /**
     * 解析db.properties文件,赋值。
     */
    static{
        // 解析db.properties
        Properties pro = new Properties();
        // 获取db.properties文件的输入流
        InputStream in = MyJdbcUtil.class.getClassLoader().getResourceAsStream("db.properties");
        // 加载文件
        try {
            pro.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 读取资源文件,进行赋值
        DRIVERCLASS = pro.getProperty("driverClass");
        URL = pro.getProperty("url");
        USERNAME = pro.getProperty("username");
        PASSWORD = pro.getProperty("password");
    }

    /**
     * 加载驱动
     */
    public static void loadDriver(){
        // 加载驱动
        try {
            Class.forName(DRIVERCLASS);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取链接对象
     */
    public static Connection getConnection(){
        // 加载驱动
        loadDriver();
        // 获取链接
        try {
            return DriverManager.getConnection(URL, USERNAME, PASSWORD);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 释放资源(两个参数和三个参数)
     */
    public static void release(ResultSet rs,Statement stmt,Connection conn){
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs = null;
        }
        if(stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            stmt = null;
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            conn = null;
        }
    }

    /**
     * 释放资源(两个参数和三个参数)
     */
    public static void release(Statement stmt,Connection conn){
        if(stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            stmt = null;
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            conn = null;
        }
    }
}

JavaEE三层结构(规范)

1.DAO模式:SUN公司提供解决问题的思想。操作数据库。DAO代码中封装的单个表的操作。(t_user) DAO中写的代码就是t_user表的增删改查的操作。

2.规范:DAO模式基于接口,自己编写实现类。希望传数据的时候传递对象。
重写登陆的案例

1.架构:Servlet+JSP+JavaBean+JDBC
2.导入jar包。
* Servlet需要封装数据(BeanUtils 导入2个jar包)
* JSP显示数据(JSTL标签库 导入2个jar)
* JDBC(导入MySQL驱动jar包)
3.创建包结构
* cn.itcast.servlet
* cn.itcast.service
* cn.itcast.dao
* cn.itcast.vo
* cn.itcast.utils

4.导入自己编写的工具类

5.先编写登陆的页面,提交到Servlet – service – dao层
SQL注入的漏洞

1.漏洞,在已知用户名的情况下,不用输入密码,可以登陆进去了。
2.防范sql注入攻击(xxx ’ or ’ 1=1 或者 xxx ’ –- ‘)
* select * from t_user where username = ’ ’ and password = ’ ‘;
* select * from t_user where username = ’ ccc ’ or ’ 1=1 ’ and password = ‘任意’;
* select * from t_user where username = ’ ccc ’ – ’ ’ and password = ’ ‘;

3.产生原因:通过拼接SQL语句,利用SQL语句中的关键字来完成该操作。
4.使用新的对象
* preparedStatement 接口
* 进行预编译(先把SQL进行编译,编译后的SQL语句的格式就固定了,再传入参数(包含关键字),参数的关键字MySQL不认识了,当成普通参数。)
* 参数的位置需要使用?占位符。

5.编写代码
public User loginUser2(User user) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
// 先获取链接
conn = MyJdbcUtil.getConnection();
// 编写SQL语句(不同,参数就不能拼接了,需要使用?占位符)
String sql = “select * from t_user where username = ? and password = ?”;
// 预编译SQL(进行预编译 )
stmt = conn.prepareStatement(sql);
// 设置参数 (ccc ’ or ’ 1=1 全部当成username的值)
stmt.setString(1, user.getUsername());
stmt.setString(2, user.getPassword());
// 执行SQL语句(方法就不需要传入SQL语句)
rs = stmt.executeQuery();
// 封装数据,返回
if(rs.next()){
// 说明登陆成功了
// 封装数据,返回对象返回
User u = new User();
u.setId(rs.getInt(“id”));
u.setUsername(rs.getString(“username”));
u.setPassword(rs.getString(“password”));
return u;
}

    } catch (Exception e) {
        e.printStackTrace();
    }finally{
        MyJdbcUtil.release(rs, stmt, conn);
    }
    return null;
}

6.不同点
* 使用对象PreparedStatement接口(防止SQL注入)
* 编写SQL语句的时候,需要使用占位符?作为参数。
* stmt = conn.prepareStatement(sql); – 需要传入SQL语句,先进行预编译的操作。
* 设置?的值。
* 执行SQL语句。
增删改查(会写)

1.需要使用PreparedStatement对象来完成增删改查的操作。
2.需要编写在DAO模式中。
操作大的数据(了解)

1.向数据库中存入文本的文档或者mp3等等。
2.文件的上传不是这么做的!!
3.注意
* 设计表结构的时候,指定数据的类型(注意类型对应的大小)

4.存储文本的文件
* 创建表结构
create table mytext(
id int primary key auto_increment,
mydata MEDIUMTEXT
);

* 存储的数据

5.异常
Packet for query is too large (1928573 > 1048576). You can change this value on the server by setting the max_allowed_packet’ variable.
6.在my.ini配置文件中进行设置
* 在mysqld下面添加max_allowed_packet=64M
* 先停止MySQL服务,修改配置文件,重启服务。

7.掌握的方法
* stmt.setCharacterStream(1, reader, (int)file.length());
* 第一个参数:代表?的位置
* 第二个参数:文件的输入流
* 第三个参数:文件的大小(转成int类型的)

8.从数据库中获取文本的内容
* Reader r = rs.getCharacterStream(“mydata”);

9.创建数据库
create table mymp3(
id int primary key auto_increment,
mydata MEDIUMBLOB
);
批处理

1.批处理:把一批的SQL语句放入一个批次中,执行。
2.可以使用statement接口完成批处理。
* 有一条SQL语句,statement编译一次,执行一次。
3.使用批处理,还使用PreparedStatemtn对象。
* 对SQL语句进行预编译,SQL编译一次。设置值。

4.和批处理相关的方法
* void addBatch(String sql) – 加入批处理
* int[] executeBatch() – 执行批处理
* void clearBatch() – 清空批处理

5.创建数据库
create table mybatch(
id int primary key auto_increment,
name varchar(20)
);

6.MySQL数据库的批处理默认没有开启,需要手动进行设置。
* 添加到数据库链接的后面:rewriteBatchedStatements=true
* jdbc:mysql:///day17?rewriteBatchedStatements=true
别忘了还有一个注册的功能呢?你们自觉吧!!!!!

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场