网站首页 > 教程分享 正文
学习目标
本次学习目标
5.1 JDBCTools工具类2.0版
5.1.1 演示事务问题
需求:
(1)修改did=1的部门简介为“部门1的简介”
(2)修改did=2的部门名称 = 部门1的名称(故意制造错误,因为t_department表的dname有唯一键元素,这条修改会失败)
要求(1)(2)同时成功或同时失败,即在一个事务中完成。
package com.atguigu.test;
import com.atguigu.bean.Department;
import com.atguigu.dao.impl.DepartmentDAOImpl;
import com.atguigu.tools.JDBCTools;
import org.junit.Test;
import java.sql.Connection;
public class TestTransaction {
@Test
public void test01()throws Exception{
DepartmentDAOImpl dao = new DepartmentDAOImpl();
Connection connection = JDBCTools.getConnection();
connection.setAutoCommit(false);
try {
Department dept1 = dao.getByDid(1);
dept1.setDescription("部门1的简介");
System.out.println("第一条记录修改:" +dao.updateDepartment(dept1));
Department dept2 = dao.getByDid(2);
dept2.setDname(dept1.getDname());//故意修改为和部门1的名称一样,制造异常
System.out.println("第一条记录修改:" +dao.updateDepartment(dept2));
System.out.println("都成功");
connection.commit();
} catch (Exception e) {
e.printStackTrace();
System.out.println("失败");
connection.rollback();
}
JDBCTools.freeConnection(connection);
}
}
运行报错:
第一条记录修改:true
java.lang.RuntimeException: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '研发部' for key 't_department.dname'
at com.atguigu.dao.impl.BaseDAOImpl.update(BaseDAOImpl.java:35)
at com.atguigu.dao.impl.DepartmentDAOImpl.updateDepartment(DepartmentDAOImpl.java:24)
at com.atguigu.test.TestTransaction.test01(TestTransaction.java:25)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '研发部' for key 't_department.dname'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1092)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1040)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1347)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1025)
at com.alibaba.druid.pool.DruidPooledPreparedStatement.executeUpdate(DruidPooledPreparedStatement.java:256)
at com.atguigu.dao.impl.BaseDAOImpl.update(BaseDAOImpl.java:33)
... 24 more
失败
5.1.2 使用ThreadLocal类
其中ThreadLocal的介绍如下:
JDK 1.2的版本中就提供java.lang.ThreadLocal,为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。通常用来在在多线程中管理共享数据库连接、Session等
ThreadLocal用于保存某个线程共享变量,原因是在Java中,每一个线程对象中都有一个ThreadLocalMap<ThreadLocal, Object>,其key就是一个ThreadLocal,而Object即为该线程的共享变量。而这个map是通过ThreadLocal的set和get方法操作的。对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量。
1、ThreadLocal对象.get: 获取ThreadLocal中当前线程共享变量的值。
2、ThreadLocal对象.set: 设置ThreadLocal中当前线程共享变量的值。
3、ThreadLocal对象.remove: 移除ThreadLocal中当前线程共享变量的值。
线程(事务)结束后别忘了移除共享对象。
5.1.3 JDBCTools2.0版
package com.atguigu.tools;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class JDBCTools {
//数据库连接池
private static DataSource ds;
//静态变量的初始化,可以使用静态代码块
static{
try {
Properties pro = new Properties();
pro.load(JDBCTools.class.getClassLoader().getResourceAsStream("druid.properties"));
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
//<Connection>表示 ThreadLocalMap中(key,value)的value是Connection类型的对象
public static Connection getConnection()throws SQLException {
Connection connection = threadLocal.get();
//每一个线程调用这句代码,都会到自己的ThreadLocalMap中,以threadLocal对象为key,找到value
//如果value为空,说明当前线程还未获取过Connection对象,那么就从连接池中拿一个数据库连接对象给你
//并且通过threadLocal的set方法把Connection对象放到当前线程ThreadLocalMap中
if(connection == null){
connection = ds.getConnection();
//通过threadLocal的set方法把Connection对象放到当前线程ThreadLocalMap中
threadLocal.set(connection);
}
return connection;
}
public static void freeConnection()throws SQLException{
Connection connection = threadLocal.get();
if(connection != null){
connection.setAutoCommit(true);//还原自动提交模式
threadLocal.remove();//从当前线程的ThreadLocalMap中删除这个连接
connection.close();
}
}
}
5.2 BaseDAOImpl类2.0版
5.2.1 使用Dbutils
commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。
其中QueryRunner类封装了SQL的执行,是线程安全的。
(1)可以实现增、删、改、查、批处理、
(2)考虑了事务处理需要共用Connection。
(3)该类最主要的就是简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。
(4)不需要手动关闭连接,runner会自动关闭连接,释放到连接池中
(1)更新
public int update(Connection conn, String sql, Object… params) throws SQLException:用来执行一个更新(插入、更新或删除)操作。
……
(2)插入
public T insert(Connection conn,String sql,ResultSetHandler rsh, Object… params) throws SQLException:只支持INSERT语句,其中 rsh - The handler used to create the result object from the ResultSet of auto-generated keys. 返回值: An object generated by the handler.即自动生成的键值
….
(3)批处理
public int[] batch(Connection conn,String sql,Object[][] params)throws SQLException: INSERT, UPDATE, or DELETE语句
public T insertBatch(Connection conn,String sql,ResultSetHandler rsh,Object[][] params)throws SQLException:只支持INSERT语句
…..
(4)使用QueryRunner类实现查询
public Object query(Connection conn, String sql, ResultSetHandler rsh,Object… params) throws SQLException:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。
….
ResultSetHandler接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。ResultSetHandler 接口提供了一个单独的方法:Object handle (java.sql.ResultSet rs)该方法的返回值将作为QueryRunner类的query()方法的返回值。
该接口有如下实现类可以使用:
- BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
- BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
- ScalarHandler:查询单个值对象
- MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
- MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
- ColumnListHandler:将结果集中某一列的数据存放到List中。
- KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。
- ArrayHandler:把结果集中的第一行数据转成对象数组。
- ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
5.2.2 使用Dbutils组件封装BaseDAOImpl
package com.atguigu.dao.impl;
import com.atguigu.tools.JDBCTools;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.sql.SQLException;
import java.util.List;
/*
如何使用DBUtils?
(1)导入jar
commons-dbutils-1.6.jar
druid-1.1.10.jar
mysql-connector-java-5.1.36-bin.jar
(2)QueryRunner有各种执行sql方法
public int update(Connection conn, String sql, Object... params) throws SQLException:用来执行一个更新(插入、更新或删除)操作。
public Object query(Connection conn, String sql, ResultSetHandler rsh,Object... params) throws SQLException:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。
查询的方法query方法,需要配合ResultSetHandler接口的实现类使用。
ResultSetHandler接口有很多实现类:
A:BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
B:BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中
C:ScalarHandler:查询单个值对象
*/
public abstract class BaseDAOImpl {
private QueryRunner queryRunner = new QueryRunner();
/**
* 通用的增删改的方法
* @param sql String 要执行的sql
* @param args Object... 如果sql中有?,就传入对应个数的?要设置值
* @return int 执行的结果
*/
protected int update(String sql,Object... args) {
try {
return queryRunner.update(JDBCTools.getConnection(),sql,args);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
/**
* 查询单个对象的方法
* @param clazz Class 记录对应的类类型
* @param sql String 查询语句
* @param args Object... 如果sql中有?,即根据条件查询,可以设置?的值
* @param <T> 泛型方法声明的泛型类型
* @return T 一个对象
*/
protected <T> T getBean(Class<T> clazz, String sql, Object... args){
List<T> list = getList(clazz, sql, args);
if(list != null && list.size()>0) {
return getList(clazz, sql, args).get(0);
}
return null;
}
/**
* 通用查询多个对象的方法
* @param clazz Class 记录对应的类类型
* @param sql String 查询语句
* @param args Object... 如果sql中有?,即根据条件查询,可以设置?的值
* @param <T> 泛型方法声明的泛型类型
* @return List<T> 把多个对象放到了List集合
*/
protected <T> List<T> getList(Class<T> clazz, String sql, Object... args){
try {
return queryRunner.query(JDBCTools.getConnection(),sql,new BeanListHandler<T>(clazz),args);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
protected Object getValue(String sql,Object... args){
try {
return queryRunner.query(JDBCTools.getConnection(),sql,new ScalarHandler<>(),args);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
5.3 其他的DAO和DAO实现类不变
1、再次运行部门DAO测试类:OK
2、再次运行员工DAO测试类:OK
3、再次测试之前的事务问题:OK(就修改最后一句关闭代码)
package com.atguigu.test;
import com.atguigu.bean.Department;
import com.atguigu.dao.impl.DepartmentDAOImpl;
import com.atguigu.tools.JDBCTools;
import org.junit.Test;
import java.sql.Connection;
public class TestTransaction {
@Test
public void test01()throws Exception{
DepartmentDAOImpl dao = new DepartmentDAOImpl();
Connection connection = JDBCTools.getConnection();
connection.setAutoCommit(false);
try {
Department dept1 = dao.getByDid(1);
dept1.setDescription("部门1的简介");
System.out.println("第一条记录修改:" +dao.updateDepartment(dept1));
Department dept2 = dao.getByDid(2);
dept2.setDname(dept1.getDname());//故意修改为和部门1的名称一样,制造异常
System.out.println("第一条记录修改:" +dao.updateDepartment(dept2));
System.out.println("都成功");
connection.commit();
} catch (Exception e) {
e.printStackTrace();
System.out.println("失败");
connection.rollback();
}
JDBCTools.freeConnection();//方法调用不用传参数了
}
}
5.4 给员工DAO增加一个查询所有员工数量的方法
5.4.1 员工DAO接口
package com.atguigu.dao;
import com.atguigu.bean.Employee;
import java.util.List;
public interface EmployeeDAO {
//添加一个员工
boolean addEmployee(Employee employee);
//根据员工编号查询一个员工对象
Employee getByEid(int eid);
//根据员工编号删除一个员工对象,即删除一条记录
boolean removeEmployee(int eid);
//查询所有的员工对象
List<Employee> getAll();
//查询所有员工数量的方法
long getEmployeeCount();
//其他方法略
}
5.4.2 员工DAO接口实现类
package com.atguigu.dao.impl;
import com.atguigu.bean.Employee;
import com.atguigu.dao.EmployeeDAO;
import java.util.List;
public class EmployeeDAOImpl extends BaseDAOImpl implements EmployeeDAO {
@Override
public boolean addEmployee(Employee employee) {
String sql = "insert into t_employee(`eid`,`ename`,`salary`,`commission_pct`,`birthday`," +
"`gender`,`tel`,`email`,`address`,`work_place`,`hiredate`,`job_id`,`mid`,`did`)" +
"values(null,?,?,?,?,?,?,?,?,?,?,?,?,?)";//null表示eid是自增的
return update(sql,employee.getEname(),
employee.getSalary(),
employee.getCommissionPct(),
employee.getBirthday(),
employee.getGender(),
employee.getTel(),
employee.getEmail(),
employee.getAddress(),
employee.getWorkPlace(),
employee.getHiredate(),
employee.getJobId(),
employee.getMid(),
employee.getDid()
)>0;
}
@Override
public Employee getByEid(int eid) {
// String sql = "select * from t_employee where eid = ?";
String sql = "SELECT `eid`,`ename`,`salary`,`commission_pct` AS commissionPct,`birthday`,`gender`,`tel`,`email`,`address`,`work_place` AS workPlace,`hiredate`,`job_id` AS jobId,`mid`,`did` FROM t_employee where eid = ?";
return getBean(Employee.class,sql,eid);
}
@Override
public boolean removeEmployee(int eid) {
String sql = "delete from t_employee where eid = ?";
return update(sql,eid)>0;
}
@Override
public List<Employee> getAll() {
// String sql = "select * from t_employee";
String sql = "SELECT `eid`,`ename`,`salary`,`commission_pct` AS commissionPct,`birthday`,`gender`,`tel`,`email`,`address`,`work_place` AS workPlace,`hiredate`,`job_id` AS jobId,`mid`,`did` FROM t_employee";
return getList(Employee.class,sql);
}
@Override
public long getEmployeeCount() {
String sql = "select count(*) from t_employee";
return (Long) getValue(sql);//Object不能直接强转为long,只能转为Long包装类,然后在自动拆箱
}
}
5.5.3 测试员工DAO实现类
package com.atguigu.test;
import com.atguigu.bean.Employee;
import com.atguigu.dao.impl.EmployeeDAOImpl;
import org.junit.Test;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Scanner;
public class TestEmployeeDAOImpl {
@Test
public void test01(){
//先测试查询所有员工对象
EmployeeDAOImpl dao = new EmployeeDAOImpl();
List<Employee> all = dao.getAll();
all.forEach(System.out::println);
/*
(1)java.lang.RuntimeException: java.lang.NoSuchFieldException: commission_pct
原因:mysql的atguigu库,t_employee表中 奖金比例字段名是 commission_pct
而Javabean Employee类中奖金比例是commissionPct
如何解决?
编写特殊的sql,在select语句中给表的字段取别名,
select commission_pct as commissionPct
公共的查询方法getList和getBean方法中,反射获取Field对象是根据ResultSet结果集中的表头来确定属性名。
String columnName = metaData.getColumnName(i);
换成
String columnName = metaData.getColumnLabel(i);
(2)java.lang.RuntimeException: java.lang.IllegalArgumentException:
Can not set double field com.atguigu.bean.Employee.commissionPct to java.math.BigDecimal。
原因:mysql的atguigu库,t_employee表中 奖金比例字段数据类型是decimal,对应Java的java.math.BigDecimal,不是double。
(3)java.lang.RuntimeException: java.lang.IllegalArgumentException:
Can not set char field com.atguigu.bean.Employee.gender to java.lang.String
原因:mysql的atguigu库,t_employee表中 gender是enum('男','女'),对应Java的String类型
其实就算是 t_employee表中 gender是char类型,也是对应Java的String类型,因为mysql的char可以存储多个字符char(M),必须用String类型
(4)java.lang.RuntimeException: java.lang.IllegalArgumentException:
Can not set int field com.atguigu.bean.Employee.jobId to null value
原因:mysql的atguigu库,t_employee表中 job_id是int类型,但是mysql中的int类型可以设置NULL中,
而Java中的int类型是不能设置为null,所以的mysql中的int要用Java的Integer对应
类似的还有:double等
*/
}
@Test
public void test02(){
//测试查询一个员工的方法
EmployeeDAOImpl dao = new EmployeeDAOImpl();
Scanner input = new Scanner(System.in);
System.out.print("请输入要查询的员工的编号:");
int eid = input.nextInt();
Employee employee = dao.getByEid(eid);
System.out.println(employee);
input.close();
}
@Test
public void test03(){
//测试删除一个员工的方法
EmployeeDAOImpl dao = new EmployeeDAOImpl();
Scanner input = new Scanner(System.in);
System.out.print("请输入要删除的员工的编号:");
int eid = input.nextInt();
System.out.println(dao.removeEmployee(eid));
input.close();
}
@Test
public void test04()throws Exception{
//测试添加员工方法
Scanner input = new Scanner(System.in);
System.out.print("请输入姓名:");
String ename = input.next();//李四
System.out.print("请输入薪资:");
double salary = input.nextDouble();//15000
System.out.print("请输入出生日期:");
String birthday = input.next();//1990-1-1
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
System.out.print("请输入性别:");
String gender = input.next();
System.out.print("请输入手机号码:");
String tel = input.next();//13578595685
System.out.print("请输入邮箱:");
String email = input.next();//zhangsan@atguigu.com
EmployeeDAOImpl dao = new EmployeeDAOImpl();
//sf.parse(birthday)把字符串的日期转为Date类型的日期
Employee emp = new Employee(ename,salary,sf.parse(birthday),gender,tel,email,"北京",new Date());
System.out.println(dao.addEmployee(emp));
input.close();
}
@Test
public void test05(){
EmployeeDAOImpl dao = new EmployeeDAOImpl();
System.out.println(dao.getEmployeeCount());
}
}
补充学生问题: jar包版本不兼容
Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:408)
at com.mysql.jdbc.Util.getInstance(Util.java:383)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1023)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:997)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:983)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:928)
at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2576)
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2309)
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:834)
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:46)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:408)
at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:419)
at com.mysql.jdbc.NonRegisteringDriver.connect(Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
Exception in thread "main" java.sql.SQLException: The server time zone value '?й???????' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:73)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:76)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:835)
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:455)
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:240)
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:199)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:247)
.java:344)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:247)
看异常好像是无事务连接异常,无法创建连接。将MySQL驱动改为了最新的8.0版本的MySQL驱动。显示那个驱动类已经过时了,新的驱动类是“com.mysql.cj.jdbc.Driver”,而不是“com.mysql.jdbc.Driver”了,并且还说我没有配置时区,查了一下,原来从JDBC6.0开始驱动类使用了新的,并且url中必须要设置时区,否侧会报错。
第一步:使用最新的MySQL驱动jar包。
第二步:把驱动的类名改为:
static String driver="com.mysql.cj.jdbc.Driver";
第三步:在访问mysql的url后加入时区设置:
static String url="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF8&serverTimezone=UTC"
- 上一篇: 《JDBC》第12节:JDBC之事务的使用
- 下一篇: JDBC快速入门(一)(jdbc6个步骤)
猜你喜欢
- 2024-10-14 Java之Spring4:JDBC(java之父余胜军网站)
- 2024-10-14 《JDBC》第09节:JDBC之DatabaseMetaData数据库元数据对象
- 2024-10-14 《JDBC》第18节:JDBC之数据库连接池Hikari的使用(软编码方式)
- 2024-10-14 flink教程-详解flink 1.11 中的JDBC Catalog
- 2024-10-14 肝!Spring JDBC持久化层框架“全家桶”教程
- 2024-10-14 JDBC的基础使用(jdbc 教程)
- 2024-10-14 大数据开发基础之JAVA基础-JDBC基础知识
- 2024-10-14 JDBC基础整理(jdbc 教程)
- 2024-10-14 小白都能看懂的JDBC事务(jdbc实现事务管理)
- 2024-10-14 Spring JdbcTemplate讲解(spring的jdbc模板)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- css导航条 (66)
- sqlinsert (63)
- js提交表单 (60)
- param (62)
- parentelement (65)
- jquery分享 (62)
- check约束 (64)
- curl_init (68)
- sql if语句 (69)
- import (66)
- chmod文件夹 (71)
- clearinterval (71)
- pythonrange (62)
- 数组长度 (61)
- javafx (59)
- 全局消息钩子 (64)
- sort排序 (62)
- jdbc (69)
- php网页源码 (59)
- assert h (69)
- httpclientjar (60)
- postgresql conf (59)
- winform开发 (59)
- mysql数字类型 (71)
- drawimage (61)
本文暂时没有评论,来添加一个吧(●'◡'●)