Happy Moment
On the day of Ching Ming Festival, I saw a kid burning paper on the roadside.
Sneaking a few exam papers into the fire every now and then
While burning, I read: Grandpa, you are old, do more problems over there, it's good for your brain, if you don't understand something, take my teacher away and let him teach you!
premise sth.
suppose that...MySQL 5.7.36
librariesqsl_datax
show that one is capable of doing sth.qsl_datax_source
and data
CREATE TABLE `qsl_datax_source` (
`id` bigint(20) NOT NULL COMMENT 'self-incrementing primary key', `username` varchar(255) NOT NULL COMMENT 'name', `qsl_datax_source'
`username` varchar(255) NOT NULL COMMENT 'name', `password` varchar(255) NOT NULL COMMENT
`password` varchar(255) NOT NULL COMMENT 'password', `birth_day` date NOT NULL COMMENT 'birth_day' date not NULL COMMENT
`birth_day` date NOT NULL COMMENT 'date of birth', `remark` text, `remark` text, `remark` text, `remark` text, `remark` text
`remark` text, `remark` text, `remark` text, `remark` text
PRIMARY KEY (`id`)
) ENGINE = InnoDB ;
INSERT INTO `qsl_datax_source` VALUES (1, 'zhang san', 'z123456', '1991-01-01', 'zhang san') ;
INSERT INTO `qsl_datax_source` VALUES (2, 'li4', 'l123456', '1992-01-01', 'li4');;
INSERT INTO `qsl_datax_source` VALUES (3, 'wang wu', 'w123456', '1993-01-01', 'wang wu');;
INSERT INTO `qsl_datax_source` VALUES (4, 'hempzi', 'm123456', '1994-01-01', 'hempzi');
You need to synchronize the data in the table to theMySQL 8.0.30
sql_db
librariesqsl_datax_source
table and only use theJDBC
of the way, how to realize it? You may find it very simple to just introduce themysql-connector-j
dependencies
<dependency>
<groupId></groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
Then write the synchronization code directly
public static void main(String[] args) throws Exception {
String url5 = "jdbc:mysql://192.168.2.118:3307/qsl_datax?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String url8 = "jdbc:mysql://192.168.2.118:3311/sql_db?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
Properties pro = new Properties();
("user", "root");
("password", "123456");
// Load Driver Class
("");
// establish a connection
Connection conn5 = (url5, pro);
// data search
Statement statement = ();
ResultSet resultSet = ("SELECT * FROM qsl_datax_source");
StringBuilder insertSql = new StringBuilder("INSERT INTO qsl_datax_source(id,username,password,birth_day,remark) VALUES ");
while (()) {
// put togethersql
("(")
.append(("id")).append(",")
.append("'").append(("username")).append("',")
.append("'").append(("password")).append("',")
.append("'").append(("birth_day")).append("',")
.append("'").append(("remark")).append("'")
.append("),");
}
// on account ofmysql5cap (a poem)mysql8The passwords are the same.,So it's the same one. pro
Connection conn8 = (url8, pro);
Statement stmt = ();
int count = ((0, () - 1));
("Number of new records inserted:" + count);
();
();
();
();
();
}
Post-execution output
Number of new records inserted: 4
existMySQL 8.0.30
librariessql_db
View Tableqsl_datax_source
data
Synchronized completion. Isn't that just a matter of having hands?
Generally speaking, a higher version of the driver will be compatible with a lower version of the database, but it is not absolute or incomplete; MySQL version, driver version, JDK version corresponds to the following relationship
The mysql-connector-j 8.0.33 driver is compatible with MySQL 5.7.36, so the above synchronization is fine, but if the MySQL version is very low (e.g., 5.), for example, from theMySQL 5.1.8
Synchronize toMySQL 8.0.30
Can the synchronization code as above still synchronize successfully (I'm not going to try, and neither should you, since the purpose of the derivation has already been achieved), so the insurance approach would be
mysql-connector-j 8.0.33 Operation MySQL 8.0.30
mysql-connector-java 5.1.49 Operation MySQL 5.7.36
mysql-connector-java 5. Operating MySQL 5.
So here's the problem.
How to insert data into MySQL 8.0.30 after checking data from MySQL 5.7.36 with mysql-connector-java 5.1.49 and then inserting it into MySQL 8.0.30 with mysql-connector-j 8.0.33
multi-driver operation
I'm sure it's easy for you, too. Go ahead and introduce it.mysql-connector-java 5.1.49
dependencies
<dependency>
<groupId></groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
Then adjust the code
public static void main(String[] args) throws Exception {
String url5 = "jdbc:mysql://192.168.2.118:3307/qsl_datax?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String url8 = "jdbc:mysql://192.168.2.118:3311/sql_db?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
Properties pro = new Properties();
("user", "root");
("password", "123456");
// Load Driver Class
("");
// establish a connection
Connection conn5 = (url5, pro);
// data search
Statement statement = ();
ResultSet resultSet = ("SELECT * FROM qsl_datax_source");
StringBuilder insertSql = new StringBuilder("INSERT INTO qsl_datax_source(id,username,password,birth_day,remark) VALUES ");
while (()) {
// put togethersql
("(")
.append(("id")).append(",")
.append("'").append(("username")).append("',")
.append("'").append(("password")).append("',")
.append("'").append(("birth_day")).append("',")
.append("'").append(("remark")).append("'")
.append("),");
}
("");
// on account ofmysql5cap (a poem)mysql8The passwords are the same.,So it's the same one. pro
Connection conn8 = (url8, pro);
Statement stmt = ();
int count = ((0, () - 1));
("Number of new records inserted:" + count);
();
();
();
();
();
}
Compare this with the previous code
Very little adjustment; the output after execution is as follows
Loading class `'. This is deprecated. The new driver class is `'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
Number of new records inserted:4
If you look at the results only, the synchronization did succeed, but the first line of thewarnings
It's worth thinking about.
Class Loading. This class has been deprecated. The new driver class is , which is automatically registered through the SPI mechanism and does not need to be loaded manually.
There are 2 questions that arise from this
- It shouldn't be.
mysql-connector-java 5.1.49
How did they get dumped? - What is the SPI mechanism.
When was it loaded?
Let's start with question 2. For more information on the SPI mechanism see
Remember a JDK SPI configuration does not take effect the problem → so simple can not, or go home to raise pigs!
DriverManager
There are static code blocks
static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}
loadInitialDrivers()
There is a code in
The driver is automatically loaded, and the driver class often has code similar to the following
Register the driver instance with theDriverManager
So you don't need to manually load the driver class anymore!
Starting with JDBC 4.0, JDBC drivers support autoloading and no longer require a call to load the driver.
Let's go back to question 1, the synchronized alarm message.
Loading class `'. This is deprecated. The new driver class is `'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
I'm sure it is.mysql-connector-j 8.0.33
Alarmed out becausemysql-connector-java 5.1.49
No class
Is that right? Do a global search.
This is deprecated. The new driver class is `'
Tap in and we'll findmysql-connector-j 8.0.33
There are also classes
Look carefully, this Driver is not registering its instance into the
(used form a nominal expression)
What does that mean? It means it's frommysql-connector-j 8.0.33
Loaded class:Instead of getting the information from the
mysql-connector-java 5.1.49
(of cargo etc) load
Let's run through the whole synchronization process
-
Through the SPI mechanism, files are loaded
META-INF/services/
Classes configured in theContents of the file mysql-connector-j 8.0.33
Contents of file mysql-connector-java 5.1.49
Class loader loading
is undoubtedly found in the mysql-connector-j 8.0.33 jar package, and loading the
The class loader found the one in the mysql-connector-j 8.0.33 jar package instead of the one in the mysql-connector-java 5.1.49 jar package, so it alerted the
-
Called manually in code
("");
Perform class loading, based on theParental Delegation Model
If the class has already been loaded, it will not be loaded again, so it is equivalent to not doing anything.The previous warning message was not triggered here! If you don't believe me, you can comment out that line of code and run it, and you'll see that you still get the same warning message!
-
To look up data from MySQL5, the driver used is actually the
Because that's the only driver that fits in the DriverManager.
-
Called manually in code
("");
Perform class loading, based on theParental Delegation Model
If the class has already been loaded, it will not be loaded again, so it is equivalent to not doing anything. -
To check data from MySQL8, the only driver you can use is no doubt the
So the whole synchronization, using the driver under mysql-connector-j 8.0.33, mysql-connector-java 5.1.49 is not used at all, is not in your expectation?
So how do we realize our original idea?
How to insert data into MySQL 8.0.30 after checking data from MySQL 5.7.36 with mysql-connector-java 5.1.49 and then inserting it into MySQL 8.0.30 with mysql-connector-j 8.0.33
maven-shade-plugin
Party A throws to the existence of two Jar packages with the same package name and class name, to be used in the project at the same time how to do? There are a number of solutions, but maven-shade-plugin is the optimal solution.
maven plugin maven-shade-plugin, to solve the problem of class coexistence in the same package with the same name of the gods!
Then how should come to the current case, in fact, very simple, just need to use maven-shade-plugin'sRetargeting class
It's just a function. Watch me.
-
Class relocation for mysql-connector-j 8.0.33
Create a new project
mysql-jdbc
There is no code and no configuration file.There's only one.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="/POM/4.0.0" xmlns:xsi="http:///2001/XMLSchema-instance" xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0."> <modelVersion>4.0.0</modelVersion> <groupId></groupId> <artifactId>mysql-jdbc8</artifactId> <version>8.0.33</version> <properties> <>8</> <>8</> <>UTF-8</> </properties> <dependencies> <dependency> <groupId></groupId> <artifactId>mysql-connector-j</artifactId> <version>8.0.33</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId></groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.6.0</version> <executions> <execution> <!-- cap (a poem) package Stage Binding --> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <relocations> <relocation> <pattern></pattern> <shadedPattern>.jdbc8</shadedPattern> </relocation> </relocations> <filters> <filter> <artifact>:mysql-jdbc8</artifact> <excludes> <exclude>META-INF/*.*</exclude> </excludes> </filter> </filters> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
mvn install
Deploy the repackaged jar to the local repository in one go -
Adjusting the maven dependencies of the sample code
mysql-connector-j 8.0.33 to mysql-jdbc8 8.0.33, mysql-connector-java 5.1.49 as is.
<dependencies> <dependency> <groupId></groupId> <artifactId>mysql-jdbc8</artifactId> <version>8.0.33</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.49</version> </dependency> </dependencies>
-
Adjustment of synchronization code
Remove manual driver loading, add connection driver information version output
public static void main(String[] args) throws Exception { String url5 = "jdbc:mysql://192.168.2.118:3307/qsl_datax?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai"; String url8 = "jdbc:mysql://192.168.2.118:3311/sql_db?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai"; Properties pro = new Properties(); ("user", "root"); ("password", "123456"); // establish a connection Connection conn5 = (url5, pro); // data search Statement statement = (); ("conn5 driver version: " + ().getDriverVersion()); ResultSet resultSet = ("SELECT * FROM qsl_datax_source"); StringBuilder insertSql = new StringBuilder("INSERT INTO qsl_datax_source(id,username,password,birth_day,remark) VALUES "); while (()) { // put togethersql ("(") .append(("id")).append(",") .append("'").append(("username")).append("',") .append("'").append(("password")).append("',") .append("'").append(("birth_day")).append("',") .append("'").append(("remark")).append("'") .append("),"); } // on account ofmysql5cap (a poem)mysql8The passwords are the same.,So it's the same one. pro Connection conn8 = (url8, pro); ("conn8 driver version: " + ().getDriverVersion()); Statement stmt = (); int count = ((0, () - 1)); ("Number of new records inserted:" + count); (); (); (); (); (); }
Processing is complete. Let's run it and see what happens.
The previous warning is indeed gone, but a new question arises: why is the driver using the same one, and why isn't the driver in mysql-connector-java 5.1.49 being used?
The one in mysql-connector-java 5.1.49 must have been loaded properly and registered with DriverManager, don't you agree? (It doesn't matter if you don't, we'll prove it later.) So why isn't it being used anymore? source code; source code to follow the more simple, I'll take you step by step with the final back to the following methods
#getConnection(, , <?>)
Inside this method is this code
for(DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then
// skip it.
if(isDriverAllowed(, callerCL)) {
try {
println(" trying " + ().getName());
Connection con = (url, info);
if (con != null) {
// Success!
println("getConnection returning " + ().getName());
return (con);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
} else {
println(" skipping: " + ().getName());
}
}
Let's make a break to follow (in the front!!!)
isDriverAllowed
The effect is to check that a givenDriver
Whether the object is allowed to pass the specifiedClassLoader
loading, we don't need to be concerned with that, but rather we need to be concerned with the
Connection con = (url, info);
Follow me in.#connect
Follow up if you're interested(url)
But I don't think it's necessary, it's obvious to match the url against the regular expression to see if it fits, since the MySQL5 url is in the same format as the MySQL8 one!
String url5 = "jdbc:mysql://192.168.2.118:3307/qsl_datax?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String url8 = "jdbc:mysql://192.168.2.118:3311/sql_db?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
I used it to connect to MySQL5 and MySQL8 because it was in the front of the queue.
Why is the driver using the same one, and why isn't the driver in mysql-connector-java 5.1.49 being used?
Isn't that clear? You may have another question: why isn't it in the first place? This has to do with the order in which classes are loaded, and is beyond the scope of this article. Does that still fulfill the original purpose?
Checking data from MySQL 5.7.36 with mysql-connector-java 5.1.49 and inserting data into MySQL 8.0.30 with mysql-connector-j 8.0.33
It's definitely possible. Watch me tweak the code.
public static void main(String[] args) throws Exception {
String url5 = "jdbc:mysql://192.168.2.118:3307/qsl_datax?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String url8 = "jdbc:mysql://192.168.2.118:3311/sql_db?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
Properties pro = new Properties();
("user", "root");
("password", "123456");
// establish a connection
Driver driver5 = getDriver("");
Connection conn5 = (url5, pro);
// data search
Statement statement = ();
("conn5 driver version: " + ().getDriverVersion());
ResultSet resultSet = ("SELECT * FROM qsl_datax_source");
StringBuilder insertSql = new StringBuilder("INSERT INTO qsl_datax_source(id,username,password,birth_day,remark) VALUES ");
while (()) {
// put togethersql
("(")
.append(("id")).append(",")
.append("'").append(("username")).append("',")
.append("'").append(("password")).append("',")
.append("'").append(("birth_day")).append("',")
.append("'").append(("remark")).append("'")
.append("),");
}
// on account ofmysql5cap (a poem)mysql8The passwords are the same.,So it's the same one. pro
Driver driver8 = getDriver("");
Connection conn8 = (url8, pro);
("conn8 driver version: " + ().getDriverVersion());
Statement stmt = ();
int count = ((0, () - 1));
("Number of new records inserted:" + count);
();
();
();
();
();
}
private static Driver getDriver(String driverClassName) {
Enumeration<Driver> drivers = ();
while (()) {
Driver driver = ();
if (().getName().equals(driverClassName)) {
return driver;
}
}
throw new RuntimeException("Driver not found:" + driverClassName);
}
Run it and see what happens.
At this point I'm just going to say: who else?
summarize
-
Sample code:mysql-driver-demo
Excluding code for mysql-jdbc8
-
As far as MySQL is concerned, the mysql-connector-j 8 driver is compatible with MySQL 5.5, 5.6, and 5.7, and it is possible to use mysql-connector-j 8 to connect to MySQL 5.7 in practice.
-
SQL Server has driver incompatibility.
Microsoft JDBC Driver for SQL Server Support Matrix
-
maven-shade-plugin to achieve the coexistence of multiple versions of the driver, simple and efficient, worth mastering!
maven plugin maven-shade-plugin, to solve the problem of class coexistence in the same package with the same name of the gods!