1. Prefacio
Al usar Java para desarrollar el software de aplicaciones empresariales, Spring+MyBatis+MySQL a menudo se usa para crear un marco de la base de datos. Si el volumen de datos es grande, una biblioteca MySQL almacena la eficiencia de acceso de datos muy baja, y a menudo utiliza el método de administración de almacenamiento de subrapositorio. Este artículo describe cómo construir una arquitectura de acceso a múltiples databás a través de Spring+MyBatis y usar múltiples subprocesos para mejorar la eficiencia de acceso a la base de datos.
Cabe señalar que este método solo es adecuado para situaciones en las que se fija el número de bases de datos y nombres, y no particularmente grandes. En respuesta a la situación en la que no se fija el número de bases de datos, escribiré otro plan de procesamiento más adelante.
2. Plan general
3. Preparación del entorno de desarrollo
3.1 Descargar componentes Spring, MyBatis, MySQL.
3.2 Eclipse: Java Development IDE. Se introducen los siguientes paquetes JAR:
La estructura del código es la siguiente:
4. Cree un clúster de base de datos
Cree 11 bases de datos en MySQL (Test1/2/3/4/5/6/7/8/11/10/11) para crear una tabla simple:
Inserte 50 millones de datos en la tabla TBL_DEMO en Test1 y 5 millones de datos en la tabla TBL_DEMO en las otras 10 bases de datos (usando funciones).
Inserte 50 millones de datos en la tabla TBL_DEMO en Test1 y 5 millones de datos en la tabla TBL_DEMO en las otras 10 bases de datos (usando funciones).
5. Cree la interfaz de mapeo de bases de datos mybatis
/** * Interfaz de mapeo mybatis * * * @author elon * @version 1.0, 23 de octubre de 2015 */pública interfaz idemo {public void insertDemo (demodao demo); Lista pública <integer> selectGroup ();}/** * * Interfaz de servicio de mapeo MyBatis * * @author elon * @version 1.0, 23 de octubre de 2015 */Interfaz pública IdemaService {public void InsertDemo (Demodao Demo); Lista pública <integer> selectGroup ();}/** * * Implementación del servicio de mapeo mybatis * * @author elon * @version 1.0, 23 de octubre de 2015 */clase public demoserviceImpl implementa IdemaService {private ideMo Idea = null; public void setidemo (Idea idemo) {this.idemo = Idea; } @Override public void InsertDemo (demooo demo) {ideamo.insertDemo (demo); } @Override Public List <Integer> selectGroup () {return Idea.SelectGroup (); }}6. Crear gestión de identidad de base de datos y fuentes de datos dinámicos
/** * * Guardar la ID de base de datos. Cada hilo está almacenado por un objeto independiente * * @author elon * @version 1.0, 23 de octubre de 2015 */public class dbindetifier {private static threadlocal <tring> dbkey = new ThreadLocal <string> (); public static void setdbkey (String final dbkeyypara) {dbkey.set (dbKeyPara); } public static string getDbkey () {return dbkey.get (); }}/*** fuente de datos dinámicos. Se pueden conectar diferentes bases de datos de acuerdo con diferentes índices de datos * * @author Elon * @version 1.0, 23 de octubre de 2015 */public class DynamicDataSource extiende abstrutingdataSource {@Override Public Object DetetInecurrentOpkey () {return dBindetifier.getDbKey (); }}7. Crear objeto de acceso a la base de datos
/** * * Objeto de acceso a la base de datos. Utilizado para insertar datos. * * @author elon * @version 1.0, 23 de octubre de 2015 */public class DeModao {private int a; cadena privada B; privado int c; public int geta () {return a; } public void seta (int a) {this.a = a; } public String getB () {return b; } public void setb (String b) {this.b = b; } public int getc () {return c; } public void setc (int c) {this.c = c; }}/** * Definición de resultados de asignación * * @author elon * @version 1.0, 23 de octubre de 2015 */public class Demoresult implementa serializable {/** * comentario para <code> serialversionUid </code> <br> * */private estático final de serialverSionUid = -413001138792531448l; larga suma privada; public Long getsum () {Sum de retorno; } public void setSum (larga suma) {this.sum = sum; } @Override public string toString () {return String.ValueOf (suma); }}8. Cree tareas de acceso a la base de datos
/*** Definición de tarea de acceso a la base de datos. Empaque cada solicitud al acceso a la base de datos en un objeto de tarea, colóquelo en la administración de tareas y luego espere a que la ejecución de la tarea complete y recupere el resultado de la ejecución. * * @author elon * @version 1.0, 23 de octubre de 2015 */public class dBTkask implementa runnable {// Operation Database Identity, utilizado para especificar la base de datos accedida. De acuerdo con la definición de fuente de datos dinámico de datos en el archivo de configuración de Spring. Cadena final privada DBKey; // Objeto de acceso a la base de datos mybatis Objeto final DBACSOBECTOCSOBJECT; // Nombre del método de acceso a la base de datos mySbatis, utilizado para reflejar el nombre de método de cadena final privada de llamadas; // almacenar el valor de los parámetros variables objeto final privado [] paraarray; // Almacene el tipo de parámetro variable @SupplesSwarnings ("RawTypes") Clase final privada [] paraclassArray; // Resultado de la operación de la base de datos. La operación de consulta devuelve el resultado de la consulta; El Insertar, Eliminar y Modificar Operaciones Devuelve NULL. objeto privado operadorSult; // Información de excepción lanzada por la Operación de la base de datos Private Exception Exception; // Identificar si la tarea ha sido ejecutada por el final privado booleano; / *** constructor* @param dbkey ID de base de datos* @param dBaccessObject Base de datos Objeto de acceso* @param MethodName Método de acceso a la base de datos* @param paraarray parameter list*/ public dBTkask (final string dbkey, objeto final dbaccessObject, string string metodname, objeto final ... paraarray) {this.dbkey = dbkey = dbkey = dbkey; this.dbaccessObject = dBaccessObject; this.methodName = MethodName; this.paraarray = paraarray; acabado = falso; excepción = nulo; paraclassArray = nueva clase [paraarray.length]; for (int index = 0; index <paraarray.length; ++ index) {paraclassArray [index] = paraarray [index] .getClass (); } operateresult = null; } / *** Función de ejecución de tareas** / @Override public void run () {try {dbindetifier.setdbkey (dbkey); Método método = dbaccessObject.getClass (). GetMethod (MethodName, ParacLassArray); // La operación de consulta devuelve el resultado de la consulta; El Insertar, Eliminar y Modificar Operaciones Devuelve NULL OperaterSult = Method.Invoke (dBAccessObject, paraarray); } capt (excepción e) {excepción = e; E.PrintStackTrace (); } final = verdadero; } /** * * Devuelve el resultado de la operación. La operación de consulta devuelve los resultados de la consulta; Insertar, eliminar y modificar las operaciones return null * * @return Operation Result */ Public Object getRetValue () {return OperaterSult; } / *** Excepción de operación de base de datos** @return excepción* / public excepción getException () {excepción de retorno; } / **** return si la tarea ha sido ejecutada** @return etiqueta* / public boolean isfinish () {return final; }}9. Cree un administrador de tareas de base de datos
/*** Gestión de tareas de acceso a la base de datos. Ponga la tarea de acceso a la base de datos en el grupo de subprocesos para ejecutar. * * * @author elon * @version 1.0, 23 de octubre de 2015 */clase pública dBTaskmgr {clase privada estática dBTaskMgrinStance {public static final dBTaskmgr instancia = new dBTaskMgr (); } public static dBTaskmgr instancia () {return dBTaskMgrinStance.Instance; } piscina privada ThreadpoolExecutor; public dBTaskMgr () {piscina = new ThreadPoolExecutor (10, 50, 60, TimeUnit.Seconds, New ArrayBlockingqueue <Runnable> (10000), New ThreadPoolExecutor.callerrunSpolicy ()); } public void Excute (tarea runnable) {piscal.execute (tarea); }}10. Cree un archivo de configuración de MyBatis
10.1 mybatis.xml
<? xml versión = "1.0" encoding = "utf-8"?> < Resource = "CFG/Demomapper.xml"/> </smpers> </figuration>
10.2 demomapper.xml
<? xml versión = "1.0" encoding = "utf-8"?> <! Doctype mapper public "-// mybatis.org//dtd mapper 3.0 // en" "http://mybatis.org/dtd/mybatis-3-mapper.dtdd"> <mepperspace = "com.elon.elon.emowem" id = "insertDemo" parametertype = "com.elon.demodao"> insertar en tbl_demo (a, b, c) valores ( #{a}, #{b}, #{c}); </sert> <resultmap id = "Demoresult" type = "com.elon.demoreSult"> <id propiedad = "sum" column = "sumcolum"/> </ resultmap> <select id = "selectGroup" resultMap = "Demoresult"> seleccione Sum (a) como sumcolum de TBL_DEMO Group by C; </select> </mapper>11. Cree un archivo de configuración de Spring
11.1 Spring.xml
<? xml versión = "1.0" encoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" "" "" xsi: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id = "dataSource_1"> <nombre de propiedad = "ClassClassName" value = "com.mysql.jdbc.driver"> </propiedad> <propiedad name = "url" value = "jdbc: mySql: //10.70.69.69: 3306/test1"> </Property> <Property Name = "Username" Value = "User123"> <///> <Nombre de propiedad = "Valor" Valor = "User123"> <<Propiedad de propiedad " name = "maxactive" value = "100"> </propiety> <Property name = "maxidle" value = "30"> </property <propiedad name = "maxwait" value = "500"> </prown> <Property name = "DefaultAutOcommit" value = "true"> </Property> </bean> <bean id = "dataSource_2"> <sperty name = "conductClaSname value = "com.mysql.jdbc.driver"> </propiedad> <propiedad name = "url" value = "jdbc: mySql: //10.70.69.69: 3306/test2"> </Property> <Property Name = "UserName" Value = "User123"> <///> <Nombre de propiedad = "Valor" Valor = "User123"> <<Propiedad de propiedad " name = "maxactive" value = "100"> </propiety> <Property name = "maxidle" value = "30"> </prown> <Property name = "maxwait" valor = "500"> </propiety> <Property name = "DefaultAutOcommit" value = "true"> </Property> </Bean> <bean Id = "DataSource_3"> <Property Name = "CLASENEMNAMEN value = "com.mysql.jdbc.driver"> </propiety> <Property name = "url" value = "jdbc: mySql: //10.70.69.69: 3306/test3"> </Property> <Property Name = "Username" Value = "User123"> <///> <Nombre de propiedad = "Valor" Valor = "User123"> <Propiedad de propiedades <Propiedad. name = "maxactive" value = "100"> </propiety> <Property name = "maxidle" value = "30"> </propiety> <Property name = "maxwait" value = "500"> </property> <Property name = "defaultAutOcommit" value = "true"> </Property> </bean> <bean id = "dataSource_4"> <sperty name = "rivilcleamname value = "com.mysql.jdbc.driver"> </propiedad> <propiedad name = "url" value = "jdbc: mySql: //10.70.69.69: 3306/test4"> </Property> <Property Name = "Username" Value = "User123"> <///> <Nombre de propiedad = "Valor" Value = "User123"> <<Propiedad de propiedad name = "maxactive" value = "100"> </propiety> <Property name = "maxidle" value = "30"> </propiety> <Property name = "maxwait" value = "500"> </property> <Property name = "DefaultAutOcommit" value = "true"> </Property> </bean> <bean id = "dataSource_5"> <sperty name = "rivilcleamname value = "com.mysql.jdbc.driver"> </propiedad> <propiedad name = "url" value = "jdbc: mySql: //10.70.69.69: 3306/test5"> </Property> <Property Name = "Username" Value = "User123"> <///> <Nombre de propiedad = "Valor" Valor = "User123"> <Propiedad de propiedades <Propiedad ". name = "maxactive" value = "100"> </propiety> <Property name = "maxidle" value = "30"> </property <Property name = "maxwait" valor = "500"> </propiety> <Property name = "DefaultAutOcommit" value = "true"> </Property> </bean> <bean id = "dataSource_6"> <sperty name = "rivilcleamname value = "com.mysql.jdbc.driver"> </propiedad> <propiedad name = "url" value = "jdbc: mySql: //10.70.69.69: 3306/test6"> </Property> <Property Name = "UserName" Value = "User123"> <///> <Nombre de propiedad = "Valor" Value = "User123"> <Propiedad de propiedad "<SeSame" name = "maxactive" value = "100"> </propiety> <Property name = "maxidle" value = "30"> </property <propiedad name = "maxwait" value = "500"> </property> <Property name = "DefaultAutOcommit" value = "true"> </Property> </Bean> <bean id = "DataSource_7"> <Property name = " value = "com.mysql.jdbc.driver"> </propiedad> <propiedad name = "url" value = "jdbc: mySql: //10.61.67.246: 3306/test7"> </propietS> <Property Name = "UserName" Value = "User123"> <//name de propiedad = "Nombre de propiedad" Value = "User123" name = "maxactive" value = "100"> </propiety> <Property name = "maxidle" value = "30"> </property <propiedad name = "maxwait" value = "500"> </property> <Property name = "DefaultAutOcommit" value = "true"> </Property> </bean> <bean id = "dataSource_8"> <sperty name = "rivilcleamname value = "com.mysql.jdbc.driver"> </propiedad> <propiedad name = "url" value = "jdbc: mySql: //10.61.67.246: 3306/test8"> </propietS> <Property name = "username" value = "user123"> <//name de propiedad = "Value =" Value = "user123" " name = "maxactive" value = "100"> </propiety> <Property name = "maxidle" value = "30"> </property <Property name = "maxwait" valor = "500"> </protper> <Property name = "defaultAutOcommit" value = "true"> </Property> </bean> <bean id = "dataSource_9"> <sperty name = "rivilcleamname value = "com.mysql.jdbc.driver"> </propiedad> <propiedad name = "url" value = "jdbc: mySql: //10.61.67.246: 3306/test9"> </Property> <Property Name = "UserName" Value = "User123"> <//name de propiedad = "Value" Value = "User123" name = "maxactive" value = "100"> </propiety> <Property name = "maxidle" value = "30"> </property <propiedad name = "maxwait" value = "500"> </property> <Property name = "defaultAutOcomMit" value = "true"> </Property> </Bean> <bean id = "dataSource_10"> <Property name = "conductClaSname value = "com.mysql.jdbc.driver"> </propiedad> <propiedad name = "url" value = "jdbc: mySql: //10.61.67.246: 3306/test10"> </propietS> <Property name = "username" value = "user123"> <//name de propiedad = "Value =" Value = "User123" name = "maxactive" value = "100"> </propiety> <Property name = "maxidle" value = "30"> </property <propiedad name = "maxwait" value = "500"> </property> <Property name = "DefaultAutOcommit" value = "true"> </Property> </bean> <bean id = "dataSource_11"> <sperty name = "rivilcleamname value = "com.mysql.jdbc.driver"> </propiedad> <propiedad name = "url" value = "jdbc: mySql: //10.61.67.246: 3306/test11"> </Property> <Property Name = "UserName" Value = "User123"> <//name de propiedad = "Value" Value = "User123" " name = "maxactive" value = "100"> </propiety> <Property name = "maxidle" value = "30"> </property <Property name = "maxwait" valor = "500"> </property> <Property name = "DefaultAutoCommit" value = "verdadero"> </Property> </Bean> <bean Id = "DataSource"> <Property Name = "TargetDataSources key = "test1" value-ref = "dataSource_1"/> <entry2 key = "test2" value-ref = "dataSource_2"/> <Entry key = "test3" value-ref = "dataSource_3"/> <entry key = "test4" value-ref = "dataSource_4"/> <<rinter = "test5" valle-ref = "datasource"/5 " key = "test6" value-ref = "dataSource_6"/> <entry7 key = "test7" value-ref = "dataSource_7"/> <entry Key = "test8" value-ref = "dataSource_8"/> <entry key = "test9" value-ref = "dataSource_9"/> <inyring = "test10" valle-ref = "datasource" /10 " key="test11" value-ref="dataSource_11"/> </map> </property> </bean> <bean id="sqlSessionFactory"> <property name="configLocation" value="classpath:cfg/mybatis.xml"></property> <property name="dataSource" ref="dataSource" /> </bean> <bean id="iDemo"> <property name = "mapperinterface" value = "com.elon.idemo"> </property> <Property name = "sqlSessionFactory" ref = "sqlSessionFactory"> </property> </le bean> <bean id = "idemoservice"> <Property name = "idemo" ref = "idemo"> </propiétame> </ beachs>
12. Código de prueba
Public Class TestMain {/** * Código de prueba * * * @param args */public static void main (string [] args) {@SupessWarnings ("Resource") ApplicationContext context = new ClassPathXMLApplicationContext ("CFG/Spring.xml"); IDEMOSERVICE SERVICE1 = (IDEMOSERVICE) context.getBean ("idemoservice"); // Crear objeto de tarea dBTask tarea1 = new dBTask ("test1", servicio1, "selectGroup"); DBTask Task2 = new DBTask ("Test2", Service1, "SelectGroup"); DBTASK TARK3 = new dBTask ("test3", servicio1, "selectGroup"); DBTASK TARK4 = new DBTask ("Test4", Service1, "SelectGroup"); DBTask tarea5 = new dBTask ("test5", servicio1, "selectGroup"); DBTASK Task6 = new DBTask ("Test6", Service1, "SelectGroup"); DBTASK TARK7 = new DBTask ("Test7", Service1, "SelectGroup"); DBTask tarea8 = new DBTask ("Test8", Service1, "SelectGroup"); DBTASK TARK9 = new DBTask ("Test9", Service1, "SelectGroup"); DBTask tareas10 = new DBTask ("Test10", Service1, "SelectGroup"); DBTASK Task11 = new DBTask ("Test11", Service1, "SelectGroup"); Demodao demo = new DeModao (); demo.seta (10000000); demo.setb ("12121212"); demo.setc (100); DBTask TaskInsert = new DBTask ("Test2", Service1, "InsertDemo", demo); SimpleDateFormat Format = new SimpleDateFormat ("yyyy-mm-dd hh: mm: ss"); System.out.println ("Iniciar insertar datos:" + format.format (new Date ())); DBTaskmgr.instance (). Excute (TaskInsert); while (true) {if (! TaskInsert.Isfinish ()) {try {Thread.sleep (1000); } catch (InterruptedException e) {E.PrintStackTrace (); }} else {break; }} System.out.println ("Insertar End de datos:" + format.format (new Date ())); System.out.println ("Comience a consultar la tabla de datos de 50 millones:" + format.format (nueva fecha ())); DBTaskmgr.instance (). Excute (Tarea1); while (true) {if (! task1.isfinish ()) {try {hild.sleep (1000); } catch (InterruptedException e) {E.PrintStackTrace (); }} else {break; }} System.out.println (task1.getRetValue ()); System.out.println ("consulta 50 millones de tabla de datos end:" + format.format (new Date ())); Lista <DBTask> TaskList = New ArrayList <DBTask> (); TaskList.Add (Tarea2); TaskList.Add (Tarea3); TaskList.Add (Tarea4); TaskList.Add (Tarea5); TaskList.Add (tarea 6); TaskList.Add (Tarea7); TaskList.Add (Tarea8); TaskList.Add (Tarea9); TaskList.Add (tarea10); TaskList.Add (tarea11); System.out.println ("Iniciar consulta 10 5 millones de tablas de datos:" + format.format (nueva fecha ())); para (tarea dBTask: tareas list) {dBTaskmgr.instance (). excute (tarea); } while (true) {int éxito = 0; for (dBTask Task: TaskList) {if (! task.isfinish ()) {try {thread.sleep (1000); } catch (InterruptedException e) {E.PrintStackTrace (); }} else {++ éxito; }} if (éxito == 10) {break; }} para (DBTask Task: TaskList) {System.out.println (task.getRetValue ()) ;; } System.out.println ("10 5 millones de la consulta de la tabla de datos finaliza:" +format.format (new Date ())); }}13. Resultados de la prueba
Se necesitan 45 para consultar directamente una base de datos de 50 millones de datos.
Se necesitan 22s para consultar 10 bases de datos con 5 millones de datos de manera síncrona.
Dado que se colocan 10 bases de datos en dos servidores, un servidor tiene 5 bases de datos. Si se implementan 10 datos en 10 servidores por separado, la eficiencia será aún mayor.
Resumir
Lo anterior es la introducción del editor a Spring+MyBatis+MySQL para construir un marco de acceso a la base de datos distribuido. Espero que sea útil para todos. Si tiene alguna pregunta, déjame un mensaje y el editor responderá a todos a tiempo. ¡Muchas gracias por su apoyo al sitio web de Wulin.com!