认识数据库 和 mysql

/**
 * 数据库简介
 */
数据库是用来保存数据的,永久化存储数据
1)实现数据共享,当然需要权限
2)减少数据冗余
3)实现集中控制数据
4)可确保数据安全
5)出现故障可恢复
/**
 * 常见数据库
 */
MySQL:     MySQL AB公司开发,开源免费,广受国内小企业的追捧,后被Oracle收购
SQL Server: 微软开发,只能在windows上
Oracle:     老牌数据库公司,推出免费和收费两种服务模式,免费版不提供任何技术支持
DB2:        IBM公司开发,只有收费版 ,国内银行比较常用
Sybase:     即将退市状态,配套工具Power Designer广受欢迎
/**
 * MySQL的服务Server和物理库Data Files
 */
MySQL数据库通常由两部分组成:服务和物理库
服务:  提供针对物理库的CRUD操作,把命令解析成实际操作
物理库: 真正保存到硬盘上的数据
/**
 * 安装MySQL连接插件
 */
插件是由Oracle公司提供的Mysql连接插件,安装完毕可以操作数据库
官方网站
https://www.mysql.com/downloads/
Community (GPL) Downloads »
MySQL on Windows (Installer & Tools)
MySQL Installer
(mysql-installer-community-5.7.18.1.msi) 405.8M
Download
No thanks, just start my download.
安装
选Server only
配置路径
端口号3306
管理员 root 密码 123456
/**
 * 配置环境变量
 */
计算机
属性
高级
环境变量
选中系统变量中的“path”,在path值添加:
C:\Program Files\MySQL\MySQL Server 5.7\bin;
注意路径的真实性
打开cmd,测试: 
mysql -u root -p
quit
/**
 * MySQL存储数据的结构
 */
库
表
字段
记录
/**
 * sql语句分类
 */
DDL: 数据库定义语言,影响数据结构,库或表的CRUD
DML: 数据库操作语言,对数据的CRUD
DCL: 数据库控制语言,用户权限和事务控制,安卓开发中用不到
//DQL: 非标准的分类,非传统分类,特指CRUD中的查询
/**
 * MySQL存储数据的数据类型
 */
//数字类
整形
    int        占4字节,最常用   
    tinyint    占1字节,相当于byte,取值范围 -128~127 0~255
    smallint   占2字节,相当于short
    mediumint  占3字节
    bigint     占8字节,相当于long
浮点型
    float      单精度4字节
    double     双精度8字节
    decimal    没有精度损失,底层是采用字符串来保存数据
//字符串类
短型字符串(255字节以内)
    char()      定长字符串
    varchar()   变长字符串
长型字符串(几乎不用,太占数据库带宽)
    text        保存字符流,存储文本
    blob        保存字节流,存储二进制
//时间类
    datatime  记录详细 2017-04-01 08:00:30,默认记录null
    timestamp 记录详细 2017-04-01 08:00:30,默认记录保存时的当前时间
    year      只记录年,2017
    date      只记录日期,2017-04-01
    time      只记录时刻,08:00:30
/**
 * 库的操作
 */
//创建库
create database if not exists d_20170401 character set utf8 collate utf8_bin;
//查看当前所有库
show databases;
//删除库
drop database d_20170401;
//使用库       
use d_20170401;
//查看当前使用库
select database();
//修改库        
alter database d_20170401 character set utf8 collate utf8_bin;
//查看表的创建语句 
show create database d_20170401;
/**
 * 约束
 */
not null       非空约束,代表值不能为空
unique         唯一约束,代表值不能重复
primary key    主键约束,代表表中的唯一标识,同一张表最多有一个主键
auto_increment 数字才能主键自增
/**
 * 表的操作
 */
//创建表
create table if not exists t_20170401 
(
    id          int(8) primary key auto_increment,
    name        varchar(20),
    sal         double(8,2),//注意左边数要大于右边
    birthday    datetime,
    changeTime  timestamp
) character set utf8 collate utf8_bin;
//查看表
show tables;
//查看表的结构
desc t_20170401;
//修改表的名称
rename table t_20170401 to t_newName;
rename table t_newName to t_20170401;
//删除表
drop table t_20170401;
//增加列
alter table t_20170401 add age int(4);
//删除列
alter table t_20170401 drop age;
//修改列的数据类型
alter table t_20170401 modify name varchar(30);
//修改列名
alter table t_20170401 change name mingzi varchar(30);
/**
 * 可视化工具
 */
SQLyog
安装啥的,不细述
/**
 * 出现乱码
 */
显示目前的编码规范
show variables like "%character%";
character_set_client
character_set_connection
character_set_database
character_set_filesystem
character_set_results
character_set_server
character_set_system
character_sets_dir
设置编码
set character_set_client = gbk;
set chaaracter_set_results = gbk;
/**
 * 操作数据
 */
//插入记录
insert into t_20170401 (name,sal) values ("wewezhang",888.88);
//修改记录
update t_20170401 set name = "wemax" where id = 1;
//删除记录
delete from t_20170401 where name = "wewezhang";
truncate table t_20170401;
//查询记录
select id,name from t_20170401 where name="wewezhang";
select id,name from t_20170401 where name in ("we","zhang");
select id,name from t_20170401 where not name in ("we","zhang","wewezhang");
select id,name from t_20170401 where name is null;
select id,name from t_20170401 where age between 20 and 40;
//通配符
注意:不常用,通配符需要底层运算,效率较低
select * from t_20170401;
 /**
  * 模糊查询
  */
 _ 表示匹配一个任意字符
 % 表示匹配n个任意字符
 select id,name from t_20170401 where name like "%zhang";
 /**
  * 去重复
  */
 select distinct age from t_20170401;
 /**
  * 计算
  */
 select name,sal,comm, ifnull(sal,0)+ifnull(comm,0) from t_20170401;
 /**
  * 别名
  */
 select name,sal,comm, ifnull(sal,0)+ifnull(comm,0) as "总收入" from t_20170401;
 /**
  * 排序
  */
 asc    升序
 desc   降序
 select * from t_20170401 order by age;
 select * from t_20170401 order by age asc;
 select * from t_20170401 order by age desc;
 select * from t_20170401 order by sal desc,name asc;
/**
 * 聚合函数
 */
count() 计算指定列不为null的总列数
max()   计算指定列最大值
min()   计算指定列最小值
sum()   计算指定列和
avg()   计算指定列平均值
/**
 * 分组查询 group by
 */
where查询分组结果前的操作
having查询分组结果后的操作,较耗性能,不常用
select bumen sum(sal) from t_20140405 group by bumen having sum(sal)>1000;
/**
 * limit
 */
mySql独有
限定查询的起始行和总行数
limit 0,5;
/**
 * JDBC
 */
Java Database connectivity
JDBC是java的研发公司(Sun公司)提供的访问数据库的API
统一众多数据库的接口规范,方便程序开发
/**
 * 导入jdbc的mysql开发包
 */
https://www.mysql.com/products/connector/
JDBC Driver for MySQL (Connector/J)
Platform Independent (Architecture Independent), ZIP Archive
解压
mysql-connector-java-5.1.41-bin.jar
粘贴到工程下的lib文件夹下
.jar 右键
Build Path
Add to Build Path
/**
 * 部署单元测试的环境jUnit
 */
工程
右键
Properties
Java Build Path,libraries,Add Library...
JUnit,Next
JUnit4,Finish,OK
/**
 * 单元测试写法:加注解@Test、public 、void、无参数
 * 单元测试运行:右键,Run As,JUnitTest,选择方法
 */
新建Java工程
新建Java Class文件
import org.junit.Test;
public class Demo {
    @Test
    public void funAny() {
    }
}
/**
 * JDBC实现思路
 */
package com.wewezhang.jdbc_hello;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
 
import org.junit.Test;
 
public class Demo {
    @Test
    public void funZeng() throws Exception {
        //注册驱动方法1,不推荐此方法,原因是Driver类的静态代码块中已经调用过此方法
//      DriverManager.registerDriver(new Driver());
        //注册驱动方法2,推荐,手动加载类即可
        Class.forName("com.mysql.jdbc.Driver");
        //获得连接对象
        Connection weMysqlConnection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/t_20170401?characterEncoding=utf8&useSSL=true","root","123456");
        //普通的连接代理对象
//      Statement weMysqlStatement = weMysqlConnection.createStatement();
        //支持反向修改数据库的连接代理对象
        Statement weMysqlStatement = weMysqlConnection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
        //增删改用executeUpdate
        String weZeng = "insert into t_20170401 (id ,name,sal) values (null,'wewezhang',888.88)";
        int weZengResult = weMysqlStatement.executeUpdate(weZeng);
        if(weZengResult==0){
            throw new RuntimeException("weZeng失败");
        }
        //查用executeQuery
        String weCha = "select * from t_20170401";
        ResultSet weChaResultSet = weMysqlStatement.executeQuery(weCha);
        //正序
        weChaResultSet.beforeFirst();
        while (weChaResultSet.next()) {
            int weId = weChaResultSet.getInt("id");
            String weName = weChaResultSet.getString("name");
            System.out.println("正序"+" id~"+weId+" name~"+weName);
        }
        //倒序
        weChaResultSet.afterLast();
        while (weChaResultSet.previous()) {
            int weId = weChaResultSet.getInt("id");
            String weName = weChaResultSet.getString("name");
            System.out.println("倒序"+" id~"+weId+" name~"+weName);
        }
        //反向修改数据库
        weChaResultSet.beforeFirst();
        weChaResultSet.next();
        weChaResultSet.updateString("name", "weTom");
        weChaResultSet.updateRow();
        //关闭数据库
        weMysqlStatement.close();
        weMysqlConnection.close();
    }
}
/**
 * 配置properties文件
 */
New
File
jdbc.properties
Source
driver   = com.mysql.jdbc.Driver
url      = jdbc:mysql://127.0.0.1:3306/t_20170401?characterEncoding=utf8&useSSL=true
user     = root
password = 123456
/**
 * 封装JDBC工具类
 */
package com.wewezhang.jdbc_hello;
 
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
 
public class JDBCUtils {
     
    private static String driver;
    private static String url;
    private static String user;
    private static String password;
    
    /*
     * 静态代码块
     * 类加载时只执行一次,适合创建单例对象
     */
    static {
        try{
            //读取properties文件
            Properties weProperties = new Properties();
            InputStream weInputStream = new FileInputStream("src/jdbc.properties");
            weProperties.load(weInputStream);
            weInputStream.close();
            //读取properties里的数据
            driver = weProperties.getProperty("driver");
            url = weProperties.getProperty("url");
            user = weProperties.getProperty("user");
            password = weProperties.getProperty("password");
            //推荐注册数据库驱动,类加载时自动调用静态代码
            Class.forName(driver);
        } catch(Exception error) {
            error.printStackTrace();
            throw new RuntimeException("加载jdbc.properties失败~~~");
        }
    }
    /*
     * 连接数据库并返回连接
     */
    public static Connection getConnection() {
        Connection weConnection  = null;
        try{
            //连接数据库
        	weConnection = DriverManager.getConnection(url,user,password);
        } catch(Exception error) {
            error.printStackTrace();
            throw new RuntimeException("数据库连接失败~~~");
        }
        return weConnection;
    }
    /*
     * 释放数据库
     */
    public static void closeConnection(Connection weConnection, Statement weStatement,ResultSet weResultSet) {
        try{
            if(weResultSet!=null) weResultSet.close();
        } catch(Exception error) {
            error.printStackTrace();
        } finally {
            try{
                if(weStatement!=null) weStatement.close();
            } catch(Exception error) {
                error.printStackTrace();
            } finally {
                try{
                    if(weConnection!=null) weConnection.close();
                } catch(Exception error) {
                    error.printStackTrace();
                } finally {
                }
            }
        }
    }
    /*
     * 测试,右键,Run As,Application
     */
//  public static void main(String[] args) {
//      System.out.println(getConnection());
//  }
}
/**
 * sql注入问题
 */
普通sql条件语句在开发中有很大的安全漏洞
"select * from t_20170401 where name='"+name+"';"
假设用户输入的是: zhang' or true or 'baby
就变成了
select * from t_20170401 where name='zhang' or true or 'baby';
那么,数据库就存在安全隐患了
/**
 * sql注入的解决方案
 */ 
Java给出了sql注入的解决办法
prepareStatement对象将不带参数的sql语句预先进行编译
prepareStatement对象再将参数传递,这样就避免出现sql注入问题
/**
 * 应用JDBCUtils的案例
 */
package com.wewezhang.jdbc_hello;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import org.junit.Test;

public class Demo {
	@Test
	public void funZeng() throws Exception {
		//连接数据库
		Connection weConnection = JDBCUtils.getConnection();
		//支持反向修改数据库的连接代理对象
        Statement weStatement = weConnection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
        //查用executeQuery
        String weCha = "select * from t_20170401";
        ResultSet weResultSet = weStatement.executeQuery(weCha);
        //正序
        weResultSet.beforeFirst();;
        while (weResultSet.next()) {
            int weId = weResultSet.getInt("id");
            String weName = weResultSet.getString("name");
            System.out.println("Go"+" id~"+weId+" name~"+weName);
        }
        //倒序
        weResultSet.afterLast();
        while (weResultSet.previous()) {
            int weId = weResultSet.getInt("id");
            String weName = weResultSet.getString("name");
            System.out.println("Back"+" id~"+weId+" name~"+weName);
        }
        //关闭数据库
        JDBCUtils.closeConnection(weConnection, weStatement, weResultSet);
	}
}
/**
 * 存储大文本,字符流
 */
//先建数据库的表
Create table if not exists t_BigText
(
    id   int  primary key  auto_increment,
    text text
);
//测试代码 - 大文本(需要额外注意文件的乱码问题)
@Test
public void funDaWenBen() throws Exception {
	//获得连接
    Connection weConnection = JDBCUtils.getConnection();
    //创建prepareStatement管理对象
    String weSql = "insert into t_BigText values(null,?)";
    PreparedStatement weStatement = weConnection.prepareStatement(weSql);
    //准备参数
    File weFile = new File("src/HongLouMeng.txt");
    FileReader weFileReader = new FileReader(weFile);
    //参数索引号,流,流的长度
    weStatement.setCharacterStream(1, weFileReader, (int)weFile.length());
    weFileReader = null;
    weFile = null;
    //查用executeUpdate
    int iUpdate = weStatement.executeUpdate();
    System.out.println("操作完成"+iUpdate);
    //关闭数据库
    JDBCUtils.closeConnection(weConnection,weStatement,null);
}
/**
 * 存储二进制字节流(不常用)
 */
//先建数据库的表
Create table if not exists t_blob
(
    id    int    primary key  auto_increment,
    file  blob
);
//测试代码 - 二进制
@Test
public void funErJinZhi() throws Exception {
	//获得连接
    Connection weConnection = JDBCUtils.getConnection();
    //创建prepareStatement管理对象
    String weSql = "insert into t_blob values(null,?)";
    PreparedStatement weStatement = weConnection.prepareStatement(weSql);
    //准备参数
    File weFile = new File("src/honghaier.jpg");
    InputStream weInputStream = new FileInputStream(weFile);
    //参数索引号,流,流的长度
    weStatement.setBinaryStream(1, weInputStream,(int)weFile.length());
    weInputStream = null;
    weFile = null;
    //查用executeUpdate
    int iUpdate = weStatement.executeUpdate();
    System.out.println("操作完成"+iUpdate);
    //关闭数据库
    JDBCUtils.closeConnection(weConnection,weStatement,null);
}
/**
 * 批量执行sql语句
 */
注意不能执行查询
@Test
public void funZhuRu() throws Exception {
    //获得连接
    Connection weConnection = JDBCUtils.getConnection();
    //创建Statement管理对象
    Statement weStatement = weConnection.createStatement();
    //添加多条sql语句
    weStatement.addBatch("insert into t_BigText values(null,'jack')");
    weStatement.addBatch("insert into t_BigText values(null,'rose')");
    //执行sql
    int[] weResultSet = weStatement.executeBatch();
    System.out.println(Arrays.toString(weResultSet));
    //关闭数据库
    JDBCUtils..closeConnection(weConnection,weStatement,null);
}

  

posted @ 2017-04-02 07:30  WeWeZhang  阅读(230)  评论(0编辑  收藏  举报