JDBC
- 1、简单入门 Statement
- 2、preparedStatement
- 3、主键回显
- 4、批量操作
- 5、事务
- 6、Druid
- 6.1 工具类V1
- 6.2 工具类V2
- 6.3
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/add0a8e684584388ba65915688a3901b.png)
1、简单入门 Statement
步骤:
1、注册驱动
2、创建连接
3、创建 Statement对象
4、编写sql语句 并且发送sql语句获得结果集
5、解析结果集
6、释放资源
注意事项 都在写下面代码里了
import com.mysql.cj.jdbc.Driver;import java.sql.*;
import java.util.Properties;public class day1 {public static void main(String[] args) throws Exception {new test();new test();//注册驱动 不推荐 会注册两次 new Driver中有静态代码块//DriverManager.registerDriver(new Driver());//new Driver();//不推荐 不能显示出 是什么驱动 如果是8+ 则是com.mysql.cj.jdbc 如果是5+ 则是com.mysql.jdbcClass.forName("com.mysql.cj.jdbc.Driver"); //推荐 通过反射获得类加载//建立连接 3种方式 ①
// Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "ckytest", "123456");// ②Properties properties=new Properties();properties.put("user","ckytest");properties.put("password","123456");
// Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test",properties);//③Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?user=ckytest&password=123456");//创建 mqlStatement statement = ckytest.createStatement();//mql 并发送 获取结果集String mysql="select * from u_ser";// statement.executeUpdate(); 非DMLResultSet resultSet = statement.executeQuery(mysql);while(resultSet.next()){int anInt = resultSet.getInt(1);
// int id = resultSet.getInt("id");String name = resultSet.getString("name");System.out.println(anInt+"---"+name);}}
}
2、preparedStatement
步骤:
1、注册驱动
2、创建连接
3、编写sql语句
4、创建preparedStatement 对象并且传入sql语句
5、占位符赋值
从左到右 索引从1开始
6、发送sql语句获得结果集
7、解析结果集
8、释放资源
import com.mysql.cj.jdbc.Driver;
import org.junit.Test;import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class test {@Testpublic void testinsert() throws Exception{Class.forName("com.mysql.cj.jdbc.Driver");Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "ckytest", "123456");String mysql="insert into u_ser(id,name) values(?,?);";PreparedStatement preparedStatement = ckytest.prepareStatement(mysql);preparedStatement.setObject(1,3);preparedStatement.setObject(2,"yue");int i = preparedStatement.executeUpdate();if (i>0)System.out.println("成功");preparedStatement.close();ckytest.close();}@Testpublic void testupdate() throws Exception{Class.forName("com.mysql.cj.jdbc.Driver");Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "ckytest", "123456");String mysql="update u_ser set name=? where id=?;";PreparedStatement preparedStatement = ckytest.prepareStatement(mysql);preparedStatement.setObject(1,"cui");preparedStatement.setObject(2,3);int i = preparedStatement.executeUpdate();if (i>0)System.out.println("成功");preparedStatement.close();ckytest.close();}@Testpublic void testdelete() throws Exception{Class.forName("com.mysql.cj.jdbc.Driver");Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "ckytest", "123456");String mysql="delete from u_ser where id=?;";PreparedStatement preparedStatement = ckytest.prepareStatement(mysql);//preparedStatement.setObject(1,"cui");preparedStatement.setObject(1,3);int i = preparedStatement.executeUpdate();if (i>0)System.out.println("成功");preparedStatement.close();ckytest.close();}//查询u_ser表中所有的内容 并保存到 List<map>集合中 key-value@Testpublic void testquery() throws Exception{Class.forName("com.mysql.cj.jdbc.Driver");Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "ckytest", "123456");String mysql="select * from u_ser;";PreparedStatement preparedStatement = ckytest.prepareStatement(mysql);ResultSet resultSet = preparedStatement.executeQuery();//得到表信息ResultSetMetaData metaData = resultSet.getMetaData();//得到列数量int columnCount = metaData.getColumnCount();List<Map> list=new ArrayList<>();while(resultSet.next()) {Map map = new HashMap();for (int i = 1; i <= columnCount; i++) {//获得结果Object object = resultSet.getObject(i);//获得列名String columnLabel = metaData.getColumnLabel(i);map.put(columnLabel, object);}list.add(map);}System.out.println(list);resultSet.close();preparedStatement.close();ckytest.close();}
}
String columnLabel = metaData.getColumnLabel(i);
getColumnLabel 有别名可以获得别名而getColumnName 不能获取别名。
getColumnCount 获取列的数量
getMetaData 获取列的信息
3、主键回显
/*** * 得到自增长的主键* 在创建prepareStatement,告知它拿回自增长的主键* getGeneratedKeys 得到一个自增长主键的结果 首先通过next 移动光标* 之后通过getxx 获取结果,插入一行 肯定只获取一个结果 所以是一行一列 索引为1 即使回显的主键*/@Testpublic void testinsertkey() throws Exception{Class.forName("com.mysql.cj.jdbc.Driver");Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "ckytest", "123456");String mysql="insert into u_ser(name) values(?);";PreparedStatement preparedStatement = ckytest.prepareStatement(mysql,Statement.RETURN_GENERATED_KEYS);preparedStatement.setObject(1,"yue1");int i = preparedStatement.executeUpdate();if (i>0)System.out.println("成功");ResultSet generatedKeys = preparedStatement.getGeneratedKeys();generatedKeys.next();Object id = generatedKeys.getObject(1);System.out.println("回显主键:"+id);preparedStatement.close();ckytest.close();}
4、批量操作
在url中添上rewriteBatchedStatements=true,允许批量操作。
sql语句不要加分号
preparedStatement.addBatch();
preparedStatement.executeBatch();
@Testpublic void testinsert1() throws Exception{Class.forName("com.mysql.cj.jdbc.Driver");Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?rewriteBatchedStatements=true", "ckytest", "123456");String mysql="insert into u_ser(name) values(?)";PreparedStatement preparedStatement = ckytest.prepareStatement(mysql,Statement.RETURN_GENERATED_KEYS);long start = System.currentTimeMillis();for (int i = 0; i < 10000; i++) {preparedStatement.setObject(1,"yue1"+i);preparedStatement.executeUpdate();}long end = System.currentTimeMillis();System.out.println("时间为:"+(end-start)/1000+"s"); //14spreparedStatement.close();ckytest.close();}@Testpublic void testabatchinsert() throws Exception{Class.forName("com.mysql.cj.jdbc.Driver");Connection ckytest = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?rewriteBatchedStatements=true", "ckytest", "123456");String mysql="insert into u_ser(name) values(?)";PreparedStatement preparedStatement = ckytest.prepareStatement(mysql);long start = System.currentTimeMillis();for (int i = 0; i < 10000; i++) {preparedStatement.setObject(1,"yue"+i);preparedStatement.addBatch();}preparedStatement.executeBatch();long end = System.currentTimeMillis();System.out.println("时间为:"+(end-start)+"s");//0.77spreparedStatement.close();ckytest.close();}
5、事务
原子性 一致性 隔离性 持久性
事务的发生 必须是在同一个连接中。
对于事务,我们应该在业务层进行开启和关闭。mysql是自动提交业务,我们可以手动开启或者关闭。
比如转账业务,我们可以在业务层获取一个连接,之后将该连接传入加钱和转钱方法,这样可以确保是一个连接。
事务,我们一般使用try,catch,如果成功就提交,捕捉到错误就回滚。
6、Druid
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.alibaba.druid.pool.DruidPooledConnection;import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;public class DruidTest {public void druid1() throws Exception{//创建连接池对象DruidDataSource druidDataSource=new DruidDataSource();//一些必要和不必要的选项 url,name,pwd,driver都是必须的 连接池数量这些不是必须的druidDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test");druidDataSource.setPassword("123456");druidDataSource.setUsername("ckytest");druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");druidDataSource.setInitialSize(5);druidDataSource.setMaxActive(10);//获得一个连接。DruidPooledConnection connection = druidDataSource.getConnection();//回收connection.close();//如果是连接池 则close代表 回收 而不是关闭连接。}public void druid2() throws Exception{//读取配置文件Properties properties=new Properties();//只要在src下 就可以使用类加载器InputStream resourceAsStream = DruidTest.class.getClassLoader().getResourceAsStream("druid.properties");properties.load(resourceAsStream);//加载到properties中DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);//获得一个连接。Connection connection = dataSource.getConnection();//回收connection.close();//如果是连接池 则close代表 回收 而不是关闭连接。}
}
Url=jdbc:mysql://127.0.0.1:3306/test
Password=123456
Username=ckytest
DriverClassName=com.mysql.cj.jdbc.Driver
6.1 工具类V1
每次都去初始化连接池太麻烦了,我们封装一个工具类,对外提供一个获取连接和回收连接的方法。
import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/*
* 工具类:内部包含一个连接池对象 对外提供连接和回收连接的方法
* 创建连接池对象 应该是一个单例模式 可以使用静态代码块来实现 只加载一次*/
public class DruidUtils {//连接池private static DataSource dataSource=null;static {Properties properties=new Properties();InputStream resourceAsStream = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");try {properties.load(resourceAsStream);} catch (IOException e) {e.printStackTrace();}try {dataSource = DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();}}public Connection getConnection() throws SQLException {return dataSource.getConnection();}public void closeConnection(Connection connection){try {connection.close();} catch (SQLException e) {e.printStackTrace();}}
}
6.2 工具类V2
我们的工具类V1,只是单例模式了连接池,但是每次获取连接都是新的连接。
如果我们在Serve层获得一个连接,这个连接还需要传给Dao层来获取,能不能让同一个线程,Serve层和Dao层获取的都是同一个连接,而不用使用参数传递呢?可以使用线程局部变量。只要一个线程里边的属性就是通用的。
import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/*
* 工具类:内部包含一个连接池对象 对外提供连接和回收连接的方法
* 创建连接池对象 应该是一个单例模式 可以使用静态代码块来实现 只加载一次*/
public class DruidUtils {//连接池private static DataSource dataSource=null;private static ThreadLocal<Connection> threadLocal=new ThreadLocal<>();static {Properties properties=new Properties();InputStream resourceAsStream = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");try {properties.load(resourceAsStream);} catch (IOException e) {e.printStackTrace();}try {dataSource = DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();}}public Connection getConnection() throws SQLException {Connection connection=threadLocal.get();if (connection==null){connection = dataSource.getConnection();threadLocal.set(connection);}return connection;}public void closeConnection() throws Exception{Connection connection = threadLocal.get();if (connection!=null){threadLocal.remove();connection.setAutoCommit(true);connection.close();}}
}
6.3
对于Dao层的封装,写一个基础BaseDao,对语句进行封装,可以分为DQL和非DQl两种。
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class A {public static int executUpdate(String sql,Object ... args) throws Exception{Connection connection = DruidUtils.getConnection();PreparedStatement preparedStatement = connection.prepareStatement(sql);for (int i = 0; i <args.length ; i++) {preparedStatement.setObject(i+1,args[i]);}int i = preparedStatement.executeUpdate();if (connection.getAutoCommit()){//没有开启事务DruidUtils.closeConnection();}return i;}public static <T> List<T> executQuery(Class<T> tClass,String sql, Object ... args) throws Exception{Connection connection = DruidUtils.getConnection();PreparedStatement preparedStatement = connection.prepareStatement(sql);if(args!=null&&args.length>0){for (int i = 0; i <args.length ; i++) {preparedStatement.setObject(i+1,args[i]);}}ResultSet resultSet = preparedStatement.executeQuery();//得到表信息ResultSetMetaData metaData = resultSet.getMetaData();//得到列数量int columnCount = metaData.getColumnCount();List<T> list=new ArrayList<>();while(resultSet.next()) {Constructor<T> constructor = tClass.getConstructor();T t = constructor.newInstance();for (int i = 1; i <= columnCount; i++) {//获得结果Object object = resultSet.getObject(i);//获得列名String columnLabel = metaData.getColumnLabel(i);Field declaredField = tClass.getDeclaredField(columnLabel);declaredField.set(t,object);}list.add(t);}if (connection.getAutoCommit()){//没有开启事务DruidUtils.closeConnection();}return list;}
}
数据库每个表都对应java中的一个实体类,查询时我们返回的是一个装有实体类的集合。
封装过工具类之后的增删改查 简化了很多。
import com.mysql.cj.jdbc.Driver;
import org.junit.Test;import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class test {@Testpublic void testinsert() throws Exception{String mysql="insert into u_ser(id,name) values(?,?);";int a = A.executUpdate(mysql, 50001, "a");System.out.println(a);}@Testpublic void testupdate() throws Exception{String mysql="update u_ser set name=? where id=?;";int a = A.executUpdate(mysql, "cui", 1);System.out.println(a);}@Testpublic void testdelete() throws Exception{String mysql="delete from u_ser where id=?;";int a = A.executUpdate(mysql, 1);System.out.println(a);}//查询u_ser表中所有的内容 并保存到 List<map>集合中 key-value@Testpublic void testquery() throws Exception{String mysql="select * from u_ser;";List<User> users = A.executQuery(User.class, mysql);System.out.println(users);}}