├── README.md ├── sql2redis.iml └── src ├── META-INF └── MANIFEST.MF └── sql2redis ├── Controller.java ├── Main.java ├── models └── ImportTaskModel.java ├── sql2redis.fxml ├── sql2redis_img.jpg ├── style.css └── tasks └── ImportTask.java /README.md: -------------------------------------------------------------------------------- 1 | # sql-to-redis # 2 | 3 | 4 | Very simple Java app. My first usage of JavaFx. Created for my tests and development reasons. Sql-to-redis can be used to export and transform data from SQL tables to Redis key-value. 5 | 6 | ![picture](src/sql2redis/sql2redis_img.jpg) 7 | 8 | 9 | How to run: 10 | ----------- 11 | 12 | 1. (optional) Get the latest JRE from Oracle website. 13 | 2. (optional) If you are using OpenJDK (instead of OracleJDK) you probably have to install javafx packages (they are not included by default in OpenJDK), for Debian/Ubuntu this should help: 14 | ``` 15 | aptitude install openjfx 16 | ``` 17 | 3. Get latest sql-to-redis JAR file from [releases](https://github.com/mojeprojekty/sql-to-redis/releases) 18 | 4. Just check Java version (should be "1.8.0_112" or greater): 19 | ``` 20 | user@localhost:~$ java -version 21 | ``` 22 | 5. Go to downloaded JAR file and run command: 23 | ``` 24 | java -jar sql-to-redis.jar 25 | ``` 26 | 6. JDBC for: 27 | 28 | * MYSQL: jdbc:mysql://HOST:PORT/DBNAME 29 | 30 | * PostgreSQL: jdbc:postgresql://HOST:PORT/DBNAME 31 | 32 | DB support: 33 | ----------- 34 | | SQL databases | Support | 35 | | ------------- |:-------:| 36 | | PostgreSQL | Yes | 37 | | MySQL | Yes | 38 | | Oracle | Not yet | 39 | | SQL Server | Not yet | 40 | 41 | Details: 42 | ----------- 43 | * all queries run using Connection/ResultSets classes 44 | * fetchSize of Statement is hardcoded and it is set to 40,000 rows (import 7 milion rows takes few minutes, but if you have bigger tables you can decrease this value) 45 | * all connections to sql use Connection class from DriverManager 46 | * all imports are run as background task , threads 47 | 48 | 49 | How to use: 50 | ----------- 51 | * prepare connection string and setup sql/redis hosts, 52 | * choose table to import, 53 | * modify (if you want) JSON schema 54 | * choose redis key name (default value is table name) 55 | * choose redis suffix (value should be unique if not then you will override previouse keys, you can choose column value - so your SQL PK can be saved, default value is autoincrement id from loop) 56 | * in JSON schema, all $$words$$ are variables, they will be replaced on the fly with row values 57 | 58 | 59 | Thanks for drivers/dbs to: 60 | ----------- 61 | * Jedis (https://github.com/xetorthio/jedis), 62 | * PostgreSQL, 63 | * Redis. 64 | -------------------------------------------------------------------------------- /sql2redis.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: sql2redis.Main 3 | 4 | -------------------------------------------------------------------------------- /src/sql2redis/Controller.java: -------------------------------------------------------------------------------- 1 | package sql2redis; 2 | 3 | import javafx.animation.KeyFrame; 4 | import javafx.animation.Timeline; 5 | import javafx.collections.FXCollections; 6 | import javafx.collections.ObservableList; 7 | import javafx.event.ActionEvent; 8 | import javafx.event.EventHandler; 9 | import javafx.fxml.FXML; 10 | import javafx.scene.control.*; 11 | import javafx.util.Duration; 12 | import redis.clients.jedis.Jedis; 13 | import sql2redis.models.ImportTaskModel; 14 | import sql2redis.tasks.ImportTask; 15 | 16 | import java.sql.*; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | public class Controller { 21 | 22 | @FXML 23 | public PasswordField sqlPassword; 24 | 25 | @FXML 26 | public TextField sqlConnectionString, sqlUsername, redisHostname, redisPort, redisKeyName, redisAuth; 27 | 28 | @FXML 29 | public ListView tableList; 30 | 31 | @FXML 32 | public ChoiceBox redisSuffix; 33 | 34 | @FXML 35 | public Button importSqlToRedis, connect; 36 | 37 | @FXML 38 | public ListView tokenList; 39 | 40 | @FXML 41 | public TextArea jsonSchema; 42 | 43 | @FXML 44 | public TableView backgroundThreadsTable; 45 | 46 | @FXML 47 | private TextArea log; 48 | 49 | private Connection connection = null; 50 | 51 | private String selectedTable; 52 | 53 | private int selectedTableFetchSize = 0; 54 | 55 | private Jedis jedis; 56 | 57 | private boolean isRedisConnected = false; 58 | 59 | private boolean isSqlConnected = false; 60 | 61 | public int importCounter = 0; 62 | 63 | private List backgroundThreads = new ArrayList(); 64 | 65 | private List selectedTableColumns = new ArrayList<>(); 66 | 67 | @FXML 68 | private void initialize() { 69 | this.log.setEditable(false); 70 | this.tokenList.setMouseTransparent(true); 71 | this.tokenList.setFocusTraversable(false); 72 | 73 | Timeline fiveSecondsWonder = new Timeline(new KeyFrame(Duration.seconds(1), new EventHandler() { 74 | @Override 75 | public void handle(ActionEvent event) { 76 | getThreadsSize(); 77 | } 78 | })); 79 | fiveSecondsWonder.setCycleCount(Timeline.INDEFINITE); 80 | fiveSecondsWonder.play(); 81 | } 82 | 83 | public void connect() { 84 | this.redisConnect(); 85 | this.sqlConnect(); 86 | if (this.isSqlConnected && this.isRedisConnected) { 87 | this.getTableList(); 88 | } 89 | } 90 | 91 | private void getTableList() { 92 | try { 93 | DatabaseMetaData dmd = this.connection.getMetaData(); 94 | String[] systemName = {"TABLE", "VIEW", "VIEWS"}; 95 | ResultSet rs = dmd.getTables(null, null, "%", systemName); 96 | ArrayList tmpTables = new ArrayList(); 97 | while (rs.next()) { 98 | tmpTables.add(rs.getString(3)); 99 | } 100 | this.tableList.setItems(FXCollections.observableArrayList(tmpTables)); 101 | } catch (Exception e) { 102 | this.log("error", e.getMessage()); 103 | } 104 | } 105 | 106 | public void selectTableList() { 107 | if (tableList.getItems().size() == 0) { 108 | return; 109 | } 110 | String tableName = tableList.getSelectionModel().getSelectedItem().toString(); 111 | this.selectedTable = tableName; 112 | this.redisKeyName.setText(tableName); 113 | this.getTableInfo(tableName); 114 | this.tokenList.setVisible(true); 115 | this.setTokenlist(); 116 | this.prepareJsonSchema(); 117 | this.log("info", "Rows count: " + this.selectedTableFetchSize); 118 | this.selectedTableColumns.add("Auto-increment id"); 119 | this.redisSuffix.setItems(FXCollections.observableArrayList(this.selectedTableColumns)); 120 | this.redisSuffix.setValue("Auto-increment id"); 121 | this.importSqlToRedis.setDisable(false); 122 | } 123 | 124 | private void log(String type, String text) { 125 | this.log.appendText("[" +type.toUpperCase()+ "] "+ text +"\n"); 126 | } 127 | 128 | private void getTableInfo(String tableName) { 129 | try { 130 | DatabaseMetaData dmd = this.connection.getMetaData(); 131 | ResultSet resultSet = dmd.getColumns(null, null, tableName, "%"); 132 | List columns = new ArrayList<>(); 133 | while (resultSet.next()) { 134 | columns.add(resultSet.getString(4)); 135 | } 136 | this.selectedTableColumns = columns; 137 | 138 | String sql = "SELECT count(*) as total FROM $tableName".replace("$tableName", tableName); 139 | Statement stmt = this.connection.createStatement(); 140 | ResultSet resultSetCount = stmt.executeQuery(sql); 141 | while (resultSetCount.next()) { 142 | this.selectedTableFetchSize = resultSetCount.getInt("total"); 143 | } 144 | } catch (SQLException e) { 145 | this.log("error", e.getMessage()); 146 | } 147 | } 148 | 149 | private void sqlConnect() { 150 | try { 151 | String connectionString = this.sqlConnectionString.getText(); 152 | String username = this.sqlUsername.getText(); 153 | String password = this.sqlPassword.getText(); 154 | this.connection = DriverManager.getConnection(connectionString, username, password); 155 | this.connect.setText("Reconnect"); 156 | this.isSqlConnected = true; 157 | this.log("info", "Successfully connected to sql database"); 158 | } catch (Exception e) { 159 | this.log("error", e.getMessage()); 160 | } 161 | } 162 | 163 | private void redisConnect() { 164 | try { 165 | String hostname = this.redisHostname.getText(); 166 | int port = Integer.parseInt(this.redisPort.getText()); 167 | this.jedis = new Jedis(hostname, port); 168 | this.jedis.connect(); 169 | if (this.jedis.isConnected()) { 170 | this.isRedisConnected = true; 171 | this.log("info", "Successfully connected to redis"); 172 | } else { 173 | this.log("error", "The connection to the redis has failed"); 174 | } 175 | } catch (Exception e) { 176 | this.log("error", e.getMessage()); 177 | } 178 | } 179 | 180 | final public void getThreadsSize() { 181 | for (int i = 0, j = this.backgroundThreads.size(); i < j; i++) { 182 | Thread tmpThread = this.backgroundThreads.get(i); 183 | this.backgroundThreadsTable.getItems().forEach(item -> { 184 | if (item.getName().equals(tmpThread.getName())) { 185 | item.setStatus(tmpThread.getState().toString()); 186 | } 187 | }); 188 | ObservableList tableSource = this.backgroundThreadsTable.getItems(); 189 | FXCollections.copy(this.backgroundThreadsTable.getItems(), tableSource); 190 | } 191 | } 192 | 193 | public void importSqlToRedis() { 194 | String sqlUrl = this.sqlConnectionString.getText(); 195 | String sqlUser = this.sqlUsername.getText(); 196 | String sqlPassword = this.sqlPassword.getText(); 197 | String redisHost = this.redisHostname.getText(); 198 | String redisPort = this.redisPort.getText(); 199 | String redisAuth = this.redisAuth.getText(); 200 | String tableToImport = this.selectedTable; 201 | String jsonSchema = this.jsonSchema.getText(); 202 | Boolean isAutoIncrementSuffix; 203 | String redisKeyBodySchema = this.redisKeyName.getText(); 204 | String redisKeySuffixSchema = this.redisSuffix.getSelectionModel().getSelectedItem().toString(); 205 | if (redisKeySuffixSchema.equals("Auto-increment id")) { 206 | isAutoIncrementSuffix = true; 207 | } else { 208 | isAutoIncrementSuffix = false; 209 | } 210 | 211 | ImportTask importTask = new ImportTask(sqlUrl, sqlUser, sqlPassword, redisHost, redisPort, tableToImport, jsonSchema, isAutoIncrementSuffix, redisKeySuffixSchema, redisKeyBodySchema, redisAuth); 212 | Thread th = new Thread(importTask); 213 | th.setName("Task" + this.importCounter); 214 | this.importCounter++; 215 | this.backgroundThreads.add(th); 216 | th.setDaemon(true); 217 | th.start(); 218 | this.log("info", "Started"); 219 | 220 | ImportTaskModel newTask = new ImportTaskModel(th.getName(), tableToImport, ImportTaskModel.translateState(th.getState().toString())); 221 | final ObservableList row = FXCollections.observableArrayList(newTask); 222 | this.backgroundThreadsTable.getItems().addAll(row); 223 | } 224 | 225 | private void setTokenlist() { 226 | this.tokenList.setItems(FXCollections.observableArrayList(this.selectedTableColumns)); 227 | } 228 | 229 | private void prepareJsonSchema() { 230 | StringBuilder jsonSchemaText = new StringBuilder(); 231 | jsonSchemaText.append("{\n"); 232 | for (int i = 0; i < this.selectedTableColumns.size(); i++) { 233 | String tmpName = this.selectedTableColumns.get(i); 234 | if (i == this.selectedTableColumns.size() - 1) { 235 | jsonSchemaText.append(" \""+tmpName+"\": " + "\"$$"+tmpName+"$$\"\n"); 236 | } else { 237 | jsonSchemaText.append(" \""+tmpName+"\": " + "\"$$"+tmpName+"$$\",\n"); 238 | } 239 | } 240 | jsonSchemaText.append("}"); 241 | this.jsonSchema.setText(jsonSchemaText.toString()); 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /src/sql2redis/Main.java: -------------------------------------------------------------------------------- 1 | /* 2 | SQL to Redis (sql-to-redis) 3 | Created for my tests and development reasons. Sql-to-redis can be used to export and transform data 4 | from sql database to redis. Redis keys are stored as JSON. 5 | */ 6 | package sql2redis; 7 | 8 | import javafx.application.Application; 9 | import javafx.fxml.FXMLLoader; 10 | import javafx.scene.Parent; 11 | import javafx.scene.Scene; 12 | import javafx.stage.Stage; 13 | 14 | import java.sql.DriverManager; 15 | 16 | public class Main extends Application { 17 | 18 | @Override 19 | public void start(Stage primaryStage) throws Exception{ 20 | Parent root = FXMLLoader.load(getClass().getResource("sql2redis.fxml")); 21 | primaryStage.setTitle("SQL2Redis - import data from SQL to Redis as JSON"); 22 | primaryStage.setScene(new Scene(root, 1024, 754)); 23 | primaryStage.setResizable(false); 24 | primaryStage.show(); 25 | } 26 | 27 | public static void main(String[] args) { 28 | try { 29 | DriverManager.registerDriver(new com.mysql.jdbc.Driver()); 30 | } catch (Exception e) { 31 | 32 | } 33 | launch(args); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/sql2redis/models/ImportTaskModel.java: -------------------------------------------------------------------------------- 1 | package sql2redis.models; 2 | 3 | 4 | public class ImportTaskModel { 5 | 6 | private String id; 7 | 8 | private String name; 9 | 10 | private String description; 11 | 12 | private String status; 13 | 14 | public ImportTaskModel(String name, String description, String status) { 15 | this.name = name; 16 | this.description = description; 17 | this.status = translateState(status); 18 | } 19 | public String getId() { 20 | return this.id; 21 | } 22 | 23 | public void setId(String id) { 24 | this.id = id; 25 | } 26 | 27 | public String getName() { 28 | return this.name; 29 | } 30 | 31 | public void setName(String name) { 32 | this.name = name; 33 | } 34 | 35 | public String getDescription() { 36 | return this.description; 37 | } 38 | 39 | public void setDescription(String description) { 40 | this.description = description; 41 | } 42 | 43 | public String getStatus() { 44 | return this.status; 45 | } 46 | 47 | public void setStatus(String status) { 48 | this.status = translateState(status); 49 | } 50 | 51 | public static String translateState(String status) { 52 | if (status.equals("TERMINATED")) { 53 | return "Done"; 54 | } else if(status.equals("RUNNABLE")) { 55 | return "Running"; 56 | } else if(status.equals("NEW")) { 57 | return "Waiting"; 58 | } else if(status.equals("BLOCKED")) { 59 | return "Waiting"; 60 | } else if(status.equals("WAITING")) { 61 | return "Waiting"; 62 | } else if(status.equals("TIMED_WAITING")) { 63 | return "Waiting"; 64 | } else if (status.equals("user_stop_action")) { 65 | return "Canceled"; 66 | } else { 67 | return ""; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/sql2redis/sql2redis.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 48 | 52 | 53 | 57 | 58 | 63 | 64 | 69 | 74 | 79 | 84 | 89 | 94 | 99 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /src/sql2redis/sql2redis_img.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaldoda/sql-to-redis/b0dbef9f1c20efd89ad7a8586d55df6ef3f7a1c4/src/sql2redis/sql2redis_img.jpg -------------------------------------------------------------------------------- /src/sql2redis/style.css: -------------------------------------------------------------------------------- 1 | #log { 2 | -fx-background-color: none; 3 | -fx-border-style: none; 4 | -fx-focus-color: transparent; 5 | -fx-faint-focus-color: transparent; 6 | } 7 | 8 | .list-view { 9 | -fx-font-size: 13px; 10 | } 11 | 12 | 13 | .text-area .content{ 14 | -fx-background-color: #45494A; 15 | } 16 | 17 | #jsonSchema { 18 | -fx-font-size: 13px; 19 | -fx-text-fill: #e7e7e7; 20 | -fx-font-weight: bolder; 21 | -fx-background-color: #45494A; 22 | } 23 | 24 | .text-field .content { 25 | -fx-prompt-text-fill: #e2e2e2; 26 | } 27 | 28 | #log { 29 | -fx-text-fill: #a2a2a2; 30 | } 31 | #log .content { 32 | -fx-background-color: #2B2B2B; 33 | } 34 | 35 | #sqlConnectionString { 36 | -fx-text-fill: #EBEBEB; 37 | -fx-font-weight: bold; 38 | } 39 | 40 | #sqlPassword { 41 | -fx-text-fill: #EBEBEB; 42 | -fx-font-weight: bold; 43 | } 44 | 45 | #sqlUsername { 46 | -fx-text-fill: #EBEBEB; 47 | -fx-font-weight: bold; 48 | } 49 | 50 | #redisHostname { 51 | -fx-text-fill: #EBEBEB; 52 | -fx-font-weight: bold; 53 | } 54 | 55 | #redisAuth { 56 | -fx-text-fill: #EBEBEB; 57 | -fx-font-weight: bold; 58 | } 59 | 60 | #redisPort { 61 | -fx-text-fill: #EBEBEB; 62 | -fx-font-weight: bold; 63 | } 64 | 65 | #redisKeyName { 66 | -fx-text-fill: #EBEBEB; 67 | -fx-font-weight: bold; 68 | } 69 | 70 | 71 | .table-view .filler { 72 | -fx-background-color: #7733ee; 73 | } 74 | 75 | .table-view .column-header .label { 76 | -fx-text-fill: #a2a2a2; 77 | -fx-background-color: #45494A; 78 | -fx-font-weight: bold; 79 | } 80 | 81 | .list-cell:filled:selected:focused, .list-cell:filled:selected { 82 | -fx-background-color: #2F65CA; 83 | -fx-text-fill: white; 84 | } 85 | 86 | .list-cell { 87 | -fx-text-fill: #aaaaaa; 88 | -fx-background-color: #414547; 89 | } 90 | 91 | .list-cell:even { 92 | -fx-text-fill: #aaaaaa; 93 | -fx-background-color: #3C3F41; 94 | } 95 | 96 | .list-cell:filled:hover { 97 | -fx-background-color: #2F65CA; 98 | -fx-text-fill: white; 99 | } 100 | 101 | .hide-thumb .scroll-bar:vertical .thumb { 102 | -fx-background-color: transparent; 103 | } 104 | 105 | .button { 106 | -fx-text-fill: #BBBBBB; 107 | -fx-font-size: 13px; 108 | -fx-font-weight: bold; 109 | -fx-background-color: #4A4F51; 110 | -fx-border-color: #2F65CA; 111 | -fx-border-radius: 3; 112 | 113 | } 114 | 115 | 116 | .button:hover { 117 | -fx-cursor: hand; 118 | } 119 | 120 | .choice-box { 121 | -fx-focus-color: transparent; 122 | -fx-font-size: 13px; 123 | -fx-font-weight: bold; 124 | -fx-background-color: #4A4F51; 125 | -fx-border-color: #595A5A; 126 | } 127 | 128 | .choice-box > * { 129 | -fx-text-fill: #BBBBBB; 130 | } 131 | 132 | 133 | .scroll-bar{ 134 | -fx-background-color: rgb(96,96,96); 135 | } 136 | .scroll-bar:horizontal .track, 137 | .scroll-bar:vertical .track { 138 | -fx-background-color: transparent; 139 | -fx-border-color:transparent; 140 | } 141 | .scroll-bar:vertical .track-background, 142 | .scroll-bar:horizontal .track-background { 143 | -fx-background-color: transparent; 144 | -fx-background-insets: 0; 145 | } 146 | .scroll-bar:horizontal .thumb { 147 | -fx-background-color: #545657; 148 | -fx-background-insets: 4 0 4 0; 149 | } 150 | .scroll-bar:vertical .thumb { 151 | -fx-background-color: #545657; 152 | -fx-background-insets: 0 4 0 4; 153 | } 154 | .scroll-bar:horizontal .thumb:hover, 155 | .scroll-bar:vertical .thumb:hover { 156 | -fx-background-color: #545657; 157 | } 158 | .scroll-bar:horizontal .thumb:pressed, 159 | .scroll-bar:vertical .thumb:pressed { 160 | -fx-background-color: #545657; 161 | } 162 | .scroll-bar:vertical .increment-button, .scroll-bar:vertical .decrement-button { 163 | -fx-background-color:transparent; 164 | -fx-padding: 1; 165 | } 166 | .scroll-bar:horizontal .increment-button, .scroll-bar:horizontal .decrement-button { 167 | -fx-background-color:transparent; 168 | -fx-padding: 1; 169 | } 170 | .scroll-bar:horizontal .increment-arrow { 171 | -fx-shape: "M 0 0 L 4 8 L 8 0 Z"; 172 | -fx-background-color: #545657; 173 | 174 | } 175 | .scroll-bar:vertical .increment-arrow { 176 | -fx-background-color: #545657; 177 | -fx-shape: "M 0 0 L 4 8 L 8 0 Z"; 178 | 179 | } 180 | .scroll-bar:horizontal .decrement-arrow { 181 | -fx-background-color: #545657; 182 | 183 | } 184 | .scroll-bar:vertical .decrement-arrow { 185 | -fx-background-color: #545657; 186 | 187 | } 188 | .scroll-bar:vertical:focused, 189 | .scroll-bar:horizontal:focused { 190 | -fx-background-color: transparent,rgb(96,96,96),rgb(96,96,96); 191 | } 192 | 193 | 194 | .table-view { 195 | -fx-background-color: #3C3F41; 196 | -fx-text-fill: #e7e7e7 ; 197 | } 198 | .table-cell { 199 | -fx-text-fill: #e7e7e7 ; 200 | } 201 | 202 | .table-view:focused .table-row-cell:filled:focused:selected { 203 | -fx-background-color: #414547; 204 | -fx-background-insets: 0, 1, 2; 205 | -fx-background: -fx-accent; 206 | -fx-text-fill: -fx-selection-bar-text; 207 | } 208 | 209 | /* Selected row when table not focused */ 210 | .table-row-cell:filled:focused:selected { 211 | -fx-background-color: #414547; 212 | -fx-background-insets: 0, 1, 2; 213 | -fx-background: -fx-accent; 214 | -fx-text-fill: -fx-selection-bar-text; 215 | } 216 | 217 | .table-view:row-selection .table-row-cell:filled:hover { 218 | -fx-background-color: #414547; 219 | -fx-background-insets: 0, 0 0 1 0; 220 | -fx-text-fill: -fx-text-inner-color; 221 | } 222 | 223 | .table-view:focused .table-row-cell:filled:focused:selected:hover { 224 | -fx-background: -fx-accent; 225 | -fx-background-color: #414547; 226 | -fx-background-insets: 0, 1, 2; 227 | -fx-text-fill: -fx-selection-bar-text; 228 | } 229 | 230 | .table-view:row-selection .table-row-cell:filled:focused:hover { 231 | -fx-background-color: #414547; 232 | -fx-background-insets: 0, 0 0 1 0, 1 1 2 1, 2 2 3 2, 3 3 4 3; 233 | -fx-text-fill: -fx-text-inner-color; 234 | } 235 | 236 | .table-row-cell { 237 | -fx-background-color: #2B2B2B; 238 | } 239 | .table-row-cell:selected { 240 | -fx-background-color: #414547; 241 | } 242 | .table-row-cell:even .table-cell { 243 | -fx-fill: #414547; 244 | -fx-background-color: #3b3b3b; 245 | -fx-text-fill: #BBBBBB ; 246 | } -------------------------------------------------------------------------------- /src/sql2redis/tasks/ImportTask.java: -------------------------------------------------------------------------------- 1 | package sql2redis.tasks; 2 | 3 | 4 | import javafx.concurrent.Task; 5 | import redis.clients.jedis.Jedis; 6 | 7 | import java.sql.*; 8 | 9 | public class ImportTask extends Task { 10 | private final String sqlUrl, sqlUser, sqlPassword, redisHost, redisPort, redisKeySuffixSchema, redisKeyBodySchema, tableToImport, jsonSchema, redisAuth; 11 | private final Boolean isAutoIncrementSuffix; 12 | 13 | 14 | 15 | public ImportTask(String sqlUrl, String sqlUser, String sqlPassword, String redisHost, String redisPort, String tableToImport, String jsonSchema, Boolean isAutoIncrementSuffix, String redisKeySuffixSchema, String redisKeyBodySchema, String redisAuth) { 16 | this.sqlUrl = sqlUrl; 17 | this.sqlUser = sqlUser; 18 | this.sqlPassword = sqlPassword; 19 | this.redisHost = redisHost; 20 | this.redisPort = redisPort; 21 | this.redisAuth = redisAuth; 22 | this.jsonSchema = jsonSchema; 23 | this.tableToImport = tableToImport; 24 | this.isAutoIncrementSuffix = isAutoIncrementSuffix; 25 | this.redisKeySuffixSchema = redisKeySuffixSchema; 26 | this.redisKeyBodySchema = redisKeyBodySchema; 27 | System.out.println("Task, constructor"); 28 | } 29 | 30 | @Override protected Integer call() throws Exception { 31 | int counter = 0; 32 | try { 33 | System.out.println("Task, call method"); 34 | Connection connection = DriverManager.getConnection(this.sqlUrl, this.sqlUser, this.sqlPassword); 35 | Jedis jedis = new Jedis(this.redisHost, Integer.parseInt(this.redisPort)); 36 | if (!this.redisAuth.equals("")) { 37 | jedis.auth(this.redisAuth); 38 | } 39 | String sql = "SELECT * FROM $tableName".replace("$tableName", this.tableToImport); 40 | Statement stmt = connection.createStatement(); 41 | connection.setAutoCommit(false); 42 | stmt.setFetchSize(40000); 43 | ResultSet rs = stmt.executeQuery(sql); 44 | 45 | ResultSetMetaData rsmd = rs.getMetaData(); 46 | int columnCount = rsmd.getColumnCount(); 47 | 48 | while (rs.next()) { 49 | String jsonRow = jsonSchema; 50 | counter++; 51 | for (int i = 1; i <= columnCount; i++ ) { 52 | String name = rsmd.getColumnName(i); 53 | if (rs.getString(name) == null) { 54 | jsonRow = jsonRow.replace("$$"+name+"$$", ""); 55 | } else { 56 | jsonRow = jsonRow.replace("$$"+name+"$$", rs.getString(name).replace("\"", "'")); 57 | } 58 | } 59 | String out = jsonRow.replaceAll("\\s+","").replace("\n", "").replace("\r", "").replace("\\/", "/").trim(); 60 | out = out.replaceAll("\\\\/", "/").replace("\\", "").replaceAll ("\\\\", "").replace('\\','/'); 61 | if (this.isAutoIncrementSuffix) { 62 | jedis.set(this.redisKeyBodySchema+"_"+counter, out); 63 | } else { 64 | jedis.set(this.redisKeyBodySchema+"_"+rs.getString(this.redisKeySuffixSchema), out); 65 | } 66 | 67 | } 68 | connection.close(); 69 | jedis.close(); 70 | } catch (Exception e) { 71 | System.out.println(e.getMessage()); 72 | } 73 | return counter; 74 | } 75 | } --------------------------------------------------------------------------------