我有一个使用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();
}
}
我知道我总是回到该用户的当前日期。我该如何约定该用户的上一个日期?
答案 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 support。 SQLite等一些人有周支持。有些像H2这样的东西在中间。仔细研究数据库的文档。然后进行实验以确保您了解其行为。日期工作可能很棘手。
我不明白您在没有时间的情况下使用仅限日期来跟踪登录信息。为什么您只关心整天的粒度登录?此外,由于日期的定义因时区而异,因此仅限日期是模糊的。通常,我们会在UTC时区内跟踪此类业务数据作为日期时间值。然后,为了演示,调整到用户期望/期望的特定时区。
以下是在数据库中存储登录尝试的完整应用程序的源代码。这个应用程序是设计的,旨在用于演示目的而不是部署。使用风险由您自己承担。
您应用的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中。
然后,您拥有的数据量,访问频率等等将告诉您应该如何组织它。