知识点
数据库和SQL
软件安装
安装mysql: windows10上安装mysql(详细步骤)
安装Navicat: 学习MySQL的第一步:安装MySQL及数据库可视化工具Navicat
Navicat使用教程: Navicat for MySQL的使用
DB
DB: Database = Data + Base 保存数据的地方
数据库:数据+库,存放数据的库(场所)
-
优点
- 数据安全、安全、安全
- 存取效率
- 性价比高
-
DBMS: Database Management System
- 操纵和管理数据库的软件,可建立、使用和维护数据库
- DB种类
- 文本文件/二进制文件
- Xls文件
- Access(包含在office里面,收费,只能运行在Windows上。32和64,office 95/97/2000/2003/2007/2010/…)
Mysql
/Postgresql/Berkely DB (免费, 但也有收费版。多平台,32和64位区分。)SQL Server
(收费,只能运行Windows,32位和64位,中文文档。SQL Server 2000/2005/2008/2012/…,也免费版,但有CPU和内存限制)Oracle
/DB2(收费,全平台,32和64位,英文文档,也有免费版,但有CPU和内存限制)- SQLite (免费,手机上使用)
表
- 表:table, 实体
- 列:列、属性、字段
- 行:记录、元组tuple,数据
- 数据值域:数据的取值范围
- 字段类型
- int :整数 -2147483648~2147483647,4个字节
- double:小数,8个字节
- datetime :时间,7个字节
- varchar:字符串,可变字节
SQL
基础知识
- 结构化查询语言(Structured Query Language),简称SQL
- 是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。
- SQL标准
- SQL-86/SQL-89/SQL-92
- SQL:1999/ SQL:2003/ SQL:2008/ SQL:2011/ SQL:2016
- 基础的部分,所有标准都一样
- 标准仅仅是标准,每个厂商的数据库实现可能有一些不一致
示例
create table t1(a int, b varchar(20));
创建一张表叫 t1,包含两列:a 和 b,a 是 int,b 是 varchar(20)
insert into t1(a,b) values(1,’abc’);
插入语句,向表中插入一条记录1,abc
select a from t1;
选择语句,把表中a这一列的值取出来
select a,b from t1 where a > 1;
把表 t1 中 a,b 两列数据都取出来,并且要求 a >1
delete from t1 where a = 10 and b=‘ab’;
删除语句,从表 t1 中把记录10,ab 删除掉
update t1 set a=2, b = ‘cd’ where a=1 and b=‘ab’;
更新语句,把 t1 表中1,ab 的记录更新为2,cd
drop table t1;
删除语句,把 t1 表删除掉
JDBC基本操作
JDBC
- Java和数据库是平行的两套系统
- Java和数据库的连接方法
- Native API
(不能跨平台)
- ODBC/JDBC-ODBC
(效率很差,也无法跨平台)
- JDBC (主流): Java Database Connectivity
- JDBC 1, JDK 1.1
- JDBC 2 JDK 1.3~JDK1.4
- JDBC 3 JDK 5
- JDBC 4 JDK 6, (JDK 7, JDBC4.1; JDK8, JDBC4.2)
- Native API
ODBC,Open Database Connectivity,开放数据库连接,是Windows平台上为了解决异构数据库间的数据共享而产生的。
Java SQL 操作类库
- java.sql.*, javax.sql.*;
这2个包只是接口类
- 根据数据库版本和JDBC版本合理选择
- 一般数据库发行包都会提供jar包,同时也要注意区分32位和64位(数据库分32/64位, JDK也分32/64位)。
- 连接字符串(样例)
- jdbc:oracle:thin:@127.0.0.1:1521:dbname
- jdbc:mysql://localhost:3306/mydb
- jdbc:sqlserver://localhost:1433;DatabaseName=dbname
Java连接数据库操作步骤
- 构建连接(搭桥)
- 注册驱动,寻找材质, class.forName(“…”);
- 确定对岸目标 , 建桥 Connection
- 执行操作(派个人过桥, 提着篮子,去拿数据)
- Statement (执行者)
- ResultSet(结果集)
- 释放连接(拆桥) connection.close();
Statement
- Statement 执行者类
- 使用executeQuery()执行select语句,返回结果放在ResultSet
- 使用executeUpdate()执行insert/update/delete,返回修改的行数
- 一个Statement对象一次只能执行一个命令
- ResultSet 结果对象(二维数组)
- next() 判断是否还有下一条记录
- getInt/getString/getDouble/……
- 可以按索引位置,可以按照列名
示例代码
数据库内容
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>MOOC19-02</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>14</maven.compiler.source>
<maven.compiler.target>14</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
</dependencies>
</project>
SelectTest
import java.sql.*;
public class SelectTest {
public static void main(String[] args){
//构建Java和数据库之间的桥梁介质
try{
Class.forName("com.mysql.jdbc.Driver");
System.out.println("注册驱动成功!");
}catch(ClassNotFoundException e1){
System.out.println("注册驱动失败!");
e1.printStackTrace();
return;
}
String url="jdbc:mysql://localhost:3306/test";
Connection conn = null;
try {
//构建Java和数据库之间的桥梁:URL,用户名,密码
conn = DriverManager.getConnection(url, "root", "123456");
//构建数据库执行者
Statement stmt = conn.createStatement();
System.out.println("创建Statement成功!");
//执行SQL语句并返回结果到ResultSet
ResultSet rs = stmt.executeQuery("select bookid, bookname, price from t_book order by bookid");
//开始遍历ResultSet数据
while(rs.next())
{
System.out.println(rs.getInt(1) + "," + rs.getString(2) + "," + rs.getInt("price"));
}
rs.close();
stmt.close();
} catch (SQLException e){
e.printStackTrace();
}
finally
{
try
{
if(null != conn)
{
conn.close();
}
}
catch (SQLException e){
e.printStackTrace();
}
}
}
}
运行结果(替换正确密码)如下:
import java.sql.*;
public class UpdateTest {
public static void main(String[] args){
executeUpdate("update t_book set price = 300 where bookid = 101");
executeUpdate("insert into t_book(bookid, bookname, price) values(104, 'dddd', 90)");
executeUpdate("delete from t_book where bookid = 102");
}
public static void executeUpdate(String sql)
{
//构建Java和数据库之间的桥梁介质
try{
Class.forName("com.mysql.jdbc.Driver");
System.out.println("注册驱动成功!");
}catch(ClassNotFoundException e1){
System.out.println("注册驱动失败!");
e1.printStackTrace();
}
String url="jdbc:mysql://localhost:3306/test";
Connection conn = null;
try {
//构建Java和数据库之间的桥梁:URL,用户名,密码
conn = DriverManager.getConnection(url, "root", "123456");
//构建数据库执行者
Statement stmt = conn.createStatement();
System.out.println("创建Statement成功!");
//执行SQL语句
int result = stmt.executeUpdate(sql);
stmt.close();
} catch (SQLException e){
e.printStackTrace();
}
finally
{
try
{
if(null != conn)
{
conn.close();
}
}
catch (SQLException e){
e.printStackTrace();
}
}
}
}
运行结果(替换正确密码)如下:
注意事项
- ResultSet不能多个做笛卡尔积连接
- ResultSet最好不要超过百条,否则极其影响性能
- ResultSet也不是一口气加载所有的select结果数据
- Connection 很昂贵,需要及时close
- Connection所用的jar包和数据库要匹配
JDBC高级操作
事务管理
事务
- 数据库事务,Database Transaction。
- 作为单个逻辑工作单元执行的一系列操作,
要么完全地执行,要么完全地不执行。
- 事务,必须满足所谓的ACID(
原子性、一致性、隔离性和持久性
)属性。 - 事务是数据库运行中的逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。
JDBC事务
- 关闭自动提交,实现多语句同一事务:
- connection.setAutoCommit(false);
- connection.commit(); 提交事务
- connection.rollback(); 回滚事务
- 保存点机制
- connection.setSavepoint()
- connection.rollback(Savepoint)
示例代码
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
public class TransactionTest {
public static void main(String[] args) throws Exception {
// 构建Java和数据库之间的桥梁介质
try {
Class.forName("com.mysql.jdbc.Driver");
System.out.println("注册驱动成功!");
} catch (ClassNotFoundException e1) {
System.out.println("注册驱动失败!");
e1.printStackTrace();
}
String url = "jdbc:mysql://localhost:3306/test";
Connection conn = null;
try {
// 构建Java和数据库之间的桥梁:URL,用户名,密码
conn = DriverManager.getConnection(url, "root", "123456");
conn.setAutoCommit(false); //关闭自动提交
insertBook(conn, "insert into t_book values(101, 'aaaa', 10)");
insertBook(conn, "insert into t_book values(102, 'bbbb', 10)");
insertBook(conn, "insert into t_book values(103, 'cccc', 10)");
Savepoint phase1 = conn.setSavepoint(); //设置一个保存点
insertBook(conn, "insert into t_book values(104, 'cccc', 10)");
insertBook(conn, "insert into t_book values(105, 'cccc', 10)");
conn.rollback(phase1); //回滚到phase1保存点,即上面2行无效
conn.commit();
System.out.println("操作成功");
} catch (SQLException e) {
e.printStackTrace();
conn.rollback();
} finally {
if (null != conn) {
conn.close();
}
}
}
public static void insertBook(Connection conn, String sql) {
try {
// 构建数据库执行者
Statement stmt = conn.createStatement();
//System.out.print("创建Statement成功!");
// 执行SQL语句
int result = stmt.executeUpdate(sql);
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
运行结果如下:
PreparedStatement
基础知识
- 拼接SQL字符串
很危险
,可能包含恶意语句
- Java提供PreparedStatement,更为安全执行SQL
- 和Statement区别是使用“?” 代替字符串拼接
- 使用setXXX(int,Object)的函数来实现对于?的替换
- 注:不需要考虑字符串的两侧单引号
- 参数赋值,清晰明了,拒绝拼接错误
- 提供addBatch批量更新功能
- Select语句一样用ResultSet接收结果
- 使用PreparedStatement的好处:
- 防止注入攻击
- 防止繁琐的字符串拼接和错误
- 直接设置对象而不需要转换为字符串
- PreparedStatement使用预编译速度相对Statement快很多
示例代码
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
public class InsertTest {
public static void main(String[] a)
{
//concatInsertBook();
//unsafeConcatInsertBook();
//safeInsertBook(); //安全插入
batchInsertBook(); //批量插入
}
public static void concatInsertBook()
{
//构建Java和数据库之间的桥梁介质
try{
Class.forName("com.mysql.jdbc.Driver");
System.out.println("注册驱动成功!");
}catch(ClassNotFoundException e1){
System.out.println("注册驱动失败!");
e1.printStackTrace();
}
String url="jdbc:mysql://localhost:3306/test";
Connection conn = null;
try {
//构建Java和数据库之间的桥梁:URL,用户名,密码
conn = DriverManager.getConnection(url, "root", "123456");
//构建数据库执行者
Statement stmt = conn.createStatement();
System.out.println("创建Statement成功!");
//执行SQL语句
int bookid = 10;
String bookName = "Effective Java";
int price = 50;
//values(1, 'Effective Java', 50)
String sql = "insert into t_book(bookid,bookname,price) values("
+ bookid + ", '" + bookName + "', " + price + ")";
int result = stmt.executeUpdate(sql);
stmt.close();
System.out.println("操作成功");
} catch (SQLException e){
e.printStackTrace();
}
finally
{
try
{
if(null != conn)
{
conn.close();
}
}
catch (SQLException e){
e.printStackTrace();
}
}
}
public static void unsafeConcatInsertBook()
{
//构建Java和数据库之间的桥梁介质
try{
Class.forName("com.mysql.jdbc.Driver");
System.out.println("注册驱动成功!");
}catch(ClassNotFoundException e1){
System.out.println("注册驱动失败!");
e1.printStackTrace();
}
String url="jdbc:mysql://localhost:3306/test?allowMultiQueries=true";
Connection conn = null;
try {
//构建Java和数据库之间的桥梁:URL,用户名,密码
conn = DriverManager.getConnection(url, "root", "123456");
//构建数据库执行者
Statement stmt = conn.createStatement();
System.out.println("创建Statement成功!");
//执行SQL语句
int bookid = 10;
String bookName = "Effective Java',50);delete from t_book;insert into t_book values(101, 'faked book";
int price = 50;
//values(1, 'Effective Java', 50)
String sql = "insert into t_book(bookid,bookname,price) values("
+ bookid + ", '" + bookName + "', " + price + ");";
System.out.println(sql);
int result = stmt.executeUpdate(sql);
stmt.close();
System.out.println("操作成功");
} catch (SQLException e){
e.printStackTrace();
}
finally
{
try
{
if(null != conn)
{
conn.close();
}
}
catch (SQLException e){
e.printStackTrace();
}
}
}
public static void safeInsertBook()
{
//构建Java和数据库之间的桥梁介质
try{
Class.forName("com.mysql.jdbc.Driver");
System.out.println("注册驱动成功!");
}catch(ClassNotFoundException e1){
System.out.println("注册驱动失败!");
e1.printStackTrace();
}
String url="jdbc:mysql://localhost:3306/test?allowMultiQueries=true";
Connection conn = null;
try {
//构建Java和数据库之间的桥梁:URL,用户名,密码
conn = DriverManager.getConnection(url, "root", "123456");
String sql = "insert into t_book(bookid,bookname,price) values(?,?,?)";
//构建数据库执行者
PreparedStatement pstmt = conn.prepareStatement(sql);
//执行SQL语句
int bookid = 10;
String bookName = "Effective Java',50);delete from t_book;insert into t_book values(101, 'faked book";
int price = 50;
//values(1, 'Effective Java', 50)
pstmt.setInt(1, bookid);
pstmt.setString(2, bookName);
pstmt.setInt(3, price);
int result = pstmt.executeUpdate();
pstmt.close();
System.out.println("操作成功");
} catch (SQLException e){
e.printStackTrace();
}
finally
{
try
{
if(null != conn)
{
conn.close();
}
}
catch (SQLException e){
e.printStackTrace();
}
}
}
public static void batchInsertBook()
{
//构建Java和数据库之间的桥梁介质
try{
Class.forName("com.mysql.jdbc.Driver");
System.out.println("注册驱动成功!");
}catch(ClassNotFoundException e1){
System.out.println("注册驱动失败!");
e1.printStackTrace();
}
String url="jdbc:mysql://localhost:3306/test?allowMultiQueries=true";
Connection conn = null;
try {
//构建Java和数据库之间的桥梁:URL,用户名,密码
conn = DriverManager.getConnection(url, "root", "123456");
String sql = "insert into t_book(bookid,bookname,price) values(?,?,?)";
//构建数据库执行者
PreparedStatement pstmt = conn.prepareStatement(sql);
//执行SQL语句
String bookName = "aaaaaaaaaaaaaaaa";
int price = 50;
//values(1, 'Effective Java', 50)
for(int i=200;i<210;i++)
{
pstmt.setInt(1, i);
pstmt.setString(2, bookName);
pstmt.setInt(3, price);
pstmt.addBatch();
}
pstmt.executeBatch();
pstmt.close();
System.out.println("操作成功");
} catch (SQLException e){
e.printStackTrace();
} finally {
try {
if(null != conn) {
conn.close();
}
}
catch (SQLException e){
e.printStackTrace();
}
}
}
}
如果有大量的 sql 语句,他们结构相同,仅在具体数值上有差别,那么可以通过 addBatch 方法进行批量操作。这样会提高性能,减少数据库负担。
ResultSetMetaData
基础知识
- ResultSet可以用来承载所有的select语句返回的结果集
- ResultSetMetaData来获取ResultSet返回的属性(如,每一行的名字类型等)
- getColumnCount(),返回结果的列数
- getColumnClassName(i),返回第i列的数据的Java类名
- getColumnTypeName(i),返回第i列的数据库类型名称
- getColumnType(i),返回第i列的SQL类型
- 使用ResultSetMetaData解析ResultSet
示例代码
import java.sql.*;
public class ResultSetMetaDataTest {
public static void main(String[] args){
//构建Java和数据库之间的桥梁介质
try{
Class.forName("com.mysql.jdbc.Driver");
System.out.println("注册驱动成功!");
}catch(ClassNotFoundException e1){
System.out.println("注册驱动失败!");
e1.printStackTrace();
return;
}
String url="jdbc:mysql://localhost:3306/test";
Connection conn = null;
try {
//构建Java和数据库之间的桥梁:URL,用户名,密码
conn = DriverManager.getConnection(url, "root", "123456");
//构建数据库执行者
Statement stmt = conn.createStatement();
System.out.println("创建Statement成功!");
//执行SQL语句并返回结果到ResultSet
ResultSet rs = stmt.executeQuery("select bookid, bookname, price from t_book order by bookid");
//获取结果集的元数据
ResultSetMetaData meta = rs.getMetaData();
int cols = meta.getColumnCount();
for(int i=1;i<=cols;i++)
{
System.out.println(meta.getColumnName(i) + "," + meta.getColumnTypeName(i));
}
rs.close();
stmt.close();
} catch (SQLException e){
e.printStackTrace();
}
finally
{
try
{
if(null != conn)
{
conn.close();
}
}
catch (SQLException e){
e.printStackTrace();
}
}
}
}
运行结果如下:
数据库连接池
享元模式(Flyweight Pattern)
- 经典23个设计模式的一种,属于结构型模式。
- 一个系统中存在大量的相同的对象,由于这类对象的大量使用,会造成系统内存的耗费,可以使用享元模式来减少系统中对象的数量。
- Connection是Java和数据库两个平行系统的桥梁
桥梁构建不易,成本很高,单次使用成本昂贵
- 运用共享技术来实现数据库连接池(享元模式)
- 降低系统中数据库连接Connection对象的数量
- 降低数据库服务器的连接响应消耗
- 提高Connection获取的响应速度
数据库连接池
- 理解池Pool的概念
- 初始数、最大数、增量、超时时间等参数。
- 常用的数据库连接池
- DBCP (Apache, http://commons.apache.org/,性能较差)
- C3P0 (https://www.mchange.com/projects/c3p0/)
- Druid (Alibaba, https://github.com/alibaba/druid)
C3P0连接池
<default-config> <!-- 默认配置 -->
<property
name="driverClass">com.mysql.jdbc.Driver</property>
<property
name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
- driverClass 驱动class,这里为mysql的驱动
- jdbcUrl jdbc 链接
- user password数据库用户名密码
- initialPoolSize 初始数量:一开始创建多少条链接
- maxPoolSize 最大数:最多有多少条链接
- acquireIncrement 增量:用完每次增加多少个
- maxIdleTime最大空闲时间:超出的链接会被抛弃
示例代码
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>MOOC19-04</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>14</maven.compiler.source>
<maven.compiler.target>14</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
</dependencies>
</project>
main
import java.sql.*;
public class SelectTest {
public static void main(String[] args){
Connection conn = null;
try {
//从c3p0获取
//conn = C3p0Factory1.getConnection();
//conn = C3p0Factory2.getConnection();
//从Druid获取
//conn = DruidFactory1.getConnection();
conn = DruidFactory2.getConnection();
//构建数据库执行者
Statement stmt = conn.createStatement();
System.out.println("创建Statement成功!");
//执行SQL语句并返回结果到ResultSet
ResultSet rs = stmt.executeQuery("select bookid, bookname, price from t_book order by bookid");
//开始遍历ResultSet数据
while(rs.next())
{
System.out.println(rs.getInt(1) + "," + rs.getString(2) + "," + rs.getInt("price"));
}
rs.close();
stmt.close();
} catch (Exception e){
e.printStackTrace();
} finally {
try {
if(null != conn) {
conn.close();
}
} catch (SQLException e){
e.printStackTrace();
}
}
}
}
C3p0
c3p0-config
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config> <!-- 默认配置 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
</c3p0-config>
C3p0Factory1
import java.sql.Connection;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3p0Factory1 {
private static ComboPooledDataSource dataSource = null;
public static void init() throws Exception {
dataSource = new ComboPooledDataSource();
dataSource.setDriverClass( "com.mysql.jdbc.Driver" );
dataSource.setJdbcUrl( "jdbc:mysql://localhost:3306/test" );
dataSource.setUser("root");
dataSource.setPassword("123456");
// the settings below are optional -- c3p0 can work with defaults
dataSource.setMinPoolSize(5);
dataSource.setAcquireIncrement(5);
dataSource.setMaxPoolSize(20);
// The DataSource dataSource is now a fully configured and usable pooled DataSource
}
public static Connection getConnection() throws Exception {
if(null == dataSource)
{
init();
}
return dataSource.getConnection();
}
}
C3p0Factory2
import java.sql.Connection;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3p0Factory2 {
private static ComboPooledDataSource dataSource = null;
public static void init() throws Exception {
dataSource = new ComboPooledDataSource();
//dataSource 自动加载c3p0-config.xml文件
// The DataSource dataSource is now a fully configured and usable pooled DataSource
}
public static Connection getConnection() throws Exception {
if(null == dataSource)
{
init();
}
return dataSource.getConnection();
}
}
Druid
druid.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test
username=root
password=123456
filters=stat
initialSize=2
maxActive=300
maxWait=60000
timeBetweenEvictionRunsMillis=60000
minEvictableIdleTimeMillis=300000
validationQuery=SELECT 1
testWhileIdle=true
testOnBorrow=false
testOnReturn=false
poolPreparedStatements=false
maxPoolPreparedStatementPerConnectionSize=200
DruidFactory1
import java.sql.Connection;
import com.alibaba.druid.pool.DruidDataSource;
public class DruidFactory1 {
private static DruidDataSource dataSource = null;
public static void init() throws Exception {
dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("123456");
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test");
dataSource.setInitialSize(5);
dataSource.setMinIdle(1);
dataSource.setMaxActive(10);
// 启用监控统计功能 dataSource.setFilters("stat");//
}
public static Connection getConnection() throws Exception {
if(null == dataSource)
{
init();
}
return dataSource.getConnection();
}
}
DruidFactory2
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
public class DruidFactory2 {
private static DruidDataSource dataSource = null;
public static void init() throws Exception {
Properties properties = new Properties();
InputStream in = DruidFactory2.class.getClassLoader().getResourceAsStream("druid.properties");
properties.load(in);
dataSource = (DruidDataSource)DruidDataSourceFactory.createDataSource(properties);
in.close();
}
public static Connection getConnection() throws Exception {
if(null == dataSource)
{
init();
}
return dataSource.getConnection();
}
}
学习过程中遇到的问题
练习
假设数据库有一张表t_mail (id, from, to, subject, content), 里面存储着具体的邮件发件人、收件人、标题和内容。采用Druid连接池,读取id为1的记录,并基于Java Mail将该邮件发送出来。
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class DoIt {
public static void main(String[] args){
Connection conn = null;
try {
//从Druid获取
conn = DruidFactory1.getConnection();
System.out.println("连接池构建成功!");
//构建数据库执行者
Statement stmt = conn.createStatement();
System.out.println("创建Statement成功!");
//执行SQL语句并返回结果到ResultSet
ResultSet rs = stmt.executeQuery("select * from t_mail where id = 1");
//开始遍历ResultSet数据
while(rs.next())
{
System.out.println("获取数据成功");
// 发送邮件
MailSend ms = new MailSend(rs.getString("from"), rs.getString("to"), rs.getString("subject"),
rs.getString("content"));
ms.init();//初始化
ms.sendMessage();//发送邮件
ms.close();
}
rs.close();
stmt.close();
} catch (Exception e){
e.printStackTrace();
} finally {
try {
if(null != conn) {
conn.close();
}
} catch (SQLException e){
e.printStackTrace();
}
}
}
}
import java.sql.Connection;
import com.alibaba.druid.pool.DruidDataSource;
public class DruidFactory1 {
private static DruidDataSource dataSource = null;
public static void init() throws Exception {
dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("123456");
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test");
dataSource.setInitialSize(5);
dataSource.setMinIdle(1);
dataSource.setMaxActive(10);
// 启用监控统计功能 dataSource.setFilters("stat");//
}
public static Connection getConnection() throws Exception {
if(null == dataSource)
{
init();
}
return dataSource.getConnection();
}
}
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.*;
public class MailSend {
private Session session;
private Transport transport;
private String from;
private String to;
private String subject;
private String content;
private String password = "";//授权码
private String smtpServer = "smtp.qq.com";
public MailSend(String from, String to, String subject, String content) {
this.from = from;
this.to = to;
this.subject = subject;
this.content = content;
}
public void init()throws Exception
{
//设置属性
Properties props = new Properties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.class", "com.sun.mail.smtp.SMTPTransport");
props.put("mail.smtp.host", smtpServer); //设置发送邮件服务器
props.put("mail.smtp.port", "25");
props.put("mail.smtp.auth", "true"); //SMTP服务器需要身份验证
// 创建Session对象
session = Session.getInstance(props,new Authenticator(){ //验账账户
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(from, password);
}
});
session.setDebug(true); //输出跟踪日志
// 创建Transport对象
transport = session.getTransport();
}
public void sendMessage() throws Exception {
//创建一个邮件
// 创建Session实例对象
Session session = Session.getDefaultInstance(new Properties());
// 创建MimeMessage实例对象
MimeMessage message = new MimeMessage(session);
// 设置发件人
message.setFrom(new InternetAddress(from));
// 设置收件人
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
// 设置发送日期
message.setSentDate(new Date());
// 设置邮件主题
message.setSubject(subject);
// 设置纯文本内容的邮件正文
message.setText(content);
// 保存并生成最终的邮件内容
message.saveChanges();
//发送邮件
transport.connect();
transport.sendMessage(message, message.getAllRecipients());
//打印结果
System.out.println("发送邮件成功");
}
public void close()throws Exception
{
transport.close();
}
}