目录
1.模拟事务回滚
当Jdbc程序向数据库获得一个Connection对象时,默认情况下这个Connection对象会自动向数据库提交在它上面发送的SQL语句。若想关闭这种默认提交方式,让多条SQL在一个事务中执行可使用下列语句:
Connection.setAutoCommit(false);
Connection.rollback();
Connection.commit();
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Savepoint;
import org.junit.Test;
import util.jdbcUtil;
public class RollbackDemo {
private Connection conn;
private PreparedStatement stmt;
@Test
public void test1() {
//模拟事务回滚到事务开始前。
//其中第三个SQL语句有错误。
String sql_1="INSERT INTO student (NAME,age) VALUES(\"xiaohua\",1)";
String sql_2="INSERT INTO student (NAME,age) VALUES(\"xiaohua\",2)";
String sql_3="INSERT INTO false (NAME,age) VALUES(\"xiaohua\",3)";
try {
//建立连接
conn=jdbcUtil.getConnection();
//设置手动提交事务
conn.setAutoCommit(false);
//第一次执行SQL语句
stmt=conn.prepareStatement(sql_1);
stmt.executeUpdate();
//第二次执行SQL语句
stmt=conn.prepareStatement(sql_2);
stmt.executeUpdate();
//第三次执行SQL语句,有错误
stmt=conn.prepareStatement(sql_3);
stmt.executeUpdate();
}catch(Exception e){
try {
//出现异常,回滚事务到开始前。
conn.rollback();
}catch(SQLException e1) {
}
e.printStackTrace();
}finally {
try {
//所有操作成功时,提交事务
conn.commit();
jdbcUtil.close(conn, stmt);
}catch(Exception e) {
e.printStackTrace();
}
}
}
@Test
public void test2() {
Savepoint sp=null;
//模拟事务回滚到指定位置。
//其中第三个SQL语句有错误。
String sql_1="INSERT INTO student (NAME,age) VALUES(\"xiaohua\",1)";
String sql_2="INSERT INTO student (NAME,age) VALUES(\"xiaohua\",2)";
String sql_3="INSERT INTO false (NAME,age) VALUES(\"xiaohua\",3)";
try {
//建立连接
conn=jdbcUtil.getConnection();
//设置手动提交事务
conn.setAutoCommit(false);
//第一次执行SQL语句
stmt=conn.prepareStatement(sql_1);
stmt.executeUpdate();
//第二次执行SQL语句
stmt=conn.prepareStatement(sql_2);
stmt.executeUpdate();
//确定前面语句不会出现问题,在此设置保存点
sp=conn.setSavepoint();
//第三次执行SQL语句,有错误
stmt=conn.prepareStatement(sql_3);
stmt.executeUpdate();
}catch(Exception e){
try {
//出现异常,回滚到指定位置
conn.rollback(sp);
}catch(SQLException e1) {
}
e.printStackTrace();
}finally {
try {
//提交事务
conn.commit();
jdbcUtil.close(conn, stmt);
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
初始状态:
执行test1()无变化
执行test2(),第一条、第二条被执行:
2.BeanUtils组件
程序中对javabean的操作很频繁, 所以apache提供了一套开源的api,方便对javabean的操作,即BeanUtils组件。
BeanUtils组件,可以简化反射封装参数的步骤,给对象封装参数。且给对象封装参数的时候会进行类型自动转换。
常用的三个操作:
1:对象属性的拷贝
static void copyProperty(Object bean,String name,Object value)
static void setProperty(Object bean,String name,Object value)
2:对象的拷贝
static void copyProperties(Object dest,Object orig)
3:map数据拷贝到javabean中
static void populate(Object bean,Map<String,? extends Object> properties)
注:map中的key要与javabean的属性名称一致
BeanUtils的应用场景:
①快速将一个JavaBean各个属性值,赋值给有相同结构的另一个JavaBean中。
②快速收集表单中的所有数据到JavaBean中。
使用BenUtils组件:
①打开Apache官网http://www.apache.org/,最下面找到字符索引C开头的 Commons,点击中间BeanUtils,点击左侧Download,下载中间的支持包:commons-beanutils-1.9.3-bin.zip和源码包commons-beanutils-1.9.3-src.zip。
②打开Apache官网http://www.apache.org/,最下面找到字符索引C开头的 Commons,点击中间logging,点击左侧Download,下载中间的日志支持包:commons-logging-1.2-bin.zip。
③解压支持包:commons-beanutils-1.9.3-bin.zip,并导入commons-beanutils-1.9.3-jar到java项目中。
④解压日志支持包:commons-logging-1.2-bin.zip,并导入commons-logging-1.2.jar到java项目中。
例1:常见的三个操作:
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
import org.junit.Test;
import entity.Student;
public class BeanUtilDemo{
@Test
public void test1() throws Exception {
Student stu=new Student();
//a.对象属性的拷贝
BeanUtils.copyProperty(stu,"name","xiaohua");
BeanUtils.setProperty(stu, "age", "24");//对基本数据类型,会自动类型转换
Student newStu=new Student();
//b.对象的拷贝
BeanUtils.copyProperties(newStu, stu);
Student stuMap=new Student();
Map<String,Object> map=new HashMap<String,Object>();
map.put("name","xiaona");
map.put("age","24");
//c.拷贝map数据到对象中
BeanUtils.populate(stuMap, map);
//测试
System.out.println(stu.toString());
System.out.println(newStu.toString());
System.out.println(stuMap.toString());
}
}
其中entity包下实体类:Student.java文件为:
package entity;
public class Student {
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
运行结果:
例2:日期类型的拷贝
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
import org.junit.Test;
import entity.Student;
public class BeanUtilDemo {
//2. 自定义日期类型转换器
@Test
public void test2() throws Exception {
// 模拟表单数据
String name = "xiaohua";
String age = "24";
String birth = "1994-02-20";
// 对象
Student stu=new Student();
// 注册日期类型转换器: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) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
},Date.class);
// 把表单提交的数据,封装到对象中
BeanUtils.copyProperty(stu, "name", name);
BeanUtils.copyProperty(stu, "age", age);
BeanUtils.copyProperty(stu, "birth", birth);
//------ 测试------
System.out.println(stu);
}
//2. 使用提供的日期类型转换器工具类
@Test
public void test3() throws Exception {
// 模拟表单数据
String name = "xiaona";
String age = "25";
String birth ="1993-10-15";
// 对象
Student stu=new Student();
// 注册日期类型转换器:2, 使用组件提供的转换器工具类
ConvertUtils.register(new DateLocaleConverter(), Date.class);
// 把表单提交的数据,封装到对象中
BeanUtils.copyProperty(stu, "name", name);
BeanUtils.copyProperty(stu, "age", age);
BeanUtils.copyProperty(stu, "birth", birth);
//------ 测试------
System.out.println(stu);
}
}
其中:student.java文件为:
import java.util.Date;
public class Student {
private String name;
private int age;
private Date birth;
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", birth=" + birth + "]";
}
}
运行结果:
3.元数据
元数据:数据库、表、列的定义信息。
①Connection.getMetaData()
DataBaseMetaData对象
getURL(): 返回一个String类对象,代表数据库的URL。
getUserName(): 返回连接当前数据库管理系统的用户名。
getDatabaseProductName(): 返回数据库的产品名称。
getDatabaseProductVersion(): 返回数据库的版本号。
getDriverName(): 返回驱动驱动程序的名称。
getDriverVersion(): 返回驱动程序的版本号。
isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。
②PreparedStatement . getParameterMetaData() 获得代表PreparedStatement元数据的ParameterMetaData对象。
getParameterCount() 获得指定参数的个数
getParameterType(int param) 获得指定参数的sql类型(mysql驱动不支持)
③ResultSet. getMetaData() 获得代表ResultSet对象元数据的ResultSetMetaData对象。
getColumnCount() 返回resultset对象的列数
getColumnName(int column) 获得指定列的名称
getColumnTypeName(int column)获得指定列的类型
例:
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import org.junit.Test;
import util.jdbcUtil;
public class MetaDataDemo {
@Test
//1.数据库元数据
public void test1() throws Exception{
//获取连接
Connection conn=jdbcUtil.getConnection();
//获取数据库元数据
DatabaseMetaData metaData=conn.getMetaData();
System.out.println(metaData.getURL());
System.out.println(metaData.getUserName());
System.out.println(metaData.getDatabaseProductName());
System.out.println(metaData.getDatabaseProductVersion());
System.out.println(metaData.getDriverName());
System.out.println(metaData.getDriverVersion());
System.out.println(metaData.isReadOnly());
System.out.println("**********************");
}
@Test
//1.参数元数据
public void test2() throws Exception{
//获取连接
Connection conn=jdbcUtil.getConnection();
//sql语句
String sql="SELECT * FROM student WHERE id=? AND age=?;";
//预编译
PreparedStatement stmt=conn.prepareStatement(sql);
//获取参数元数据
ParameterMetaData metaData=stmt.getParameterMetaData();
System.out.println(metaData.getParameterCount());
System.out.println("**********************");
}
@Test
//1.结果集元数据
public void test3() throws Exception{
//获取连接
Connection conn=jdbcUtil.getConnection();
//sql语句
String sql="SELECT * FROM student ";
//预编译
PreparedStatement stmt=conn.prepareStatement(sql);
//执行,返回结果集
ResultSet rs=stmt.executeQuery();
//获取结果集元数据
ResultSetMetaData metaData=rs.getMetaData();
//迭代每一行
while(rs.next()) {
//获取列的个数
int count=metaData.getColumnCount();
//遍历每一列的列名称、列值
for(int i=0;i<count;i++) {
String columnName=metaData.getColumnName(i+1);
Object columnValue=rs.getObject(columnName);
System.out.print(columnName+"="+columnValue+",");
}
System.out.println();
}
}
}
运行结果: