Java14---JDBC封装优化,ORM思想

导读

1.PreparedStatement
2.封装优化
3.ORM思想

PreparedStatement

–是Statement的子接口
特点:可以设定参数,把带参数的SQL语句先传过去,再设置对应参数的值传过去执行

较Statement来看,PreparedStatement的变化主要在第三,第四步骤

第三步,创建PreparedStatement,传入带参数的SQL语句
	对于变化的数值,可以参数化,用?做占位符占位
	String sql = "INSERT INTO t_user (id,username,password,sex,"
				+ "id_number,tel,addr) "
				+ "VALUES(t_user_id_seq.NEXTVAL,?,?,?,?,?,?)";

	PreoareStatement pstmt=conn.prepareStatement(sql);

第四步,执行SQL语句
	1)先设置占位符的值,发过去值执行SQL语句
	每一个问号对应一个索引,从1开始,语句按照从左到右的顺序
	pstmt.setXXX(索引,对应的值);
	
	2)执行,注意不要再次传入SQL语句了
	int rows = pstmt.executeUpdate();
	

PreparedStatement vs Statement

直观看:
利用PreparedStatement不需要拼接,不需要关心单引号的问题
先传带参数的SQL语句
在传参数执行

利用Statement利用拼接,注意文本型要加单引号拼接
把完整的拼接后的语句传过去执行
效率看:
如果添加1个学生,Statement相对快一点(后者只传一次)
如果添加100个学生,
	对于Statement,循环第四步,发送100次语句过去,都不相同
		对于一个语法,发送过去需要先编译处理,再执行,编译100次		
	对于Preparedstatement,循环第四步,发送100次参数值过去,语句是一样的
		对于带参数的语句,先预编译,只要预编译1次,执行100次,相对效率高一点
从安全角度来看:
	需求:登录时,通过用户名和密码查找一个用户
	Statement:
	"SELECT id,username,password,sex FROM t_user WHERE username="+username+" and password='"+password+"'";
	
	PreparedStatement:
	"SELECT id,username,password,sex FROM t_user WHERE username=? and password=?";

假如:用户名:aa
     密码:111
	 结果一致
	 
假如:用户名:aa
     密码:"111' OR '1'='1"
	 Statement中枪,可以查到所有的用户信息
	 PreparedSatement直接报错,不允许设置

PreparedStatement更安全

PreparedStatement可以替代Statement,我们推荐使用PreparedSatement

封装优化

1.封装第一,二步

自创类ConnectionFactory实现

package com.hala.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * Connection工厂类
 * 利用这个类获取连接的数据库对象
 * @author air
 *
 */
public class ConnectionFactory {

	private static final String DRIVER="oracle.jdbc.driver.OracleDriver";

	public static Connection getConnection(){
		//这里把声明放在try{}里边的话成为局部变量,会报错
		Connection conn=null;
		try {
			Class.forName(DRIVER);
			conn=DriverManager.getConnection(
					"jdbc:oracle:thin:@localhost:1521:XE",
					"easybuy",
					"easybuy");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return conn;
	}
}

替换
Connection conn=ConnectionFactory.getConnection();

注意:这里有两种优化思想
(1)将常量抽出为private static final 属性,便于使用改动
(2)将这些常量存在一个配置文件中,在ConnectionFactory所在的包下创建一个properties文件

properties:属性文件(不能带引号,否则引号也作为有效的一部分)
			键值对
			key=value
			key=value
			key=value
		Java中:Properties类,集合类,存储键值对
			这个类对象可以从properties文件中加载数据,把所有的键值对
			加载到内存对象中

jdbcinfo.properties

driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:XE
username=easybuy
userpassword=easybuy

怎样获取文件中的键值对来使用呢?
->更改后的 ConnectionFactory.java

package com.hala.jdbc;

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

/**
 * Connection工厂类
 * 利用这个类获取连接的数据库对象
 * @author air
 *
 */
public class ConnectionFactory {
	//用来存储从文件中获得的值
	private static String DRIVER;
	private static String URL;
	private static String USERNAME;
	private static String USERPASSWORD;
	
	
	//利用静态代码块实现,在类加载时执行,只会执行一次
	static{
		//1.创建一个Properties对象
		Properties prop=new Properties();
	
		try {
			//2.加载properties文件的数据,这种写法只能对同包下的文件获取一个字节流
			//加载后prop里边就有了文件里边的键值对
			prop.load(ConnectionFactory.class.
					getResourceAsStream("jdbcinfo.properties"));
			//3.通过键获取对应的值,注意大小写
			DRIVER=prop.getProperty("driver");
			URL=prop.getProperty("url");
			USERNAME=prop.getProperty("username");
			USERPASSWORD=prop.getProperty("userpassword");
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	public static Connection getConnection(){
		//这里把声明放在try{}里边的话成为局部变量,会报错
		Connection conn=null;
		try {
			Class.forName(DRIVER);
			conn=DriverManager.getConnection(URL,USERNAME,USERPASSWORD);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return conn;
	}
}

2.释放资源:自创一个类实现

package com.hala.jdbc;

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

/**
 * 释放资源
 * @author air
 *
 */
public class DBUtils {
	//这里PreparedStatement是Statement的子接口,所以这里用Statement即可
	public static void close(ResultSet rs,Statement stmt,Connection conn){
		if(rs!=null){
			try {
			rs.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		}
		
		if(stmt!=null){
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			}
		
		if(conn!=null){
			try {
			conn.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		}
	}

}

替换
DBUtils.close(rs,stmt,conn);

ORM思想

Object/Relational Mapping
java对象<---->数据库映射

对象模型        			关系模型
实体类(pojo)	  			表
属性              		列(字段)	
OID				  		主键
对象              		记录
实体类之间的关联关系        外键
一对一
映射到Java中:
Person		Passport
id           id
name         ...
Passport     Person

Person中含有Passport属性,Passport属性也含有Person属性
一对多
Order (订单)             OrderDetail(订单明细)
List<OrderDetail>  			Order
Order中含有List<OrderDetail> 属性,OrderDetail含有Order	属性
多对多
Teacher           Student
List<Student>     List<Teacher>

ORM思想其实本质就是将两个类相互关联起来

实例:
定义一个方法,
	查询一个订单,及其对应的明细并返回
	要求,返回订单对象,里面包含对应的明细集合对象

分步操作:
1.定义一个OrderJDBC类,
		定义 Order getOrder(long id){}
		
2.定义一个OrderDetailJDBC类,
		定义 List<OrderDetail> getDetails(long orderId){}
		
3.定义一个方法,
	查询一个订单,及其对应的明细并返回
	要求,返回订单对象,里面包含对应的明细集合对象
	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值