jdbc学习
来源:互联网 发布:家电维修软件 编辑:程序博客网 时间:2024/06/14 21:00
1.使用java代码发送sql语句的技术,就是jdbc技术。
2.使用jdbc发送sql的前提
首先需要
登录数据库服务器(连接数据库服务器)
数据库的IP地址
端口
数据库用户名
密码
//建立数据库连接的代码
public class TestJDBC1 {
//连接数据库的配置
private String url="jdbc:mysql://localhost:3306/test";
private String user="root";
private String password="123456";
//方法一
@Test
public void test1() throws SQLException{
Driver driver = new Driver();
Properties properties = new Properties();
properties.setProperty("user", user);
properties.setProperty("password", password);
Connection conn = driver.connect(url,properties);
System.out.println(conn);
}
@Test
public void test2() throws SQLException{
//新建Driver方法时,内部有注册驱动程序的静态代码块
Driver driver = new Driver();
//注册驱动程序(可以注册多个)
//DriverManager.registerDriver(driver);
//连接到具体的数据库
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println(conn);
}
//推荐使用
@Test
public void test3() throws Exception{
//通过得到字节码对象的方式加载静态代码块,从而注册驱动程序
Class.forName("com.mysql.jdbc.Driver");
//连接到具体的数据库
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println(conn);
}
}
JDBC接口核心的API
java.sql.* 和 javax.sql.*
|-Driver接口: 表示java驱动程序接口。所有的具体的数据库厂商要来实现此接口。
|-connect(url, properties): 连接数据库的方法。
url:连接数据库的URL
URL语法: jdbc协议:数据库子协议://主机:端口/数据库
user:数据库的用户名
password:数据库用户密码
|-DriverManager类: 驱动管理器类,用于管理所有注册的驱动程序
|-registerDriver(driver) : 注册驱动类对象
|-ConnectiongetConnection(url,user,password); 获取连接对象
|-Connection接口: 表示java程序和数据库的连接对象。
|-Statement createStatement() : 创建Statement对象
|-PreparedStatement prepareStatement(String sql) 创建PreparedStatement对象
|-CallableStatement prepareCall(String sql) 创建CallableStatement对象
|-Statement接口: 用于执行静态的sql语句
|-int executeUpdate(String sql) :执行静态的更新sql语句(DDL,DML)
|-ResultSet executeQuery(String sql) :执行的静态的查询sql语句(DQL)
|-PreparedStatement接口:用于执行预编译sql语句
|- int executeUpdate() :执行预编译的更新sql语句(DDL,DML)
|-ResultSet executeQuery() : 执行预编译的查询sql语句(DQL)
|-CallableStatement接口:用于执行存储过程的sql语句(call xxx)
|-ResultSetexecuteQuery() :调用存储过程的方法
|-ResultSet接口:用于封装查询出来的数据
|-boolean next() : 将光标移动到下一行
|-getXX(): 获取列的值
创建statement执行sql语句
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url, user, password);
stmt = conn.createStatement();
String sql = "insert into testjdbc(name,password) values ('李四','5201314')";
int count = stmt.executeUpdate(sql);
当执行查询语句时返回ResultSet,遍历集合
//遍历结果
while(rs.next()){
int id =rs.getInt("id");
String name = rs.getString("name");
String gender = rs.getString("gender");
System.out.println(id+","+name+","+gender);
}
创建preparestatement执行sql语句
//1.获取连接
conn = JdbcUtil.getConnection();
//2.准备预编译的sql
String sql ="INSERT INTO student(NAME,gender) VALUES(?,?)";//?表示一个参数的占位符
//3.执行预编译sql语句(检查语法)
stmt = conn.prepareStatement(sql);
//4.设置参数值
/**
*参数一:参数位置 从1开始
*/
stmt.setString(1,"李四");
stmt.setString(2,"男");
//5.发送参数,执行sql
int count =stmt.executeUpdate();
PreparedStatement vs Statment
1)语法不同:PreparedStatement可以使用预编译的sql,而Statment只能使用静态的sql
2)效率不同: PreparedStatement可以使用sql缓存区,效率比Statment高
3)安全性不同: PreparedStatement可以有效防止sql注入,而Statment不能防止sql注入。
CallableStatement执行存储过程//获取连接
conn = JdbcUtil.getConnection();
//准备sql
String sql ="CALL pro_findById(?)";//可以执行预编译的sql
//预编译
stmt = conn.prepareCall(sql);
//设置输入参数
stmt.setInt(1, 6);
//发送参数
rs = stmt.executeQuery();//注意:所有调用存储过程的sql语句都是使用executeQuery方法执行!!!
//遍历结果
while(rs.next()){
int id =rs.getInt("id");
String name = rs.getString("name");
String gender = rs.getString("gender");
System.out.println(id+","+name+","+gender);
}
执行带有输出参数的存储过程
//获取连接
conn = JdbcUtil.getConnection();
//准备sql
String sql = "CALL pro_findById2(?,?)";//第一个?是输入参数,第二个?是输出参数
//预编译
stmt = conn.prepareCall(sql);
//设置输入参数
stmt.setInt(1, 6);
//设置输出参数(注册输出参数)
/**
* 参数一:参数位置
* 参数二:存储过程中的输出参数的jdbc类型 VARCHAR(20)
*/
stmt.registerOutParameter(2,java.sql.Types.VARCHAR);
//发送参数,执行
stmt.executeQuery(); //结果不是返回到结果集中,而是返回到输出参数中
//得到输出参数的值
/**
* 索引值:预编译sql中的输出参数的位置
*/
String result = stmt.getString(2);//getXX方法专门用于获取存储过程中的输出参数
System.out.println(result);
使用properties配置文件配置信息时,关于配置文件的路径问题 Properties properties = new Properties();
//这种读取方法在web项目中不可用,.代表的路径不一致
// FileInputStream inputStream = new FileInputStream("./src/db.properties");
//使用类路径的读取方式
/*/:斜杠代表classpath的根目录
在java项目中,classpath的根目录是从bin目录开始的
在web项目中,classpath的根目录是从WEB-INF/classes目录开始的*/
//只要配置文件都放在根目录src下,都能读取到
InputStream inputStream = JdbcUtil.class.getResourceAsStream("/db.properties");
properties.load(inputStream);
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");
driverClass = properties.getProperty("driverClass");
Class.forName(driverClass);
定义一个存储过程
//2. 自定义日期类型转换器
@Test
publicvoid test2()throws Exception {
//模拟表单数据
String name ="jack";
String age ="20";
String birth ="1995-12-26";
//对象
Admin admin =new Admin();
//注册日期类型转换器:1,自定义的方式
ConvertUtils.register(new Converter() {
//转换的内部实现方法,需要重写
@Override
public Object convert(Class type, Object value) {
//判断
if (type != Date.class) {
return null;
}
if (value ==null ||"".equals(value.toString().trim())) {
return null;
}
try {
//字符串转换为日期
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd");
return sdf.parse(value.toString());
} catch (ParseException e) {
thrownew RuntimeException(e);
}
}
},Date.class);
//把表单提交的数据,封装到对象中
BeanUtils.copyProperty(admin,"userName", name);
BeanUtils.copyProperty(admin,"age", age);
BeanUtils.copyProperty(admin,"birth", birth);
//------测试------
System.out.println(admin);
}
使用自带的日期类型转换器
// 注册日期类型转换器:2,使用组件提供的转换器工具类
ConvertUtils.register(new DateLocaleConverter(), Date.class);
(SimpleDateFormat字符串时间和时间格式的转换)
//将日期格式转字符串用format,将字符串转日期格式用parse
ublic static void main(String[] args) throws ParseException {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String formatdate = sdf.format(date);
System.out.println(formatdate);
String oridate="1995-12-26 12:24:56";
Date date2 = parse(oridate);
System.out.println(date2);
}
public static Date parse(String oridate){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date=null;
try {
date = sdf.parse(oridate);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return date;
}
事务编程
事务的特性:
原子性,是一个最小逻辑操作单元 !
一致性,事务过程中,数据处于一致状态。
持久性, 事务一旦提交成功,对数据的更改会反映到数据库中。
隔离性, 事务与事务之间是隔离的。
|-- Connection
voidsetAutoCommit(boolean autoCommit) ; 设置事务是否自动提交
如果设置为false,表示手动提交事务。
void commit() (); 手动提交事务
void rollback() ; 回滚(出现异常时候,所有已经执行成功的代码需要回退到事务开始前的状态。)
SavepointsetSavepoint(String name) 回滚到指定的点con.setAutoCommit(false);
//设置回滚点
sp =con.setSavepoint();
con.rollback(sp);
con.commit();
==和equals方法的比较
当使用 == 来判断两个变量是否相等时,如果两个变量是基本类型变量,且都是数值类型(不一定要求数据类型严格相同),则只要两个变量的值相等,就返回true。
但是对于两个引用类型变量,只有它们指向同一个对象时, == 判断才会返回true。 == 不可用于比较类型上没有父子关系的两个对象。
只要两个字符串所包含的字符序列相同,通过equals()比较将返回true,否则返回 false。
BeanUtils组件
简介
程序中对javabean的操作很频繁,所以apache提供了一套开源的api,方便对javabean的操作!即BeanUtils组件。
BeanUtils组件, 作用是简化javabean的操作!
使用BeanUtils组件:
1. 引入commons-beanutils-1.8.3.jar核心包
2. 引入日志支持包: commons-logging-1.1.3.jar
实例, 基本用法
方法1:对象属性的拷贝
BeanUtils.copyProperty(admin,"userName", "jack");
BeanUtils.setProperty(admin,"age", 18);
方法2:对象的拷贝
BeanUtils.copyProperties(newAdmin,admin);
方法3: map数据拷贝到javabean中
【注意:map中的key要与javabean的属性名称一致】
BeanUtils.populate(adminMap,map);
//对于map数据的拷贝
map数据,拷贝到对象中
Admin adminMap = new Admin();
Map<String,Object> map =new HashMap<String,Object>();
map.put("userName","Jerry");
map.put("age", 29);
//注意:map中的key要与javabean的属性名称一致
BeanUtils.populate(adminMap, map);
//自定义通用的方法
//通用的update语句
public void update(String sql,Object[] params){
Connection conn=null;
PreparedStatement prestmt=null;
try {
conn = JdbcUtil.getConnection();
prestmt = conn.prepareStatement(sql);
int count = prestmt.getParameterMetaData().getParameterCount();
for(int i=0;i<count;i++){
prestmt.setObject(i+1, params[i]);
}
prestmt.executeUpdate();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JdbcUtil.close(prestmt, conn);
}
}
//通用的query方法
public <T> List<T> query(String sql,Object[] params,Class<T> clazz) {
Connection conn=null;
PreparedStatement prestmt=null;
ResultSet rs=null;
List<T> list=new ArrayList<T>();
T t=null;
try {
conn = JdbcUtil.getConnection();
prestmt = conn.prepareStatement(sql);
int count = prestmt.getParameterMetaData().getParameterCount();
for(int i=0;i<count;i++){
prestmt.setObject(i+1, params[i]);
}
rs = prestmt.executeQuery();
//获取元数据
ResultSetMetaData rsmd = rs.getMetaData();
//获取行数
int columnCount = rsmd.getColumnCount();
while(rs.next()){
t=clazz.newInstance();
//通过行获得列名
for(int i=0;i<columnCount;i++){
String columnName = rsmd.getColumnName(i+1);
//列名和属性名一致,通过属性名得到对应的值
Object value = rs.getObject(columnName);
//封装到T中
BeanUtils.setProperty(t, columnName, value);
}
//将T添加到集合中
list.add(t);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JdbcUtil.close(prestmt, conn, rs);
}
return list;
}
DbUtils组件
l commons-dbutils 是Apache 组织提供的一个开源JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很多不喜欢hibernate的公司的首选。
DbUtils组件,
1. 简化jdbc操作
2. 下载组件,引入jar文件 : commons-dbutils-1.6.jar
实例
|-- DbUtils 关闭资源、加载驱动
|-- QueryRunner 组件的核心工具类:定义了所有的与数据库操作的方法(查询、更新)
Int update(Connection conn, String sql,Object param); 执行更新带一个占位符的sql
Int update(Connection conn,String sql, Object… param); 执行更新带多个占位符的sql
Int[] batch(Connection conn,String sql, Object[][] params) 批处理
T query(Connectionconn ,String sql, ResultSetHandler<T> rsh, Object... params) 查询方法
Int update( String sql,Object param);
Int update( String sql,Object… param);
Int[] batch( String sql, Object[][]params)
//批量查询的实例
@Test
public void test() {
conn=JdbcUtil.getConnection();
String sql="INSERT INTO admin(name,password) VALUES(?,?)";
QueryRunner qr = new QueryRunner();
try {
qr.batch(conn, sql, new Object[][]{{"bob","123"},{"cherry","123"}});
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
DbUtils.close(conn);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
注意:如果调用DbUtils组件的操作数据库方法,没有传入连接对象,那么在实例化QueryRunner对象的时候需要传入数据源对象: QueryRunner qr = new QueryRunner(ds);
DbUtils提供的封装结果的一些对象:
1) BeanHandler: 查询返回单个对象
2) BeanListHandler: 查询返回list集合,集合元素是指定的对象
3) ArrayHandler, 查询返回结果记录的第一行,封装对对象数组,即返回:Object[]
4) ArrayListHandler, 把查询的每一行都封装为对象数组,再添加到list集合中
5) ScalarHandler 查询返回结果记录的第一行的第一列 (在聚合函数统计的时候用)
6) MapHandler 查询返回结果的第一条记录封装为map
实例:
conn=JdbcUtil.getConnection();
String sql="SELECT * FROM admin WHERE name=? AND password=?";
QueryRunner qr = new QueryRunner();
String flag=null;
try {
//查询结果用集合返回
//List<Admin> list = qr.query(conn, sql, new BeanListHandler<Admin>(Admin.class), admin.getName());
Admin admin2 = qr.query(conn, sql, new BeanHandler<Admin>(Admin.class),new Object[]{admin.getName(),admin.getPassword()});
if(admin2!=null){
flag="登录成功";
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return flag;
传入集合的声明方法:
new Object[]{admin.getPassword(),admin.getName()}
new Object[][]{{"bob","123"},{"cherry","123"}}
- jdbc学习
- JDBC学习
- JDBC学习
- jdbc 学习
- JDBC学习
- JDBC学习
- jdbc学习
- JDBC学习
- JDBC学习
- JDBC学习
- JDBC学习
- JDBC学习
- jdbc学习
- JDBC学习
- jdbc学习
- jdbc学习
- jdbc学习
- jdbc学习
- [Panads数据分析-02]Pandas数据结构之DataFrame
- 51nod1394 差和问题
- MFC下常用曲线控件
- Mockito 2.1.0 Mock Fianl类的原理
- 资料分享
- jdbc学习
- 设计模式--策略模式
- PAT (Basic Level) Practise (中文)1062. 最简分数(20)
- 吐槽天猫精灵链接不上网络
- 猜拳游戏
- HashMap 源码分析 -- entrySet()
- springcloud和dubbo微服务架构图
- python学习笔记——字符串操作
- 深夜沐月幻想乡——逝月镜夜【前篇】