JDBC事务和数据

上一篇博客  http://blog.csdn.net/forrest_ou/article/details/53907003  简单的使用了JDBC连接MySQL数据库的增删改查,异常和资源关闭等内容均没有涉及

玩一个东西,肯定是先去上手玩,然后才来慢慢的了解学习它的注意事项和更加深层次的内容


这篇博客的主要内容:

       1、创建一个工具类,完成加载驱动,建立连接和释放资源

       2、日期格式的处理

       3、元数据的获取

       4、事务的操作

       5、批处理


所有代码都是自己动手敲出来,实践过,感觉具体的动手会发现更多的问题,也就会了解决更多的问题,重要的是你知道了到底行不行


工具类————加载驱动,建立连接,释放资源

package TestJDBC;

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

//JDBC工具类,  加载驱动   建立连接    关闭资源 。方法都是static,可以直接调用
public final class JDBCUtil {
	private static String DRIVER = "com.mysql.jdbc.Driver";
	private static String URL = "jdbc:mysql://localhost:3306/test";
	private static String USER_NAME = "admin";
	private static String PASSWORD = "123456";
	
    //注册驱动放在静态代码块中,保证只注册一次,当类装载到虚拟机中就会执行
	static{
		try {
			Class.forName(DRIVER);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	//建立连接
	public static Connection getConnection() throws SQLException{
		return DriverManager.getConnection(URL, USER_NAME, PASSWORD);
	}
	//释放资源
	public static void closeAll(ResultSet rs, Statement stmt, Connection conn){
		
		try {
			if(rs != null){
				rs.close();
			}
			rs = null;
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			try {
				if(stmt != null){
					stmt.close();
				}
				stmt = null;
			} catch (Exception e) {
				e.printStackTrace();
			}
			finally {
				try {
					if(conn != null){
						conn.close();
					}
					conn = null;
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
					
		}

}

例如我在main方法中的调用

Connection conn = JDBCUtil.getConnection();
JDBCUtil.closeAll(rs, stmt, conn);



对于日期处理一直是一个老生常谈的问题,经常遇到。弄一个Datedemo类来实验日期的操作,主要有SimpleDateFormat和Calendar

使用SimpleDateFormat来完成日期与字符串的相互转换,了解Calendar更多的操作方式

package TestForDate;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date; 	 	
//SimpleDateFormat  格式化存储  日期转换为字符串(sdf.format(Date date)方法),字符串转日期(sdf.parse(String str)方法)
public class DateDemo {

	public static void main(String[] args) throws ParseException {
		Date date = new Date();
		//System.out.println(date.toString());//当前日期
		
		SimpleDateFormat sdf  = new SimpleDateFormat("yyyy-MM-dd");
		String str = "2016-12-12";
		Date t = sdf.parse(str); 	
		String s = sdf.format(date);
		System.out.println(s);
		System.out.println(t);

		//日期处理类,包含Date类, Calendar类 是更厉害,包含更多,通过 set 和  get 方法
		Calendar cld = Calendar.getInstance();
		cld.set(2016, 12-1, 12);
		int year1 = cld.get(Calendar.YEAR);
		int month1 = cld.get(Calendar.MONTH) + 1;
		System.out.println(year1 +" "+ month1);
		cld.set(Calendar.YEAR, 2017);
		System.out.println(cld.get(Calendar.YEAR));
		cld.add(Calendar.MONTH, -2);
		System.out.println(cld.get(Calendar.MONTH) + 1);
		
	}

}

JDBC中日期的使用,user表中新增一个birthday字段,实验日期。user类与user表中的birthday属性得保证是一样的,这样才能成功操作

1、可以都设置为String类型的

2、Date 类型的的涉及到java.sql.Date与java.util.Date的相互转换

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String str = "2017-01-01";
        java.util.Date date = sdf.parse(str);
        //parse后得到的是java.util.Date类型的日期,转换成java.sql.Date类型,才可以使用(父子类,真是青出于蓝而胜于蓝啊)
        //都有getTime()方法,返回自1970年1月1日00:00:00到目标日期的毫秒数,通过这样来转换
        java.sql.Date sqlDate = new java.sql.Date(date.getTime());


元数据信息的获取

databaseMetadata  parameterMetadata  ResultSetMetada 分别对应 Connection Statement  ResultSet

//DatabaseMetaData  Connection
		conn = JDBCUtil.getConnection();
		DatabaseMetaData dbmd = conn.getMetaData();
		String url = dbmd.getURL();
		System.out.println(url+" "+dbmd.getUserName()+" "+dbmd.getDriverName());*/
		/*getURL():返回一个String类对象,代表数据库的URL。
		getUserName():返回连接当前数据库管理系统的用户名。
		getDatabaseProductName():返回数据库的产品名称。
		getDatabaseProductVersion():返回数据库的版本号。
		getDriverName():返回驱动驱动程序的名称。
		getDriverVersion():返回驱动程序的版本号。
		isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。.........等等

/*ResultSet getTables(String catalog,String schemaPattern,String tableNamePattern,String[] types); 
        * catalog - 表所在的类别名称;""表示获取没有类别的列,null表示获取所有类别的列。 
        * schema - 表所在的模式名称(oracle中对应于Tablespace);""表示获取没有模式的列,null标识获取所有模式的列; 可包含单字符通配符("_"),或多字符通配符("%"); 
        * tableNamePattern - 表名称;可包含单字符通配符("_"),或多字符通配符("%"); 
        * types - 表类型数组; "TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS" 和 "SYNONYM";null表示包含所有的表类型;可包含单字符通配符("_"),或多字符通配符("%"); */
		//获取数据库的表
		ResultSet rs = dbmd.getTables(null, null, null, new String[]{"TABLE"});
		while(rs.next()){
			System.out.println(rs.getString(1));//db名称
			//System.out.println(rs.getString(2));//用户名称
			System.out.println(rs.getString("TABLE_NAME"));//表名称
			//System.out.println(rs.getString("REMARKS"));//获取备注
		}

//获取表主键信息
		ResultSet rs1 = dbmd.getPrimaryKeys(null, null, "user");
		while(rs1.next()){
			System.out.println(rs1.getString("COLUMN_NAME"));//主键列名
			System.out.println(rs1.getString("TABLE_NAME"));
			System.out.println(rs1.getShort("KEY_SEQ"));//第几列
		}

               ParameterMetaData  pmd = stmt.getParameterMetaData();
	       System.out.println(pmd.getParameterCount());//获取参数个数

                        ResultSet rs = stmt.executeQuery();
			ResultSetMetaData rsmd = rs.getMetaData();
			System.out.println(rsmd.getColumnCount());
			for(int i = 0; i < rsmd.getColumnCount(); i++){
				System.out.println(rsmd.getColumnName(i+1));
			}


事务的操作,要么全部执行成功,要么全部执行不成功,回滚到原来的状态

主要的方法有conn.setAutoCommit(false);   conn.commit();  conn.rollback();

1、取消自动提交

2、提交事务信息(不同的sql)

3、提交事务

4、提交出现错误,回滚到原来的状态

//事务处理
		String sql[] = new String[3];
		sql[0] = "INSERT INTO user(id,name,password) VALUES (24,'yy','yy')";
		sql[1] = "INSERT INTO user(id,name,password) VALUES (25,'yyyy','yyyy')";
		sql[2] = "INSERT INTO user(id,name) VALUES (26,'yyyy')";//这样就不成功,因为password是必填的,三条语句一起执行失败并回滚状态	
		//sql[2] = "UPDATE user SET name = '杨' WHERE id = 88"; //执行成功,88的不存在
		//sql[2] = "DELETE FROM user WHERE id = 88"; //执行成功,88的不存在
		try {
			conn = JDBCUtil.getConnection();
			conn.setAutoCommit(false);
			for(int i = 0; i < sql.length; i++){
				stmt = conn.prepareStatement(sql[i]);
				stmt.execute();
			}
			conn.commit();
			System.out.println("事务执行成功");
		} catch (Exception e) {
			try {
				System.out.println("事务执行失败,执行回滚");
				conn.rollback();
				e.printStackTrace();//打印错误信息对于找原因是为一神技
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		finally {
			conn.setAutoCommit(true);//可以不用,会自动变为false
			JDBCUtil.closeAll(rs, stmt, conn);
		}

批处理:对应Statement和preparedStatement有两种批处理方式

对应Statement的批处理适合不同类型的sql操作

对应preparedStatement的批处理适合相同类型但是不同参数的sql操作

主要是方法:addBatch()添加批处理语句,executeBatch()执行批处理语句,clearBatch()清除缓存

try {
			conn = JDBCUtil.getConnection();
			Statement stmt = conn.createStatement();
			//添加批处理语句
			stmt.addBatch("INSERT INTO user (id,name,password,phone) VALUES (1,'oo','oo',111)");
			stmt.addBatch("INSERT INTO user (id,name,password,phone) VALUES (2,'ooo','ooo',111)");
			stmt.addBatch("INSERT INTO user (id,name,password,phone) VALUES (3,'oooo','oooo',111)");
			stmt.addBatch("INSERT INTO user (id,name,password,phone) VALUES (4,'ooooo','ooooo',111)");
			stmt.addBatch("UPDATE user SET name = '杨' WHERE id = 2 ");
			stmt.executeBatch();//执行批处理语句
			stmt.clearBatch();//去除缓存
			
			/*String sql = "DELETE FROM user WHERE id = ?";
		    stmt = conn.prepareStatement(sql);*/
		    
			/*for(int i = 1; i < 5; i++){
				stmt.setInt(1, i);
				stmt.addBatch();//添加批处理语句
			}*/
			/*for(int i = 25; i > 14; i--){
				stmt.setInt(1, i);
				stmt.addBatch();//添加批处理语句
			}
			stmt.executeBatch();//执行批处理语句
			stmt.clearBatch();//去除缓存
*/			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			JDBCUtil.closeAll(rs, stmt, conn);
		}



整体代码,包含上面的工具类,一共三个类

JdbcForUser2类

package TestJDBC;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Date;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.text.SimpleDateFormat;

public class JdbcForUser2 {
	
	private static Connection conn = null;
	private static PreparedStatement stmt = null;
	private static ResultSet rs = null;

	public static void main(String[] args) throws Exception {
		//获取是否支持事务和是否自动提交信息
		/*conn = JDBCUtil.getConnection();
		DatabaseMetaData dbmd = conn.getMetaData();
		System.out.println(dbmd.supportsTransactions()+" "+conn.getAutoCommit());*/
		
		//日期格式一致性问题
		/*JdbcForUser2 jfu = new JdbcForUser2();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String str = "2017-01-01";
        java.util.Date date = sdf.parse(str);
        //parse后得到的是java.util.Date类型的日期,转换成java.sql.Date类型,才可以使用(父子类,真是青出于蓝而胜于蓝啊)
        //都有getTime()方法,返回自1970年1月1日00:00:00到目标日期的毫秒数,通过这样来转换
        java.sql.Date sqlDate = new java.sql.Date(date.getTime());
		jfu.addUser(new User(13,"test3","ooo","2222",sqlDate));*/
			
		/*User user1 = jfu.getById(10);
		System.out.println(user1.getName()+" "+user1.getBirthday());*/
		
		//元数据
		//DatabaseMetaData  Connection
		/*conn = JDBCUtil.getConnection();
		DatabaseMetaData dbmd = conn.getMetaData();
		String url = dbmd.getURL();
		System.out.println(url+" "+dbmd.getUserName()+" "+dbmd.getDriverName());*/
		/*getURL():返回一个String类对象,代表数据库的URL。
		getUserName():返回连接当前数据库管理系统的用户名。
		getDatabaseProductName():返回数据库的产品名称。
		getDatabaseProductVersion():返回数据库的版本号。
		getDriverName():返回驱动驱动程序的名称。
		getDriverVersion():返回驱动程序的版本号。
		isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。.........等等*/
		
		/*ResultSet getTables(String catalog,String schemaPattern,String tableNamePattern,String[] types); 
        * catalog - 表所在的类别名称;""表示获取没有类别的列,null表示获取所有类别的列。 
        * schema - 表所在的模式名称(oracle中对应于Tablespace);""表示获取没有模式的列,null标识获取所有模式的列; 可包含单字符通配符("_"),或多字符通配符("%"); 
        * tableNamePattern - 表名称;可包含单字符通配符("_"),或多字符通配符("%"); 
        * types - 表类型数组; "TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS" 和 "SYNONYM";null表示包含所有的表类型;可包含单字符通配符("_"),或多字符通配符("%"); */
		//获取数据库的表
		/*ResultSet rs = dbmd.getTables(null, null, null, new String[]{"TABLE"});
		while(rs.next()){
			System.out.println(rs.getString(1));//db名称
			//System.out.println(rs.getString(2));//用户名称
			System.out.println(rs.getString("TABLE_NAME"));//表名称
			//System.out.println(rs.getString("REMARKS"));//获取备注
		}*/
		
		//获取表主键信息
		/*ResultSet rs1 = dbmd.getPrimaryKeys(null, null, "user");
		while(rs1.next()){
			System.out.println(rs1.getString("COLUMN_NAME"));//主键列名
			System.out.println(rs1.getString("TABLE_NAME"));
			System.out.println(rs1.getShort("KEY_SEQ"));//第几列
		}*/
		
		//ParameterMetaData   PreparedStatement
		//下面getById(int id)方法内
		//ResultSetMetaData   ResultSet
		//下面getById(int id)方法内
		/*JdbcForUser2 jfu = new JdbcForUser2();
		User user1 = jfu.getById(1);
		System.out.println(user1.getName()+" "+user1.getBirthday());*/
		
		//事务处理
		/*String sql[] = new String[3];
		sql[0] = "INSERT INTO user(id,name,password) VALUES (24,'yy','yy')";
		sql[1] = "INSERT INTO user(id,name,password) VALUES (25,'yyyy','yyyy')";
		sql[2] = "INSERT INTO user(id,name) VALUES (26,'yyyy')";//这样就不成功,因为password是必填的,三条语句一起执行失败并回滚状态	
		//sql[2] = "UPDATE user SET name = '杨' WHERE id = 88"; //执行成功,88的不存在
		//sql[2] = "DELETE FROM user WHERE id = 88"; //执行成功,88的不存在
		try {
			conn = JDBCUtil.getConnection();
			conn.setAutoCommit(false);
			for(int i = 0; i < sql.length; i++){
				stmt = conn.prepareStatement(sql[i]);
				stmt.execute();
			}
			conn.commit();
			System.out.println("事务执行成功");
		} catch (Exception e) {
			try {
				System.out.println("事务执行失败,执行回滚");
				conn.rollback();
				e.printStackTrace();//打印错误信息对于找原因是为一神技
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		finally {
			conn.setAutoCommit(true);//可以不用,会自动变为false
			JDBCUtil.closeAll(rs, stmt, conn);
		}*/

		//批处理
		JdbcForUser2 jfu = new JdbcForUser2();
		jfu.batchDel();
		//System.out.println("批处理成功");
	}
	public void addUser(User user) {
		try {
		    conn = JDBCUtil.getConnection();
			String sql = " INSERT INTO user (id,name,password,phone,birthday) VALUES (?,?,?,?,?) ";
			stmt = conn.prepareStatement(sql);//预编译sql
			stmt.setInt(1, user.getId());
			stmt.setString(2, user.getName());
			stmt.setString(3, user.getPassword());
			stmt.setString(4, user.getPhone());
			//stmt.setDate(5, new Date(System.currentTimeMillis()));
			stmt.setDate(5, user.getBirthday());
			stmt.execute();	
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			JDBCUtil.closeAll(rs, stmt, conn);
		}

	}
	public User getById(int id) {
		User user = null;
		try {
			conn = JDBCUtil.getConnection();
			String sql = " SELECT * FROM user WHERE id = ?";
			PreparedStatement stmt = conn.prepareStatement(sql);
			stmt.setInt(1, id);
			ParameterMetaData  pmd = stmt.getParameterMetaData();
			System.out.println(pmd.getParameterCount());//获取参数个数
			//System.out.println(pmd.getParameterTypeName(2));
			ResultSet rs = stmt.executeQuery();
			ResultSetMetaData rsmd = rs.getMetaData();
			System.out.println(rsmd.getColumnCount());
			for(int i = 0; i < rsmd.getColumnCount(); i++){
				System.out.println(rsmd.getColumnName(i+1));
			}
			user = new User();
			while(rs.next()){
				user.setName(rs.getString("name"));
				user.setPhone(rs.getString("phone"));
				user.setBirthday(rs.getDate("birthday"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			JDBCUtil.closeAll(rs, stmt, conn);
		}
		return user;
	}
	//批处理,对应Statement和preparedStatement的两种批处理方式
	public void batchDel(){
		try {
			conn = JDBCUtil.getConnection();
			Statement stmt = conn.createStatement();
			//添加批处理语句
			stmt.addBatch("INSERT INTO user (id,name,password,phone) VALUES (1,'oo','oo',111)");
			stmt.addBatch("INSERT INTO user (id,name,password,phone) VALUES (2,'ooo','ooo',111)");
			stmt.addBatch("INSERT INTO user (id,name,password,phone) VALUES (3,'oooo','oooo',111)");
			stmt.addBatch("INSERT INTO user (id,name,password,phone) VALUES (4,'ooooo','ooooo',111)");
			stmt.addBatch("UPDATE user SET name = '杨' WHERE id = 2 ");
			stmt.executeBatch();//执行批处理语句
			stmt.clearBatch();//去除缓存
			
			/*String sql = "DELETE FROM user WHERE id = ?";
		    stmt = conn.prepareStatement(sql);*/
		    
			/*for(int i = 1; i < 5; i++){
				stmt.setInt(1, i);
				stmt.addBatch();//添加批处理语句
			}*/
			/*for(int i = 25; i > 14; i--){
				stmt.setInt(1, i);
				stmt.addBatch();//添加批处理语句
			}
			stmt.executeBatch();//执行批处理语句
			stmt.clearBatch();//去除缓存
*/			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			JDBCUtil.closeAll(rs, stmt, conn);
		}
	}

}



User类

package TestJDBC;

import java.sql.Date;

public class User {
	private int id;
	private String name;
	private String password;
	private String phone;
	private Date birthday;	
	
	public User(int id, String name, String password, String phone, Date birthday){
		this.id = id;
		this.name = name;
		this.password = password;
		this.phone = phone;
		this.birthday = birthday;
	}
	public User(){	
	}
	public User(int id, String name, String password){
		this.id = id;
		this.name = name;
		this.password = password;
	}
	public User(int id, String name, String password, String phone){
		this.id = id;
		this.name = name;
		this.password = password;
		this.phone = phone;
	}
	

	
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

}


————————over——————————

好记性不如烂笔头,总结为一篇博客,下次需要时或者有所忘记的时候,可以再来瞧瞧

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值