JDBC实例之—手机号码归属地查询(控制台版本)
JDBC基础入门学习小练习,实现控制台提示输入电话号码,输入完成回册后,打印电话号码归属地和运营商类型。
实现步骤
:
1. 编写手机号码归属地数据库文件解析程序,从文件中获得有效的字段(号码段对应的地区和运营商类型)。
2. 在mysql数据库中创建表(Table),采用Navicat Lite来创建表。
3. 将从数据库文件中解析出来字段按格式插入到mysql的表中,采用批量的方式来插,不然耗时太久。
4. 编写控制台程序,用于和用户交互读取输入的电话号码,并提取出前7位,在mysql查询结果集中进行遍历,如果查询到,则获取该行的地区和运营商类型,然后输出,如果没有查询到输出“未知号码”。
1. 查询功能实现,在查询之前,数据库中的表已经插入了数据了。 主程序代码:
import java.util.*;
import java.sql.*;
/**
* 主程序,完成控制台输入,数据查询,遍历比较,控制台输出
* */
public class PhoneNumberQuery
{
public static void main(String[] args)
{
//控制台输入
Scanner in = new Scanner(System.in);
String inPhoneNumber = null; //输入的电话号码
//输出
String strPhoneNumber = null;
String strArea = null; //输出号码归属地
String strMobileType = null; //输出运营商类型
//SQL查询语句
String sql = "Select * from T_PhoneNumber";
//创建数据库连接
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
//执行SQL查询
try
{
conn = JdbcUtils.getConnection(); //获得连接
ps = conn.prepareStatement(sql); //获得预编译的 SQL语句的对象
rs = ps.executeQuery(); //获得查询结果集
while(true)
{
System.out.print("请输入电话号码:");
//获取输入的电话号码,提取前7位
inPhoneNumber = in.nextLine();
inPhoneNumber = inPhoneNumber.substring(0, 7);
//从第一行开始遍历直到查询成功,或者遍历到最后一行
while(rs.next())
{
//从数据库查询结果集中获取电话号码前7位
strPhoneNumber = rs.getString("PhonePrefix");
//逐条和输入电话号码进行比较
if(strPhoneNumber.equals(inPhoneNumber))
{
//查询成功,获取地区和运营商类型字段
strArea = rs.getString("Area");
strMobileType = rs.getString("MobileType");
//退出遍历
break;
}
}
//如果查旬结果为空
if(strArea == null && strMobileType == null)
{
System.out.println("未知号码");
}
else
{
//查询成功输出信息
System.out.print(strArea + " ");
System.out.println(strMobileType);
}
//变量归零,进行下一次查询
strArea = null;
strMobileType = null;
inPhoneNumber = null;
rs.first(); //将结果集返回到第一行
}
}
catch(SQLException e)
{
e.printStackTrace();
}
finally
{
//资源关闭
JdbcUtils.closeQuietly(rs);
JdbcUtils.closeQuietly(ps);
JdbcUtils.closeQuietly(conn);
in.close();
}
}
}
运行效果:
2. 号码归属地数据库文件解析功能实现
实际上,在进行主程序查询前,已经创建了数据表,并插入了号码归属地数据,号码归属地文件解析,信息提取,批量插入等功能放在PhoneNumberPrase.java中,数据表创建的数据插入只需执行一次,则该表以后要以多次利用,所以这是一个单独的应用程序,实现代码如下:
import java.io.*;
import java.sql.*;
/**
* 解析号码归属地csv文件,提取有效信息,插入数据表中
*
* */
/**
* 号码归属地解析类,实现.CSV文件内容的解析,并插入到mysql数据中
* @author 樊文杰
* @version V0.1
* */
public class PhoneNumberPrase
{
public static InputStream csvFile = null;
public static InputStreamReader csvFileReader = null;
public static BufferedReader csvFileBufferReader = null;
/**
* 号码归属地数据源文件读取,返回输入流
* @param filePath csv文件源路径
* @return 文件流
* */
public static BufferedReader getCsvFileBuffer(String filePath) throws IOException
{
//字节读——>字符读——>缓冲读(行读)
csvFile = new FileInputStream(filePath);
csvFileReader = new InputStreamReader(csvFile);
csvFileBufferReader = new BufferedReader(csvFileReader);
return csvFileBufferReader;
}
public static void main(String[] args) throws SQLException
{
BufferedReader csvFileBuffer = null;
String line = null;
int count = 0;
//数据库连接和SQL语句预编译对像
Connection conn = null;
PreparedStatement pstmt = null;
//计算插入用时
long start = System.currentTimeMillis();
try
{
//从当前工作空间的src目录下读取数据文件
csvFileBuffer = getCsvFileBuffer("./src/PhoneNumbersDataBase.csv");
//丢弃第一行数据
csvFileBuffer.readLine();
//创建数据 连接,关闭连接默认的自动提交功能
conn = JdbcUtils.getConnection();
conn.setAutoCommit(false); //关闭自动提交
//获取SQL语句预编译的对像
pstmt = conn.prepareStatement("Insert into T_PhoneNumber(PhonePrefix,Area,MobileType) values(?,?,?)");
//读取CSV数据行,每2000行提交一次
while( (line = csvFileBuffer.readLine()) != null)
{
//分解一行字符串,然后进行处理得到有效数据
String[] segments = line.split(",");
String phonePrefix = segments[1].replace("\"", "");
String area = segments[2].replace("\"", "");
String yys = segments[3].replace("\"", "");
//清空参数集
pstmt.clearParameters();
//赋值
pstmt.setString(1, phonePrefix);
pstmt.setString(2, area);
pstmt.setString(3, yys);
pstmt.addBatch();
count ++;
//2000行批量更新一次
if(count%2000 == 0)
{
pstmt.executeBatch();
}
//System.out.printf("号码前缀:%s, %s, %s\n",phonePrefix,area,yys);
}
//得交剩余不足2000行的部分
pstmt.executeBatch();
//事物提交
conn.commit();
//结整时间,计算此过程用时
long end = System.currentTimeMillis();
System.out.println("执行成功,用时: " + (end - start) + " ms");
}
catch (IOException e)
{
// TODO 自动生成的 catch 块
e.printStackTrace();
}
catch (SQLException e)
{
//如果事物提交出错,则进行回滚
conn.rollback();
e.printStackTrace();
}
finally
{
//关闭资源,包括:IO流,JDBC的连接等
IOUtils.closeQuietly(csvFileBuffer);
JdbcUtils.closeQuietly(pstmt);
JdbcUtils.closeQuietly(conn);
}
}
}
3. 数据表插入实现, JDBC常用功能封装,包括: 加载驱动,创建连接,执行SQL语句并更新,查询结果集等,代码封装如下:
import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.util.Properties;
/**
* JAVA JDBC常用功能封装
* @author 樊文杰
* @version V0.1
* */
public class JdbcUtils
{
public static String driverName = null;
public static String dbUrl = null;
public static String dbUserName = null;
public static String dbPassWord = null;
/**
* 静态代码块,加载配置文件JdbcConfig.properties,读取MySQL配置信息,
* 然后加载驱动程序
*
* */
static{
InputStream inStream = null;
// 1.加载配置文件
try
{
inStream = JdbcUtils.class.getResourceAsStream("JdbcConfig.properties");
Properties props = new Properties();
props.load(inStream);
//提取配置文件中的相关字段
driverName = props.getProperty("drivername");
dbUrl = props.getProperty("dburl");
dbUserName = props.getProperty("dbusername");
dbPassWord = props.getProperty("dbpassword");
}
catch(IOException e)
{
throw new RuntimeException("加载JdbcConfig.properties出错",e);
}
finally{
if(inStream != null)
{
try
{
inStream.close();
}
catch(IOException e)
{
}
}
}
//2.加载驱动程序,驱动程序名由配置文件解析得到
try
{
Class.forName(driverName);
}
catch(ClassNotFoundException e)
{
System.out.println("驱动加载出错:" + e.getMessage());
}
}
/**
* 创建与数据库的连接
* @return 返回的连接
* */
public static Connection getConnection() throws SQLException
{
return DriverManager.getConnection(dbUrl,dbUserName,dbPassWord);
}
/**
* 在指定的连接上执行SQL语句并更新结果
* @param conn 指定的连接
* @param sql SQL语句
* @param parameters 可变参数列表
* @return 返回更新的条目
*/
public static int executeUpdate(Connection conn, String sql, Object ...parameters)
{
PreparedStatement ps = null;
try
{
//获得SQL语句预编译的结果存储对像
ps = conn.prepareStatement(sql);
for(int i = 0; i < parameters.length; i ++)
{
ps.setObject(i+1, parameters[i]);
}
return ps.executeUpdate();
}
catch(SQLException e)
{
System.out.println(e);
}
finally
{
closeQuietly(ps);
}
return -1;
}
/**
* 执行SQL语句并更新结果
* @param sql SQL语句
* @param parameters 可变参数列表
* @return 返回更新的条目
*/
public static int executeUpdate(String sql, Object ...parameters)
{
Connection conn = null;
//首先创建连接,然后再执行SQL语句
try
{
conn = getConnection();
return executeUpdate(conn,sql,parameters);
}
catch(SQLException e)
{
System.out.println(e);
}
finally
{
closeQuietly(conn);
}
return 0;
}
/**
* 在指定的连接上执行SQL查询并返回结果集
* @param conn 指定的连接
* @param sql SQL语句
* @param parameters 可变参数列表
* @return 返回结果集
*/
public static ResultSet executeQuery(Connection conn,String sql,
Object ...parameters) throws SQLException
{
//获取连接上SQL语句预编译对像
PreparedStatement ps = conn.prepareStatement(sql);
for(int i = 0; i < parameters.length; i ++)
{
ps.setObject(i+1, parameters[i]);
}
//执行查询
return ps.executeQuery();
}
public static ResultSet executeQuery(String sql, Object ...parameters)
throws SQLException
{
Connection conn = getConnection();
return executeQuery(conn,sql,parameters);
}
//关闭资源方法封装
public static void closeQuietly(ResultSet res)
{
if(res != null)
{
try{
res.close();
}
catch(SQLException e)
{
// do nothing
}
}
}
public static void closeQuietly(Connection conn)
{
if(conn != null)
{
try{
conn.close();
}
catch(SQLException e)
{
// do nothing
}
}
}
public static void closeQuietly(Statement stmt)
{
if(stmt != null)
{
try{
stmt.close();
}
catch(SQLException e)
{
// do nothing
}
}
}
public static void closeAll(ResultSet rs)
{
try
{
if(rs != null)
{
closeQuietly(rs.getStatement().getConnection());
closeQuietly(rs.getStatement());
closeQuietly(rs);
}
}
catch(SQLException e)
{
}
}
}