From 750f0d156b81a62ec90111d84dddba41887da47f Mon Sep 17 00:00:00 2001 From: MoMenne Date: Sun, 27 Jul 2014 10:22:08 -0500 Subject: [PATCH] transitioned from JDBC to hibernate --- pset6/jdbc-example/pom.xml | 41 ++- .../launchcode/MetrolinkCommandLineApp.java | 13 +- .../java/com/mikemenne/launchcode/Stop.java | 19 ++ .../launchcode/dao/SqliteJDBCDao.java | 48 +-- .../launchcode/util/ScreenOutput.java | 3 + .../org/hibernate/dialect/SQLiteDialect.java | 291 ++++++++++++++++++ .../main/resources/application-context.xml | 46 +-- .../src/main/resources/log4j.properties | 59 ++++ 8 files changed, 450 insertions(+), 70 deletions(-) create mode 100644 pset6/jdbc-example/src/main/java/org/hibernate/dialect/SQLiteDialect.java create mode 100644 pset6/jdbc-example/src/main/resources/log4j.properties diff --git a/pset6/jdbc-example/pom.xml b/pset6/jdbc-example/pom.xml index 211b901..65d7a0e 100644 --- a/pset6/jdbc-example/pom.xml +++ b/pset6/jdbc-example/pom.xml @@ -16,6 +16,11 @@ spring-context 4.0.5.RELEASE + + org.springframework + spring-orm + 4.0.5.RELEASE + org.xerial @@ -26,28 +31,32 @@ org.hibernate - hibernate - 3.5.4-FINAL + hibernate-core + 4.2.0.Final + + org.hibernate + hibernate-annotations + 3.5.6-Final + - - dom4j - dom4j - 1.6.1 + org.slf4j + slf4j-log4j12 + 1.7.5 - commons-logging - commons-logging - 1.1.1 + javax.transaction + jta + 1.1 - commons-collections - commons-collections - 3.2.1 + javassist + javassist + 3.12.1.GA @@ -55,7 +64,13 @@ antlr 2.7.7 - + + + log4j + log4j + 1.2.17 + + \ No newline at end of file diff --git a/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/MetrolinkCommandLineApp.java b/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/MetrolinkCommandLineApp.java index 722e283..784b2f9 100644 --- a/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/MetrolinkCommandLineApp.java +++ b/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/MetrolinkCommandLineApp.java @@ -1,7 +1,9 @@ package com.mikemenne.launchcode; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.stereotype.Component; import java.util.List; @@ -10,6 +12,8 @@ * Date: 7/3/14 * Time: 1:51 AM */ + +@Component public class MetrolinkCommandLineApp { public static void main(String[] varArgs) { @@ -26,14 +30,9 @@ private void run() { } } + @Autowired private MetrolinkDao metrolinkDao; + @Autowired private AppOutput appOutput; - public void setMetrolinkDao(MetrolinkDao metrolinkDao) { - this.metrolinkDao = metrolinkDao; - } - - public void setAppOutput(AppOutput appOutput) { - this.appOutput = appOutput; - } } diff --git a/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/Stop.java b/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/Stop.java index 59370b4..e7546a3 100644 --- a/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/Stop.java +++ b/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/Stop.java @@ -1,5 +1,8 @@ package com.mikemenne.launchcode; +import javax.persistence.*; +import static javax.persistence.GenerationType.IDENTITY; + import java.util.Date; /** @@ -8,9 +11,17 @@ * Time: 1:40 AM */ +@Entity +@Table(name="stops") public class Stop { + @Id + @GeneratedValue(strategy = IDENTITY) + @Column(name = "stop_id", unique = true, nullable = false) + private Integer id; + @Column(name = "stop_name") private String stopName; + @Column(name = "stop_desc") private String stopDescription; @@ -29,4 +40,12 @@ public String getStopDescription() { public void setStopDescription(String stopDescription) { this.stopDescription = stopDescription; } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } } diff --git a/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/dao/SqliteJDBCDao.java b/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/dao/SqliteJDBCDao.java index 0dfec3b..6821bad 100644 --- a/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/dao/SqliteJDBCDao.java +++ b/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/dao/SqliteJDBCDao.java @@ -3,47 +3,33 @@ import com.mikemenne.launchcode.AppOutput; import com.mikemenne.launchcode.MetrolinkDao; import com.mikemenne.launchcode.Stop; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.hibernate.Criteria; +import org.hibernate.SessionFactory; +import org.hibernate.criterion.Restrictions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; import java.sql.*; import java.util.ArrayList; import java.util.List; +@Repository public class SqliteJDBCDao implements MetrolinkDao { - public static final String JDBC_SQLITE_METROLINK_DB = "jdbc:sqlite:metrolink.db"; - public static final String ORG_SQLITE_JDBC = "org.sqlite.JDBC"; - + @Autowired private AppOutput appOutput; + @Autowired + private SessionFactory sessionFactoryBean; public List getStopsAllStops() { - appOutput.print("Fetching metrolink stations..."); - try (Connection connection = getConnection();) { - PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM stops"); - ResultSet resultSet = preparedStatement.executeQuery(); - List stops = new ArrayList(); - while (resultSet.next()) { - Stop stop = new Stop(); - stop.setStopName(resultSet.getString("stop_name")); - stop.setStopDescription(resultSet.getString("stop_desc")); - stops.add(stop); - } - return stops; - } catch (SQLException e) { - throw new RuntimeException("Error retrieving stops"); - } - } - - private static Connection getConnection() throws SQLException { - try { - Class.forName(ORG_SQLITE_JDBC); - } catch (ClassNotFoundException e) { - throw new RuntimeException("Unable to find class for loading the database", e); - } - return DriverManager.getConnection(JDBC_SQLITE_METROLINK_DB); - } - - public void setAppOutput(AppOutput appOutput) { - this.appOutput = appOutput; + sessionFactoryBean.getCurrentSession().beginTransaction(); + Criteria criteria = sessionFactoryBean.getCurrentSession().createCriteria(Stop.class); + List list = criteria.list(); + sessionFactoryBean.getCurrentSession().getTransaction().commit(); + return list; } } diff --git a/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/util/ScreenOutput.java b/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/util/ScreenOutput.java index 107727a..3a27f40 100644 --- a/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/util/ScreenOutput.java +++ b/pset6/jdbc-example/src/main/java/com/mikemenne/launchcode/util/ScreenOutput.java @@ -1,12 +1,15 @@ package com.mikemenne.launchcode.util; import com.mikemenne.launchcode.AppOutput; +import org.springframework.stereotype.Service; /** * User: mpmenne * Date: 7/3/14 * Time: 2:04 AM */ + +@Service public class ScreenOutput implements AppOutput{ @Override public void print(String output) { diff --git a/pset6/jdbc-example/src/main/java/org/hibernate/dialect/SQLiteDialect.java b/pset6/jdbc-example/src/main/java/org/hibernate/dialect/SQLiteDialect.java new file mode 100644 index 0000000..bd108aa --- /dev/null +++ b/pset6/jdbc-example/src/main/java/org/hibernate/dialect/SQLiteDialect.java @@ -0,0 +1,291 @@ +/* + * The author disclaims copyright to this source code. In place of + * a legal notice, here is a blessing: + * + * May you do good and not evil. + * May you find forgiveness for yourself and forgive others. + * May you share freely, never taking more than you give. + * + */ +package org.hibernate.dialect; + +import java.sql.SQLException; +import java.sql.Types; + +import org.hibernate.JDBCException; +import org.hibernate.dialect.function.AbstractAnsiTrimEmulationFunction; +import org.hibernate.dialect.function.NoArgSQLFunction; +import org.hibernate.dialect.function.SQLFunction; +import org.hibernate.dialect.function.SQLFunctionTemplate; +import org.hibernate.dialect.function.StandardSQLFunction; +import org.hibernate.dialect.function.VarArgsSQLFunction; +import org.hibernate.exception.*; +import org.hibernate.exception.spi.SQLExceptionConverter; +import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter; +import org.hibernate.exception.spi.ViolatedConstraintNameExtracter; +import org.hibernate.type.StandardBasicTypes; + +public class SQLiteDialect extends Dialect { + public SQLiteDialect() { + registerColumnType(Types.BIT, "boolean"); + registerColumnType(Types.TINYINT, "tinyint"); + registerColumnType(Types.SMALLINT, "smallint"); + registerColumnType(Types.INTEGER, "integer"); + registerColumnType(Types.BIGINT, "bigint"); + registerColumnType(Types.FLOAT, "float"); + registerColumnType(Types.REAL, "real"); + registerColumnType(Types.DOUBLE, "double"); + registerColumnType(Types.NUMERIC, "numeric($p, $s)"); + registerColumnType(Types.DECIMAL, "decimal"); + registerColumnType(Types.CHAR, "char"); + registerColumnType(Types.VARCHAR, "varchar($l)"); + registerColumnType(Types.LONGVARCHAR, "longvarchar"); + registerColumnType(Types.DATE, "date"); + registerColumnType(Types.TIME, "time"); + registerColumnType(Types.TIMESTAMP, "datetime"); + registerColumnType(Types.BINARY, "blob"); + registerColumnType(Types.VARBINARY, "blob"); + registerColumnType(Types.LONGVARBINARY, "blob"); + registerColumnType(Types.BLOB, "blob"); + registerColumnType(Types.CLOB, "clob"); + registerColumnType(Types.BOOLEAN, "boolean"); + + 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() { + protected SQLFunction resolveBothSpaceTrimFunction() { + return new SQLFunctionTemplate(StandardBasicTypes.STRING, "trim(?1)"); + } + + protected SQLFunction resolveBothSpaceTrimFromFunction() { + return new SQLFunctionTemplate(StandardBasicTypes.STRING, "trim(?2)"); + } + + protected SQLFunction resolveLeadingSpaceTrimFunction() { + return new SQLFunctionTemplate(StandardBasicTypes.STRING, "ltrim(?1)"); + } + + protected SQLFunction resolveTrailingSpaceTrimFunction() { + return new SQLFunctionTemplate(StandardBasicTypes.STRING, "rtrim(?1)"); + } + + protected SQLFunction resolveBothTrimFunction() { + return new SQLFunctionTemplate(StandardBasicTypes.STRING, "trim(?1, ?2)"); + } + + protected SQLFunction resolveLeadingTrimFunction() { + return new SQLFunctionTemplate(StandardBasicTypes.STRING, "ltrim(?1, ?2)"); + } + + protected SQLFunction resolveTrailingTrimFunction() { + return new SQLFunctionTemplate(StandardBasicTypes.STRING, "rtrim(?1, ?2)"); + } + } ); + } + + @Override + public boolean supportsIdentityColumns() { + return true; + } + + /* + public boolean supportsInsertSelectIdentity() { + return true; // As specified in NHibernate dialect + } + */ + + @Override + public boolean hasDataTypeInIdentityColumn() { + return false; // As specified in NHibernate dialect + } + + /* + 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 getIdentityColumnString() { + // return "integer primary key autoincrement"; + return "integer"; + } + + @Override + public String getIdentitySelectString() { + return "select last_insert_rowid()"; + } + + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public boolean bindLimitParametersInReverseOrder() { + return true; + } + + @Override + protected String getLimitString(String query, boolean hasOffset) { + return query + (hasOffset ? " limit ? offset ?" : " limit ?"); + } + + @Override + public boolean supportsTemporaryTables() { + return true; + } + + @Override + public String getCreateTemporaryTableString() { + return "create temporary table if not exists"; + } + + @Override + public Boolean performTemporaryTableDDLInIsolation() { + return Boolean.FALSE; + } + + /* + @Override + public boolean dropTemporaryTableAfterUse() { + return true; // temporary tables are only dropped when the connection is closed. If the connection is pooled... + } + */ + + @Override + public boolean supportsCurrentTimestampSelection() { + return true; + } + + @Override + public boolean isCurrentTimestampSelectStringCallable() { + return false; + } + + @Override + public String getCurrentTimestampSelectString() { + return "select current_timestamp"; + } + + 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 SQLExceptionConverter buildSQLExceptionConverter() { + return new SQLExceptionConverter() { + @Override + public JDBCException convert(SQLException sqlException, String message, String sql) { + final int errorCode = org.hibernate.internal.util.JdbcExceptionHelper.extractErrorCode(sqlException); + if (errorCode == SQLITE_CONSTRAINT) { + final String constraintName = EXTRACTER.extractConstraintName(sqlException); + return new ConstraintViolationException(message, sqlException, sql, constraintName); + } else 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); + } + return new GenericJDBCException(message, sqlException, sql); + } + }; + } + + public static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() { + public String extractConstraintName(SQLException sqle) { + return extractUsingTemplate( "constraint ", " failed", sqle.getMessage() ); + } + }; + + @Override + public boolean supportsUnionAll() { + return true; + } + + @Override + public boolean hasAlterTable() { + return false; // As specified in NHibernate dialect + } + + @Override + public boolean dropConstraints() { + return false; + } + + /* + public String getAddColumnString() { + return "add column"; + } + */ + + @Override + public String getForUpdateString() { + return ""; + } + + @Override + public boolean supportsOuterJoinForUpdate() { + return false; + } + + @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 supportsIfExistsBeforeTableName() { + return true; + } + + /* + public boolean supportsCascadeDelete() { + return true; + } + */ + + /* not case insensitive for unicode characters by default (ICU extension needed) + public boolean supportsCaseInsensitiveLike() { + return true; + } + */ + + @Override + public boolean supportsTupleDistinctCounts() { + return false; + } + + @Override + public String getSelectGUIDString() { + return "select hex(randomblob(16))"; + } +} \ No newline at end of file diff --git a/pset6/jdbc-example/src/main/resources/application-context.xml b/pset6/jdbc-example/src/main/resources/application-context.xml index 957b848..2fccb03 100644 --- a/pset6/jdbc-example/src/main/resources/application-context.xml +++ b/pset6/jdbc-example/src/main/resources/application-context.xml @@ -2,40 +2,48 @@ + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd + http://www.springframework.org/schema/aop + http://www.springframework.org/schema/aop/spring-aop-3.0.xsd + http://www.springframework.org/schema/tx + http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> - - - - + - + - - - + + class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> + - - + + + com.mikemenne.launchcode.Stop + - org.hibernate.dialect.MySQLDialect - true + org.hibernate.dialect.SQLiteDialect + thread + - - - /hibernate/Stock.hbm.xml - - + + + + + + \ No newline at end of file diff --git a/pset6/jdbc-example/src/main/resources/log4j.properties b/pset6/jdbc-example/src/main/resources/log4j.properties new file mode 100644 index 0000000..89a5596 --- /dev/null +++ b/pset6/jdbc-example/src/main/resources/log4j.properties @@ -0,0 +1,59 @@ + +# Define the root logger with appender file +log4j.rootLogger = DEBUG, FILE + +# logs from application code +log4j.logger.com.mikemenne.launchcode = ALL, FILE, stdout + +# logs from Spring code +log4j.logger.org.springframework = ALL, SPRING +log4j.additivity.org.springframework = false + +# logs from hibernate libraries +log4j.logger.org.hibernate = ALL, HBM +log4j.additivity.org.hibernate = false + +# logs from hibernate spring +log4j.logger.org.springframework.orm = ALL, HBM-SPRING +log4j.additivity.org.springframework.orm = false + +# Define the file appender +log4j.appender.FILE=org.apache.log4j.RollingFileAppender +# Set the name of the file +log4j.appender.FILE.File=metrolink.log +# Set the immediate flush to true (default) +log4j.appender.FILE.ImmediateFlush=true +# Set the threshold to debug mode +#log4j.appender.FILE.Threshold=debug +# Set the append to false, overwrite +log4j.appender.FILE.Append=false +# Define the layout for file appender +log4j.appender.FILE.layout=org.apache.log4j.PatternLayout +log4j.appender.FILE.layout.conversionPattern=%d{ISO8601} %-5p %c ~ %m%n + +# appender for spring logs +log4j.appender.SPRING = org.apache.log4j.RollingFileAppender +log4j.appender.SPRING.layout = org.apache.log4j.PatternLayout +log4j.appender.SPRING.layout.ConversionPattern = %d{ISO8601} %-5p %c ~ %m%n +log4j.appender.SPRING.File = spring.log +log4j.appender.SPRING.Append=false + +# appender for hibernate logs +log4j.appender.HBM = org.apache.log4j.RollingFileAppender +log4j.appender.HBM.layout = org.apache.log4j.PatternLayout +log4j.appender.HBM.layout.ConversionPattern = %d{ISO8601} %-5p %c ~ %m%n +log4j.appender.HBM.File = hbm.log +log4j.appender.HBM.Append=false + +# appender for hibernate logs +log4j.appender.HBM-SPRING = org.apache.log4j.RollingFileAppender +log4j.appender.HBM-SPRING.layout = org.apache.log4j.PatternLayout +log4j.appender.HBM-SPRING.layout.ConversionPattern = %d{ISO8601} %-5p %c ~ %m%n +log4j.appender.HBM-SPRING.File = hbm-spring.log +log4j.appender.HBM-SPRING.Append=false + +# appender for logs to console +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n