有没有一种简单的、基于Java本身的方法来持久化数据?

4
我猜我对基本的Java还很陌生——Android和.NET都有简单的方法将应用程序特定数据存储到私有数据库中,但是在普通的Java中,我没有看到这样的方法来进行数据存储。
我错过了什么?Hibernate和JPA似乎有点过度。
编辑: 我并没有在我的应用程序中寻找大量的数据存储(目前)——只需要一个持久记录一些设置,例如当前用户就足够了。我基本上是在寻找类似于Android的共享首选项或.Net的属性的模拟。

(但这是事后的事情,因为我已经收到了很多回复。)


3
Java不是操作系统。 - Hot Licks
4
是的,属性是其中之一,序列化是另一个……问题是哪种类型的数据以及其容量。另一方面,根据你的问题,我理解你只是在寻找表格,这正确吗?祝你好运。 - Fer
1
Java中没有这样的功能。最多可以通过Properties类将数据存储在.properties文件中,或者存储二进制数据。 - Luiggi Mendoza
2
关于Preferences API怎么样? - David Conrad
1
@LuiggiMendoza 除了Properties、Preferences、Serialization、XMLEncoder、JDBC、JNDI、JAXB等功能之外,没有其他的功能。 - user207421
显示剩余4条评论
4个回答

3
如果偏好设置 API 不够全面,Hibernate/JPA 又过于复杂,那么在数据库中存储应用程序数据的最简单的中间替代方法,也是最容易学习的方法可能就是 Java JDBC
下面是一个简单的示例;
    // Database URL including driver, username, password, database name etc.
    String URL = "jdbc:oracle:thin:username/password@amrood:1521:EMP";
    Connection conn = DriverManager.getConnection(URL);
    // Create your SQL Query.
    PreparedStatement st = conn.prepareStatement("UPDATE YourTable SET YourColumn = 12 WHERE TableID = 1337");
    // Execute (If your statement doesn't need to return results).
    st.execute();

SQLite可以在本地和应用程序内运行。驱动程序也可以集成。不需要服务器。因此,在这两者之间,您可以使用SQL数据库获得简单的本地持久性。


编辑:

看到您只需要持久化设置/首选项,我建议使用较新的Preferences API(上面链接的教程)而不是旧的Properties API,因为Preferences API可以更优雅地处理文件位置。

例如;

// This will define a node in which the preferences can be stored
prefs = Preferences.userRoot().node(this.getClass().getName());
// First we get the values
// Define a boolean value with the default true
prefs.getBoolean("Test1", true);
// Define a string with default "Hello World"
prefs.get("Test2", "Hello World");
// Define a integer with default 50
prefs.getInt("Test3", 50);
// now set the values
prefs.putBoolean("Test1", false);
prefs.put("Test2", "Hello Europa");
prefs.putInt("Test3", 45);
// Delete the preference settings for the first value
prefs.remove("Test1");

1
在我的上一个项目中,我使用了JDBC和SQLite,效果还不错。没有什么花哨或新颖的东西,但它完成了工作。 - zubergu
但是——请原谅我的无知——这不需要一些外部托管的...东西吗?额外的SQLite驱动程序?等等?(编辑:显然是的。https://bitbucket.org/xerial/sqlite-jdbc) - user1499731
@user 当使用 .Net 写入 MySQL、SQL Server 或 Oracle 时,同样需要外部托管的数据库。在这方面没有任何区别。 - Namphibian
@user - 更新了我的答案,包括对Preferences API的引用。此外,SQLite可以在本地和应用程序内运行。驱动程序也可以集成。不需要服务器。 - Rudi Kershaw
对于我的需求(我确实没有明确说明,所以我不能抱怨),JDBC 有点过头了。我应该要求持久化“设置”,而不是一些模糊的东西。 - user1499731

1
如果您需要一个简单的键值存储,可以考虑使用Properties。
下面是Properties的一个示例简单用法。
public class Program {
    static final Properties Prefs = new Properties();
    static final String Default_Path = "prefs.properties";

    static void loadPreferences() throws IOException { 
        try (FileInputStream fis = new FileInputStream(Default_Path)) {
            Prefs.loadFromXML(fis);
        } catch (FileNotFoundException ex) { 
            // Okay - if not found we'll save it later
        }
    }

    static void savePreferences() throws FileNotFoundException, IOException {
        try (FileOutputStream fos = new FileOutputStream(Default_Path)) {
            Prefs.storeToXML(fos, "Program Preferences");
        }

    }

    public static void main(String[] args) throws IOException {
        loadPreferences();

        if (Prefs.getProperty("FavoriteColor") == null) {
            Prefs.setProperty("FavoriteColor", "black"); 
        }

        System.out.println(Prefs.getProperty("FavoriteColor"));

        savePreferences();
    }
}

生成一个XML文件,prefs.properties

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Program Preferences</comment>
<entry key="FavoriteColor">black</entry>
</properties>

关键笔记

  • 不要使用 Properties.put()。使用 Properties.setProperty()Properties.getProperty()
  • 倾向于使用作为 Properties 的一部分声明的方法,而不是从 Hashtable 继承的方法。

您特别询问了关于注释中的序列化。我不建议将其用于此任务(实际上,我可能不会将其用于任何任务...)。
  • 序列化允许打破类的不变性。例如,将一个实例序列化,然后在外部编辑该实例,最后将其反序列化回对象。
  • implements Serializable 实际上为您的类提供了一个构造函数,因此它无法与单例模式和其他创建模式一起使用。
  • implements Serializable 还公开了除您声明为 transient 之外的所有字段。这意味着类的私有部分是公共接口的一部分。如果您稍后更改它(我的意思是,后续版本可能会在没有仔细控制的情况下破坏它),那就太糟糕了。
  • 此列表不完整...
有人认为可以正确地执行序列化,但肯定很难做到。

1

3
或许把序列化视为最后的手段。将来你会为简便付出代价。 - jdphenix
@jdphenix请解释一下怎么做?4个人不可能都错(对吧)? - user1499731

1

属性是简单的键值配置数据的好建议。

既然您建议Hibernate/JPA,那我会提出嵌入式Derby。它是一个可以在应用程序和内存中嵌入的数据库。 http://db.apache.org/derby/

为了这个目的最好避免序列化。我会将其用于集群或在虚拟机之间发送对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接