使用日期显示以前的登录信息

时间:2015-12-25 13:27:03

标签: java mysql date

我有一个使用MySql数据库的java应用程序。在我的应用程序中,我有一个JInternalFrame,我用它来显示当前用户信息,如“登录为:”和“上次登录:”。

rhc scp appname download localpath app-root/repo/path/to/file

如何设置日期,我目前设置为虚拟值“14-03-2015”以显示我的上次登录?有没有办法通过MySql?

更新

我已经创建了一个新表来存储一些登录详细信息:

    loggedInUserLabel.setText("Logged in as: ");
    getContentPane().add(loggedInUserLabel);
    loggedInUserLabel.setBounds(30, 30, 80, 30);

    loggedInUser.setText("Admin");
    getContentPane().add(loggedInUser);
    loggedInUser.setBounds(140, 30, 80, 30);

    lastLoginLabel.setText("Last Login:");
    getContentPane().add(lastLoginLabel);
    lastLoginLabel.setBounds(30, 60, 80, 30);

    lastLogin.setText("14-03-2015");
    getContentPane().add(lastLogin);
    lastLogin.setBounds(140, 60, 80, 30);

登录的位置如下所示:

CREATE TABLE IF NOT EXISTS `last_login`(
`username` varchar(20) NOT NULL,
`date` varchar(20) NOT NULL
);

使用“insertData”将新数据插入到我的表中,如下所示

if (rs.next()) {
        if (rs.getString("usertype").equals("Admin")) {
            setLoggedInUser(userBox.getText());
            insertData();
            AdminMenu adminMenu = new AdminMenu();
            adminMenu.setVisible(true);
            setVisible(false);
        } else if (rs.getString("usertype").equals("Employee")) {
            setLoggedInUser(userBox.getText());
            insertData();
            EmployeeMenu employeeMenu = new EmployeeMenu();
            employeeMenu.setVisible(true);
            setVisible(false);
        }

但问题是:我使用此代码从数据库中检索日期

public static void insertData() {
    String user = "root";
    String pass = "pass";
    String schmea = "db";

    Date date = new Date();
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
    String currentDate = dateFormat.format(date);

    try {
        Connection conn = MySql.getConnection(user, pass, "/" + schmea);

        try {
            String q = "insert into last_login(username,date) values(?,?)";
            PreparedStatement stmt = conn.prepareStatement(q);
            stmt.setString(1, loggedInUser);
            stmt.setString(2, currentDate);
            stmt.execute();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

我知道我总是回到该用户的当前日期。我该如何约定该用户的上一个日期?

2 个答案:

答案 0 :(得分:1)

使用日期时间类型

不要将字符串用于日期时间值。将日期时间类型用于日期时间值。

在Java 8及更高版本中,使用java.time类型,例如Instant(UTC时间轴上的时刻)。如果Java 8技术不可用(Android等),那么使用古老的Joda-Time库。

要将数据传入和传出数据库,请使用java.sql.Timestamp等java.sql类型。希望JDBC驱动程序将更新为直接支持java.time类型,但在此之前使用java.time - java.sql转换方法,例如from( Instant )toInstant

在您的数据库中,了解其日期时间类型。 SQL规范定义了几种类型,但对这些类型的支持差异很大。某些数据库(例如Postgres)有excellent date-time supportSQLite等一些人有周支持。有些像H2这样的东西在中间。仔细研究数据库的文档。然后进行实验以确保您了解其行为。日期工作可能很棘手。

我不明白您在没有时间的情况下使用仅限日期来跟踪登录信息。为什么您只关心整天的粒度登录?此外,由于日期的定义因时区而异,因此仅限日期是模糊的。通常,我们会在UTC时区内跟踪此类业务数据作为日期时间值。然后,为了演示,调整到用户期望/期望的特定时区。

示例App

以下是在数据库中存储登录尝试的完整应用程序的源代码。这个应用程序是设计的,旨在用于演示目的而不是部署。使用风险由您自己承担。

您应用的Swing部分是一个很大的分心。此示例应用程序更简单,没有用户界面。每次运行应用程序的main方法时,它都会报告先前的登录尝试,然后重新尝试。新尝试随机选择一个用户名。

package com.example.logintracker;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;

/**
 * Contrived app to demonstrate saving login attempts to a database.
 *
 * This source code available via the Free Public License 1.0.0. http://opensource.org/licenses/FPL-1.0.0
 *
 * @author Basil Bourque
 */
public class App {

    public static void main ( String[] args ) {
        App app = new App ();

        // Report the most recent login attempt.
        Authenticator authenticator_Reporter = new Authenticator ();
        LoginAttempt loginAttempt_Recent = authenticator_Reporter.getMostRecentAttempt ();
        System.out.println ( "Recent loginAttempt: " + loginAttempt_Recent );

        // Attempt a login.
        Authenticator authenticator_Login = new Authenticator ();
        ArrayList<String> userNames = new ArrayList<> ( Arrays.asList ( "Wendy" , "Lisa" , "Jesse" , "Oliver" , "Jasmine" , "Jean-Luc" , "Jarrod" , "Evonne" , "Elise" ) ); // Pick a name at random.
        String userName = userNames.get ( new Random ().nextInt ( userNames.size () ) ); // From user-interface.
        String password = "pw"; // From user-interface.
        LoginAttempt loginAttempt_Now = authenticator_Login.authenticate ( userName , password );
        System.out.println ( "Fresh loginAttempt: " + loginAttempt_Now );
        if ( loginAttempt_Now.getSuccessful () ) {
            // Run the app for this user.
            // TODO: implement.
        } else {
            // Else block this user from running this app.
            // TODO: implement.
        }
    }
}

Authenticator是主要业务逻辑的网关。

package com.example.logintracker;

import java.time.Instant;
import java.util.UUID;

/**
 * The business logic for handling login attempts. Called by separate user interface code.
 *
 * This source code available via the Free Public License 1.0.0. http://opensource.org/licenses/FPL-1.0.0
 *
 * @author Basil Bourque
 *
 */
public class Authenticator {

    // User-interface makes this call to execute a user’s login attempt.
    public LoginAttempt authenticate ( String userName , String password ) {
        Boolean successful = Boolean.FALSE;

        // TODO: Add business logic to perform authentication. Hard-coded here to always succeed for this demonstration code.
        successful = Boolean.TRUE;
        LoginAttempt loginAttempt = new LoginAttempt ( userName , Instant.now () , successful , UUID.randomUUID () );

        // Remember this attempt.
        Persister persister = new Persister ();
        persister.saveLoginAttempt ( loginAttempt );

        return loginAttempt;
    }

    public LoginAttempt getMostRecentAttempt () {
        Persister persister = new Persister ();
        LoginAttempt loginAttempt = persister.fetchMostRecentLoginAttempt ();
        return loginAttempt;
    }

}

每次登录尝试的数据都是一个简单的LoginAttempt类,value objects

package com.example.logintracker;

import java.time.Instant;
import java.util.UUID;

/**
 *
 * Value object holding the data describing each login attempt: who was the user, when attempted, was the login successful.
 *
 * This source code available via the Free Public License 1.0.0. http://opensource.org/licenses/FPL-1.0.0
 *
 * @author Basil Bourque
 *
 */
public class LoginAttempt {

    private String userName;
    private Instant whenAttempted;
    private Boolean successful;
    private UUID uuid = null;

    public LoginAttempt ( String userNameArg , Instant whenAttemptedArg , Boolean successfulArg , UUID uuidArg ) {
//        System.out.println ( "Constructor of LoginAttempt: " + whenAttemptedArg + " user: " + userNameArg );
        this.userName = userNameArg;
        this.whenAttempted = whenAttemptedArg;
        this.successful = successfulArg;
        this.uuid = uuidArg;
    }

    // Getters. Read-only object.
    public String getUserName () {
        return this.userName;
    }

    public Instant getWhenAttempted () {
        return this.whenAttempted;
    }

    public Boolean getSuccessful () {
        return this.successful;
    }

    public UUID getUuid () {
        return this.uuid;
    }

    // Override Object.
    @Override
    public String toString () {
        return "LoginAttempt{ " + "userName=" + this.userName + " | whenAttempted=" + this.whenAttempted + " | successful=" + this.successful + " | uuid=" + this.uuid + " }";
    }

}

这些登录尝试存储在基本的SQL表中。

CREATE TABlE IF NOT EXISTS login_attempt_
(
    uuid_ UUID DEFAULT RANDOM_UUID() PRIMARY KEY,
    when_written_ TIMESTAMP DEFAULT NOW() NOT NULL,
    username_ VARCHAR_IGNORECASE(255) NOT NULL,
    when_attempted_ TIMESTAMP NOT NULL,
    success_ BOOLEAN NOT NULL
)
;

每次运行此应用程序时,都会检查该表是否存在。如果未找到,则应用会自动创建该表。包含该表和数据库用户的数据库&amp;密码也是自动创建的。所以,只需运行此应用程序即可看到演示。无需额外设置。

此示例数据库使用H2 database,这是一个免费的开源纯Java SQL数据库。 H2可以以嵌入模式或客户端/服务器模式运行。在这个应用程序中我们使用嵌入模式在Maven项目中,只需为com.h2database添加依赖项。

Persister类处理与数据库的所有交互,保存并检索登录尝试。

package com.example.logintracker;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Handles all persisting of data to database or other storage mechanism. Called from other code handling business logic.
 *
 * This source code available via the Free Public License 1.0.0. http://opensource.org/licenses/FPL-1.0.0
 *
 * @author Basil Bourque
 *
 */
public class Persister {

    public void saveLoginAttempt ( LoginAttempt loginAttempt ) {
        // Get database connection.
        // Make prepared statement.
        // Transfer pieces of data from LoginAttempt into PreparedStatement.
        // Execute database transaction.

        StringBuilder sql = new StringBuilder ();
        sql.append ( "INSERT INTO login_attempt_ ( username_ , when_attempted_ , success_ , uuid_ ) " + " \n" );
        sql.append ( "VALUES ( ? , ? , ? , ? )" + " \n" );
        sql.append ( ";" + " \n" );

        try ( Connection conn = this.fetchConnection (); ) {
//            System.out.println ( "conn: " + conn );

            try ( PreparedStatement ps = conn.prepareStatement ( sql.toString () ); ) {
                ps.setString ( 1 , loginAttempt.getUserName () );
                java.sql.Timestamp ts = java.sql.Timestamp.from ( loginAttempt.getWhenAttempted () );  // Converting from java.time.Instant to java.sql.Timestamp.
                ps.setTimestamp ( 2 , ts );
                ps.setBoolean ( 3 , loginAttempt.getSuccessful () );
                ps.setObject ( 4 , loginAttempt.getUuid () );
                ps.executeUpdate ();

            } catch ( SQLException ex ) {
                System.err.println ( "SQLException: " + ex.getMessage () );
                // TODO: Handle exception.
            }
        } catch ( SQLException ex ) {
            System.err.println ( "SQLException on this.fetchConnection: " + ex.getMessage () );
            // TODO: Handle exception.
        }

    }

    public LoginAttempt fetchMostRecentLoginAttempt () {
        // Get database connection.
        // Make prepared statement.
        // Execute query.
        // Transfer pieces of data from ResultSet to new LoginAttempt object.
        // Return object (or null if failure occurred).

        StringBuilder sql = new StringBuilder ();
        sql.append ( "SELECT * " + " \n" );
        sql.append ( "FROM login_attempt_" + " \n" );
        sql.append ( "ORDER BY when_attempted_ DESC" + " \n" );
        sql.append ( "LIMIT 1" + " \n" );
        sql.append ( ";" + " \n" );

        LoginAttempt loginAttempt = null;
        try ( Connection conn = this.fetchConnection (); ) {
//            System.out.println ( "conn: " + conn );

            try ( Statement stmt = conn.createStatement (); ) {
                ResultSet rs = stmt.executeQuery ( sql.toString () );
                int count = 0;
                while ( rs.next () ) {
                    count ++;
                    String userName = rs.getString ( "username_" );
                    java.sql.Timestamp whenWritten = rs.getTimestamp ( "when_attempted_" );
                    Boolean success = rs.getBoolean ( "success_" );
                    UUID uuid = ( UUID ) rs.getObject ( "uuid_" );
                    loginAttempt = new LoginAttempt ( userName , whenWritten.toInstant () , success , uuid );  // Converting from java.sql.Timestamp to java.time.Instant.
                }
                if ( count > 1 ) {
                    // TODO: Handle problem where more than one row returned.
                }

            } catch ( SQLException ex ) {
                System.err.println ( "SQLException: " + ex.getMessage () );
                // TODO: Handle exception.
            }
        } catch ( SQLException ex ) {
            System.err.println ( "SQLException on this.fetchConnection: " + ex.getMessage () );
            // TODO: Handle exception.
        }
        return loginAttempt;
    }

    private Connection fetchConnection () throws SQLException {
        Connection conn = null;

        try {
            Class.forName ( "org.h2.Driver" );
        } catch ( ClassNotFoundException e ) {
            // TODO: Handle exception.
            System.out.println ( "Database failure: " + e );
            return null;
        }

        // Specify a database named 'LoginTracker.mv.db' in the Unix user’s home folder.
        String dbFolderPath = "~/";
        String dbName = "LoginTracker";
        String dbUrl = "jdbc:h2:" + dbFolderPath + dbName;
        String dbUserName = "h2";
        String dbPassword = "pw";

        try {
            // If database does not yet exist, it is automatically created.
            conn = DriverManager.getConnection ( dbUrl , dbUserName , dbPassword );
        } catch ( SQLException ex ) {
            System.out.println ( "SQLException on DriverManager.getConnection: " + ex.getMessage () );
            // TODO: Handle exception when no Connection is made.
        }

        if ( null == conn ) {
            System.out.println ( "Database error. No Connection." );
            // TODO: Handle exception when no Connection is made.
        } else {
            // ELSE got database connection. Normal.
            this.updateDatabaseStructureIfNeedBe ( conn );
        }

        return conn;
    }

    private void updateDatabaseStructureIfNeedBe ( Connection conn ) {
        // Update database structure if needed.

        // 'login_attempt_' Table.
        StringBuilder sql = new StringBuilder ();
        sql.append ( "CREATE TABlE IF NOT EXISTS login_attempt_" + " \n" );
        sql.append ( "(" + " \n" );
        sql.append ( "uuid_ UUID DEFAULT RANDOM_UUID() PRIMARY KEY," + " \n" );  // Primary key, UUID type.
        sql.append ( "when_written_ TIMESTAMP DEFAULT NOW() NOT NULL," + " \n" );  // Record when this record was written to database. Apparently H2 only provides txn start time, not current time.
        sql.append ( "username_ VARCHAR_IGNORECASE(255) NOT NULL," + " \n" );  // User’s name. Case-insensitive.
        sql.append ( "when_attempted_ TIMESTAMP NOT NULL," + " \n" );  // When this login attempt was made.
        sql.append ( "success_ BOOLEAN NOT NULL" + " \n" );  // Did this login attempt succeed or fail?
        sql.append ( ")" + " \n" );
        sql.append ( ";" + " \n" );

        try ( Statement stmt = conn.createStatement () ) {
            stmt.executeUpdate ( sql.toString () );
            stmt.close ();

        } catch ( SQLException ex ) {
            System.err.println ( "SQLException: " + ex.getMessage () );
            // TODO: Handle exception.
        }

    }

}

答案 1 :(得分:0)

考虑一下你想要多少持久性,以及你需要保存多少数据。服务器重启后,您是否希望此信息持续存在并仍然可用?

这将告诉您是否需要持久存储(磁盘,数据库等),或者是否可以将其保存在RAM中。

然后,您拥有的数据量,访问频率等等将告诉您应该如何组织它。