JDBC操作数据库
JDBC操作数据库
一、JDBC的概念
JDBC:JavaDataBaseConnection:通过java代码操作数据库。可以把JDBC看成一个操作Mysql的一个客户端。
JDBC使用步骤:
1、加载mysql的驱动类:mysql-connector-java-5.1.7-bin.jar。
2、建立数据库与JAVA之间的连接:DriverManager.getConnection(url, user, password);url是数据库连接地址:jdbc:mysql://localhost:3306/数据库名。此处连得是本机。user是用户名,password是数据库登录密码。
3、通过Connection对象创建Statement对象,conn.createStatement();
4、通过Statement发送SQL语句,executeUpdate():只能发送DML语句,executeQuery();可以执行DQL语句。
代码如下:
public class JDBCDemo1 {
//数据库连接地址:
//jdbc:mysql://mysql's ip:3306/数据库名
private static String url
= "jdbc:mysql://127.0.0.1:3306/ph";
private static String user = "j180703";
private static String password = "123456";
//驱动类名
private static String driverClassName
= "com.mysql.jdbc.Driver";
/**
* 创建数据库连接,并返回该连接对象
* @return 连接对象
*/
public static Connection getConnection(){
//DriverManager负责安装数据库驱动
Connection conn = null;
try {
//加载com.mysql.jdbc.Driver类到JVM
Class.forName(driverClassName);
//通过DriverManager创建数据库连接
conn = DriverManager.getConnection(
url, user, password);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
/**
* 向学生表插入一行记录,使用DML语句
* @param args
*/
public static void insertDemo(){
try {
//1.获取连接
Connection conn = getConnection();
//2.通过Connection对象创建Statement对象
Statement stmt = conn.createStatement();
//3.编写sql语句
String sql = "insert into t_student " +
"values(null,'phooxx2b','男',28," +
"'2018-08-01','xxoo@163.com',1)";
//4.通过Statement发送SQL
//executeUpdate():只能发送DML语句
int result = stmt.executeUpdate(sql);
if(result!=1){
System.out.println("插入失败!");
}else{
System.out.println("插入成功!");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 查询学生表中的所有记录,使用的是DQL语句
*/
public static void queryDemo(){
try {
//1.获取连接
Connection conn = getConnection();
//2.通过Connection对象创建Statement对象
Statement stmt = conn.createStatement();
//3.编写sql
String sql = "select * from t_student";
//4.发送Sql
//发送DQL使用executeQuery(),返回值为ResultSet
//ResultSet结果集,该对象封装了查询结果
//ResultSet有行有列,它就是虚拟表
ResultSet rs = stmt.executeQuery(sql);
//取出ResultSet中的结果:
//一次取一行,循环去取,直到取完
//rs.next():判断是否有下一行,如果有直接取出
//相当于迭代器的hasNext()+next()
while(rs.next()){
//next()一次就取出了一行
//取一行中的各列值:
System.out.println(rs.getInt("student_id"));
System.out.println(rs.getString("student_name"));
System.out.println(rs.getString("sex"));
System.out.println("-----------");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Statement的缺点:
1、拼写sql容易出错
2、不能防止sql注入
因此开发中我们常用PreparedStatement来执行sql语句。(sql注入不懂的可以上网查查,在这里就不在细讲。)
使用PreparedStatement来进行数据库操作
public class DBUtil {
private static String url;
private static String user;
private static String password;
//驱动类名
private static String driverClassName ;
//static代码块会在类被JVM加载是立即执行
//读取db.properties文件,并给静态属性赋值
static{
//1、读取db.properties文件
//读取src以及同级目录下的文件
//1.1getClassLoader()获取config的classloader
//获取IO流
InputStream in = DBUtil.class.getClassLoader().
getResourceAsStream("db.properties");
//1.2创建properties对象
//专门读取.properties文件工具类
Properties prop = new Properties();
try {
//加载输入流
prop.load(in);
} catch (IOException e) {
e.printStackTrace();
}
//2、给静态属性赋值
url = prop.getProperty("jdbc.url");
user = prop.getProperty("jdbc.user");
password = prop.getProperty("jdbc.password");
driverClassName = prop.getProperty("jdbc.driverClassName");
}
/**
* 创建数据库连接,并返回该连接对象
* @return 连接对象
*/
public static Connection getConnection(){
//DriverManager负责安装数据库驱动
Connection conn = null;
try {
//加载com.mysql.jdbc.Driver类到JVM
Class.forName(driverClassName);
//通过DriverManager创建数据库连接
conn = DriverManager.getConnection(
url, user, password);
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
/**
* general:通用
* 封装一个通用增删改方法
* @param sql Object... params:占位符:
*Object... 表示参数个数不确定,但必须放在最后一个参数位置
*相当于一个数组
*/
public static int generalUpadate(String sql,Object... params){
int result = 0;
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = getConnection();
//此处执行sql语句,但占位符处值为空
pstmt = conn.prepareStatement(sql);
//给sql中的占位符赋值
if(params!=null){
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i+1, params[i]);
}
}
//将赋值过的占位符值传给sql语句
result = pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
closeAll(conn,pstmt,null);
}
return result;
}
/**
* 通用查询,可以查询任意表,可以把查询结果封装成任意对象
* Java类的属性名要和数据库的列名一致
* 因为是通过列名反射得到的属性名
* @param <X> 占位符,声明泛型
* @param cls 要封装对象的类对象
* @param sql 查询语句
* @param params sql语句中的占位符值:Object...
*/
public static <X> List<X> generalQuery(Class<X> cls,String sql,Object...params){
List<X> list = new ArrayList<>();
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = getConnection();
pstmt = conn.prepareStatement(sql);
//给sql中占位符赋值
if(params!=null){
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i+1, params[i]);
}
}
//将占位符的值传过去
rs = pstmt.executeQuery();
//如何获取列名
//ResultSetMetaData:封装了列的名和列的总数
ResultSetMetaData md = rs.getMetaData();
//获取列的总数
int columnCount = md.getColumnCount();
//md.getColumnName(column):通过列号获取列名
X x = null;
String columnName = null;
while(rs.next()){
//一行记录对应一个对象
x = cls.newInstance();
//给对象属性赋值
//获取列名,为反射做准备
//一行有很多列,列号从一开始
for (int i = 1; i <= columnCount; i++) {
columnName = md.getColumnName(i);
//取出一个列名,反射得到一个属性
try {
//1、获取父类类对象
Class<?> superCls = cls.getSuperclass();
if(superCls == Object.class){
//如果一个类无直接父类,那么该类属性全在本类中
throw new NoSuchFieldException();
}
Field superField = superCls.getDeclaredField(columnName);
//无异常表示属性属于父类,给属性赋值
superField.setAccessible(true);
superField.set(x, rs.getObject(i));
} catch (NoSuchFieldException e) {
// TODO: handle exception
// e.printStackTrace();
//抛出异常属性在子类中
Field childField = cls.getDeclaredField(columnName);
childField.setAccessible(true);
childField.set(x, rs.getObject(columnName));
}
}
//循环一次结束讲对象加到集合中
list.add(x);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
closeAll(conn, pstmt, rs);
}
return list;
}
/**
* 关闭资源
* Connection,Statement,ResultSet
*/
public static void closeAll(Connection conn,Statement stmt,ResultSet rs){
try {
//先开的后关
if(rs!=null){
rs.close();
}
if(stmt!=null){
stmt.close();
}
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
System.out.println(getConnection());
}
}