diff --git a/SerialPortCommJava/SerialPortCommJava.db b/SerialPortCommJava/SerialPortCommJava.db new file mode 100644 index 0000000..e69de29 diff --git a/SerialPortCommJava/pom.xml b/SerialPortCommJava/pom.xml index 8432807..ea94f91 100644 --- a/SerialPortCommJava/pom.xml +++ b/SerialPortCommJava/pom.xml @@ -106,6 +106,12 @@ jSerialComm 2.9.0 + + + org.xerial + sqlite-jdbc + 3.45.1.0 + diff --git a/SerialPortCommJava/src/main/java/com/rehome/serialportcommjava/config/SQLiteDialect.java b/SerialPortCommJava/src/main/java/com/rehome/serialportcommjava/config/SQLiteDialect.java new file mode 100644 index 0000000..7841bfa --- /dev/null +++ b/SerialPortCommJava/src/main/java/com/rehome/serialportcommjava/config/SQLiteDialect.java @@ -0,0 +1,330 @@ +package com.rehome.serialportcommjava.config; + +import org.hibernate.JDBCException; +import org.hibernate.ScrollMode; +import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.function.*; +import org.hibernate.dialect.identity.IdentityColumnSupport; +import org.hibernate.dialect.pagination.AbstractLimitHandler; +import org.hibernate.dialect.pagination.LimitHandler; +import org.hibernate.dialect.pagination.LimitHelper; +import org.hibernate.dialect.unique.DefaultUniqueDelegate; +import org.hibernate.dialect.unique.UniqueDelegate; +import org.hibernate.engine.spi.RowSelection; +import org.hibernate.exception.DataException; +import org.hibernate.exception.JDBCConnectionException; +import org.hibernate.exception.LockAcquisitionException; +import org.hibernate.exception.spi.SQLExceptionConversionDelegate; +import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter; +import org.hibernate.exception.spi.ViolatedConstraintNameExtracter; +import org.hibernate.internal.util.JdbcExceptionHelper; +import org.hibernate.mapping.Column; +import org.hibernate.type.StandardBasicTypes; + +import java.sql.SQLException; +import java.sql.Types; + +public class SQLiteDialect extends Dialect { + private final UniqueDelegate uniqueDelegate; + + public SQLiteDialect() { + registerColumnType(Types.BIT, "boolean"); + registerColumnType(Types.FLOAT, "float"); + registerColumnType(Types.DOUBLE, "double"); + registerColumnType(Types.DECIMAL, "decimal"); + registerColumnType(Types.CHAR, "char"); + registerColumnType(Types.LONGVARCHAR, "longvarchar"); + registerColumnType(Types.TIMESTAMP, "datetime"); + registerColumnType(Types.BINARY, "blob"); + registerColumnType(Types.VARBINARY, "blob"); + registerColumnType(Types.LONGVARBINARY, "blob"); + + registerFunction("concat", new VarArgsSQLFunction(StandardBasicTypes.STRING, "", "||", "")); + registerFunction("mod", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "?1 % ?2")); + registerFunction("quote", new StandardSQLFunction("quote", StandardBasicTypes.STRING)); + registerFunction("random", new NoArgSQLFunction("random", StandardBasicTypes.INTEGER)); + registerFunction("round", new StandardSQLFunction("round")); + registerFunction("substr", new StandardSQLFunction("substr", StandardBasicTypes.STRING)); + registerFunction("trim", new AbstractAnsiTrimEmulationFunction() { + @Override + protected SQLFunction resolveBothSpaceTrimFunction() { + return new SQLFunctionTemplate(StandardBasicTypes.STRING, "trim(?1)"); + } + + @Override + protected SQLFunction resolveBothSpaceTrimFromFunction() { + return new SQLFunctionTemplate(StandardBasicTypes.STRING, "trim(?2)"); + } + + @Override + protected SQLFunction resolveLeadingSpaceTrimFunction() { + return new SQLFunctionTemplate(StandardBasicTypes.STRING, "ltrim(?1)"); + } + + @Override + protected SQLFunction resolveTrailingSpaceTrimFunction() { + return new SQLFunctionTemplate(StandardBasicTypes.STRING, "rtrim(?1)"); + } + + @Override + protected SQLFunction resolveBothTrimFunction() { + return new SQLFunctionTemplate(StandardBasicTypes.STRING, "trim(?1, ?2)"); + } + + @Override + protected SQLFunction resolveLeadingTrimFunction() { + return new SQLFunctionTemplate(StandardBasicTypes.STRING, "ltrim(?1, ?2)"); + } + + @Override + protected SQLFunction resolveTrailingTrimFunction() { + return new SQLFunctionTemplate(StandardBasicTypes.STRING, "rtrim(?1, ?2)"); + } + }); + uniqueDelegate = new SQLiteUniqueDelegate(this); + } + + // database type mapping support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + /*@Override + public String getCastTypeName(int code) { + // http://sqlite.org/lang_expr.html#castexpr + return super.getCastTypeName( code ); + }*/ + + // IDENTITY support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + private static final SQLiteDialectIdentityColumnSupport IDENTITY_COLUMN_SUPPORT = new + SQLiteDialectIdentityColumnSupport(new SQLiteDialect()); + + + @Override + public IdentityColumnSupport getIdentityColumnSupport() { + return IDENTITY_COLUMN_SUPPORT; + } + + // limit/offset support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + private static final AbstractLimitHandler LIMIT_HANDLER = new AbstractLimitHandler() { + @Override + public String processSql(String sql, RowSelection selection) { + final boolean hasOffset = LimitHelper.hasFirstRow(selection); + return sql + (hasOffset ? " limit ? offset ?" : " limit ?"); + } + + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public boolean bindLimitParametersInReverseOrder() { + return true; + } + }; + + @Override + public LimitHandler getLimitHandler() { + return LIMIT_HANDLER; + } + + // lock acquisition support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + @Override + public boolean supportsLockTimeouts() { + // may be http://sqlite.org/c3ref/db_mutex.html ? + return false; + } + + @Override + public String getForUpdateString() { + return ""; + } + + @Override + public boolean supportsOuterJoinForUpdate() { + return false; + } + + // current timestamp support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Override + public boolean supportsCurrentTimestampSelection() { + return true; + } + + @Override + public boolean isCurrentTimestampSelectStringCallable() { + return false; + } + + @Override + public String getCurrentTimestampSelectString() { + return "select current_timestamp"; + } + + // SQLException support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + private static final int SQLITE_BUSY = 5; + private static final int SQLITE_LOCKED = 6; + private static final int SQLITE_IOERR = 10; + private static final int SQLITE_CORRUPT = 11; + private static final int SQLITE_NOTFOUND = 12; + private static final int SQLITE_FULL = 13; + private static final int SQLITE_CANTOPEN = 14; + private static final int SQLITE_PROTOCOL = 15; + private static final int SQLITE_TOOBIG = 18; + private static final int SQLITE_CONSTRAINT = 19; + private static final int SQLITE_MISMATCH = 20; + private static final int SQLITE_NOTADB = 26; + + @Override + public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() { + return new SQLExceptionConversionDelegate() { + @Override + public JDBCException convert(SQLException sqlException, String message, String sql) { + final int errorCode = JdbcExceptionHelper.extractErrorCode(sqlException) & 0xFF; + if (errorCode == SQLITE_TOOBIG || errorCode == SQLITE_MISMATCH) { + return new DataException(message, sqlException, sql); + } else if (errorCode == SQLITE_BUSY || errorCode == SQLITE_LOCKED) { + return new LockAcquisitionException(message, sqlException, sql); + } else if ((errorCode >= SQLITE_IOERR && errorCode <= SQLITE_PROTOCOL) || errorCode == SQLITE_NOTADB) { + return new JDBCConnectionException(message, sqlException, sql); + } + + // returning null allows other delegates to operate + return null; + } + }; + } + + @Override + public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() { + return EXTRACTER; + } + + private static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() { + @Override + protected String doExtractConstraintName(SQLException sqle) throws NumberFormatException { + final int errorCode = JdbcExceptionHelper.extractErrorCode(sqle) & 0xFF; + if (errorCode == SQLITE_CONSTRAINT) { + return extractUsingTemplate("constraint ", " failed", sqle.getMessage()); + } + return null; + } + }; + + // union subclass support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Override + public boolean supportsUnionAll() { + return true; + } + + // DDL support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + @Override + public boolean canCreateSchema() { + return false; + } + + @Override + public boolean hasAlterTable() { + // As specified in NHibernate dialect + return false; + } + + @Override + public boolean dropConstraints() { + return false; + } + + @Override + public boolean qualifyIndexName() { + return false; + } + + @Override + public String getAddColumnString() { + return "add column"; + } + + @Override + public String getDropForeignKeyString() { + throw new UnsupportedOperationException("No drop foreign key syntax supported by SQLiteDialect"); + } + + @Override + public String getAddForeignKeyConstraintString(String constraintName, + String[] foreignKey, String referencedTable, String[] primaryKey, + boolean referencesPrimaryKey) { + throw new UnsupportedOperationException("No add foreign key syntax supported by SQLiteDialect"); + } + + @Override + public String getAddPrimaryKeyConstraintString(String constraintName) { + throw new UnsupportedOperationException("No add primary key syntax supported by SQLiteDialect"); + } + + @Override + public boolean supportsCommentOn() { + return true; + } + + @Override + public boolean supportsIfExistsBeforeTableName() { + return true; + } + + /* not case insensitive for unicode characters by default (ICU extension needed) + public boolean supportsCaseInsensitiveLike() { + return true; + } + */ + + @Override + public boolean doesReadCommittedCauseWritersToBlockReaders() { + // TODO Validate (WAL mode...) + return true; + } + + @Override + public boolean doesRepeatableReadCauseReadersToBlockWriters() { + return true; + } + + @Override + public boolean supportsTupleDistinctCounts() { + return false; + } + + @Override + public int getInExpressionCountLimit() { + // Compile/runtime time option: http://sqlite.org/limits.html#max_variable_number + return 1000; + } + + @Override + public UniqueDelegate getUniqueDelegate() { + return uniqueDelegate; + } + + private static class SQLiteUniqueDelegate extends DefaultUniqueDelegate { + public SQLiteUniqueDelegate(Dialect dialect) { + super(dialect); + } + + @Override + public String getColumnDefinitionUniquenessFragment(Column column) { + return " unique"; + } + } + + @Override + public String getSelectGUIDString() { + return "select hex(randomblob(16))"; + } + + @Override + public ScrollMode defaultScrollMode() { + return ScrollMode.FORWARD_ONLY; + } +} \ No newline at end of file diff --git a/SerialPortCommJava/src/main/java/com/rehome/serialportcommjava/config/SQLiteDialectIdentityColumnSupport.java b/SerialPortCommJava/src/main/java/com/rehome/serialportcommjava/config/SQLiteDialectIdentityColumnSupport.java new file mode 100644 index 0000000..4896124 --- /dev/null +++ b/SerialPortCommJava/src/main/java/com/rehome/serialportcommjava/config/SQLiteDialectIdentityColumnSupport.java @@ -0,0 +1,51 @@ +package com.rehome.serialportcommjava.config; + + +import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.identity.IdentityColumnSupportImpl; + + +public class SQLiteDialectIdentityColumnSupport extends IdentityColumnSupportImpl { + public SQLiteDialectIdentityColumnSupport(Dialect dialect) { + super(); + } + + @Override + public boolean supportsIdentityColumns() { + return true; + } + + /* + public boolean supportsInsertSelectIdentity() { + return true; // As specified in NHibernate dialect + } + */ + + @Override + public boolean hasDataTypeInIdentityColumn() { + // As specified in NHibernate dialect + // FIXME true + return false; + } + + /* + public String appendIdentitySelectToInsert(String insertString) { + return new StringBuffer(insertString.length()+30). // As specified in NHibernate dialect + append(insertString). + append("; ").append(getIdentitySelectString()). + toString(); + } + */ + + @Override + public String getIdentitySelectString(String table, String column, int type) { + return "select last_insert_rowid()"; + } + + @Override + public String getIdentityColumnString(int type) { + // return "integer primary key autoincrement"; + // FIXME "autoincrement" + return "integer"; + } +} \ No newline at end of file diff --git a/SerialPortCommJava/src/main/java/com/rehome/serialportcommjava/config/SQLiteMetadataBuilderInitializer.java b/SerialPortCommJava/src/main/java/com/rehome/serialportcommjava/config/SQLiteMetadataBuilderInitializer.java new file mode 100644 index 0000000..eb36fc8 --- /dev/null +++ b/SerialPortCommJava/src/main/java/com/rehome/serialportcommjava/config/SQLiteMetadataBuilderInitializer.java @@ -0,0 +1,41 @@ +package com.rehome.serialportcommjava.config; + + + +import org.hibernate.boot.MetadataBuilder; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.spi.MetadataBuilderInitializer; +import org.hibernate.engine.jdbc.dialect.internal.DialectResolverSet; +import org.hibernate.engine.jdbc.dialect.spi.DialectResolver; +import org.jboss.logging.Logger; + +/** + * SQLite工具 + */ +public class SQLiteMetadataBuilderInitializer implements MetadataBuilderInitializer { + + private final static Logger logger = Logger.getLogger(SQLiteMetadataBuilderInitializer.class); + + @Override + public void contribute(MetadataBuilder metadataBuilder, StandardServiceRegistry serviceRegistry) { + DialectResolver dialectResolver = serviceRegistry.getService(DialectResolver.class); + + if (!(dialectResolver instanceof DialectResolverSet)) { + logger.warnf("DialectResolver '%s' is not an instance of DialectResolverSet, not registering SQLiteDialect", + dialectResolver); + return; + } + + ((DialectResolverSet) dialectResolver).addResolver(resolver); + } + + static private final SQLiteDialect dialect = new SQLiteDialect(); + + static private final DialectResolver resolver = (DialectResolver) info -> { + if (info.getDatabaseName().equals("SQLite")) { + return dialect; + } + + return null; + }; +} \ No newline at end of file diff --git a/SerialPortCommJava/src/main/resources/application.properties b/SerialPortCommJava/src/main/resources/application.properties deleted file mode 100644 index 964b62c..0000000 --- a/SerialPortCommJava/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.application.name=SerialPortCommJava diff --git a/SerialPortCommJava/src/main/resources/application.yml b/SerialPortCommJava/src/main/resources/application.yml new file mode 100644 index 0000000..501660b --- /dev/null +++ b/SerialPortCommJava/src/main/resources/application.yml @@ -0,0 +1,26 @@ +server: + port: 8070 +spring: + datasource: + url: jdbc:sqlite:SerialPortCommJava.db + #url: jdbc:sqlite:/Users/admin/springboot-sqlite-jpa-temperature.db + #url: jdbc:sqlite:/root/temperature/springboot-sqlite-jpa-temperature.db + driver-class-name: org.sqlite.JDBC + username: + password: + jpa: + database-platform: com.rehome.serialportcommjava.config.SQLiteDialect + show-sql: true # ???????? SQL ????? + open-in-view: true + hibernate: + ddl-auto: update # ?????create ???update????????????? + servlet: + multipart: + # ?? multipart ???? + enabled: true + # ????????? + file-size-threshold: 2KB + # ?????? + max-file-size: 200MB + # ?????? + max-request-size: 215MB