Как обновить базовую «базу данных» с помощью файлов .json - PullRequest
0 голосов
/ 05 июня 2018

Я работаю над университетским проектом, написанным на Java.Проект состоит из небольшого программного обеспечения для сети магазинов спортивных товаров.Мой учитель сказал мне сохранять информацию о сотрудниках, спортивные объекты и многое другое (заказы в магазинах, ...) в файлы JSON, используя JSON simple.jar.Мое программное обеспечение в начале загружает списки из файлов .json, вот пример:

private static ArrayList<Person> personale = new ArrayList<Person>();
public ArrayList<Person> readPersonale() throws IOException, org.json.simple.parser.ParseException {
    JSONParser parser = new JSONParser();
    FileReader fileReader = new FileReader("f:\\personale.json");
    JSONObject jsonObject = (JSONObject) parser.parse(fileReader);
    ArrayList<Person> personale = new ArrayList<>();
    JSONArray array = (JSONArray) jsonObject.get("personale");
    for(int i=0; i<array.size(); i++) {
        Person p = new Person();
        JSONObject json = (JSONObject)array.get(i);
        p.setName(json.get("NAME"));
        p.setSurname(json.get("SURNAME"));
        p.setUserCode(json.get("USER CODE"));
        p.setPassword(json.get("PASSWORD"));
        p.setRule(json.get("RULE"));
        personale.add(p);
    }
    fileReader.close();
    return personale;
}

Перед закрытием программного обеспечения моя программа должна удалить содержимое предыдущих файлов .json и переписать все списки в один и тот же список.Файл .json:

    public void writePersonale(ArrayList<Person> list) throws org.json.simple.parser.ParseException, ParseException {

    JSONObject obj = new JSONObject();
    JSONArray Jlist = new JSONArray();
    for(Person e : list) {
        JSONObject json = new JSONObject();
        json.put("NAME", e.getName());
        json.put("SURNAME", e.getSurname());
        json.put("USER CODE", e.getUserCode());
        json.put("PASSWORD", e.getPassword());
        json.put("RULE", e.getRule());
        Jlist.add(json);
    }
    obj.put("personale", Jlist);

    try (FileWriter file = new FileWriter("f:\\personale.json")) {
        file.write(obj.toJSONString());
        file.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Это правильный способ программирования с файлами .json?Есть лучший способ использовать файлы jSON?Спасибо

1 Ответ

0 голосов
/ 05 июня 2018

Хорошо, во-первых, я бы избегал использования библиотеки, которую вы используете для обработки JSON.Ручное создание JSONArrays и т. Д. - скорее боль в заднице, чем продуктивная работа.В этом смысле я бы пошел с Jackson, чтобы выполнить любую сериализацию / десериализацию (запись в и из БД).

Поскольку Jackson может активно отображать типы данных и конвертировать их, вы будете использовать следующие POJO для выполнения вашихзадание:

UserDto

public class UserDto {

    private String name;
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    private String surName;
    public String getSurName() { return surName; }
    public void setSurName(String surName) { this.surName = surName; }

    private Integer userCode;
    public Integer getUserCode() { return userCode; }
    public void setUserCode(Integer userCode) { this.userCode = userCode; }

    private String rule;
    public String getRule() { return rule; }
    public void setRule(String rule) { this.rule = rule; }

    public UserDto() {}

    public UserDto(String name, String surName, Integer userCode, String rule) {
        this.name = name;
        this.surName = surName;
        this.userCode = userCode;
        this.rule = rule;
    }

    @Override
    public String toString() {
        return "UserDto{" +
            "name='" + name + '\'' +
            ", surName='" + surName + '\'' +
            ", userCode=" + userCode +
            ", rule='" + rule + '\'' +
            '}';
    }

}

BulkUserDto

public class BulkUserDto {

    private List<UserDto> userDtos;
    public List<UserDto> getUserDtos() { return userDtos; }
    public void setUserDtos(List<UserDto> userDtos) { this.userDtos = userDtos; }

}

С этими двумя возможностями ваш служебный класс базы данных можно упростить до следующего:

public final class DatabaseUtil {

    private static final String FILE_PATH = "/tmp/db.json";

    private static ObjectMapper objectMapper = new ObjectMapper();

    private DatabaseUtil() {}

    public static List<UserDto> initUserList() throws IOException {
        BulkUserDto dto = objectMapper.readValue(Paths.get(FILE_PATH).toFile(), BulkUserDto.class);
        return dto.getUserDtos();
    }

    public static void saveUserList(BulkUserDto dto) throws IOException {
        String parsedObject = objectMapper.writeValueAsString(dto);
        if (Files.exists(Paths.get(FILE_PATH))) {
            System.out.println("Found old db file under:: " + FILE_PATH + " deleting");
            Files.delete(Paths.get(FILE_PATH));
        }

        FileWriter writer = new FileWriter(Paths.get(FILE_PATH).toFile());
        writer.write(parsedObject);
        writer.flush();
    }

}

Обратите внимание, насколько упорядочен процесс сериализации / десериализации.Для получения дополнительной информации о Джексоне вы можете обратиться к следующему базовому руководству https://www.mkyong.com/java/how-to-convert-java-object-to-from-json-jackson/

Обратите также внимание, что метод сохранения активно проверяет и удаляет старый файл db.json, если он уже присутствует в файловой системе.

Еще одна приятная оптимизация, которую вы можете сделать, - это следующее.Поскольку вы храните все прочитанные пользовательские записи в статическом списке, вы фактически создаете кеш.Я предполагаю, что в противном случае вы вызываете readPersonale через программу только один раз, и, поскольку кажется, что у вас нет связанных проверок, это может привести к его повреждению.Исходя из вышеизложенного, я бы предложил следующее:

Я бы оставил объявление статического списка, но вместо того, чтобы назначить ему пустой список, я бы пошел дальше и оставил его пустым.Затем я бы создал следующий метод, чтобы убедиться, что кеш инициализируется только один раз:

private static final Object LOCK = new Object();
    private static List<UserDto> userCache;
    public static List<UserDto> getUserCache() {
        synchronized (LOCK) {
            if (userCache == null) {
                try {
                    userCache = initUserList();
                } catch (IOException e) {
                    return Collections.emptyList();
                }
            }
            return userCache;
        }
    }

Обратите внимание на синхронизированный блок, который будет гарантировать, что инициализация произойдет только один раз и только первым вызывающим потоком.

Имея это, я бы просто использовал этот кеш для добавления / удаления пользователя, а затем, наконец, просто сохранил это.Обратите внимание, что если вы решите следовать этому, вы должны принять во внимание синхронизацию (при условии, что в вашей программе более одного потока).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...