ManyToOne creates new entry in both tables for every new object - java

I got City and Weather. Weather should point to the city objects in the database. A city can have multiple weather entries. My problem is that each time I add a weather to my db it creates a new city with the same name but other ID.
Weather Entity;
#Entity
public class Weather implements Serializable{
#Id
#GeneratedValue
private int id;
private static final long serialVersionUID = -3562151396218034738L;
private LocalDateTime timeStamp;
private Float windSpeed;
private Float windDir;
private Float humidity;
private Float temperature;
private String weatherDescription;
#ManyToOne(fetch=FetchType.LAZY, cascade = CascadeType.PERSIST)
#JoinColumn(name="city_id")
private City city;
public Weather(){}
public Weather(LocalDateTime timeStamp, Float windSpeed, Float windDir, Float humidity, Float temperature, String weatherDescription, City city){
this.timeStamp = timeStamp;
this.windSpeed = windSpeed;
this.windDir = windDir;
this.humidity = humidity;
this.temperature = temperature;
this.weatherDescription = weatherDescription;
this.city = city;
}
}
City Entity:
#Entity
public class City implements Serializable {
#Id
#GeneratedValue
private int id;
private static final long serialVersionUID = 1L;
private String cityName;
private String cityPostalcode;
#OneToMany(mappedBy = "city")
private List<Weather> weather;
public City(){}
public City(String cityName, String cityPostalcode){
this.cityName = cityName;
this.cityPostalcode = cityPostalcode;
}
My two methods for adding weather to my db.
#Override
public Weather addWeather(Weather weather) throws Exception {
EntityManager em = JpaUtil.createEntityManager();
try {
em.getTransaction().begin();
em.persist(weather);
em.persist(weather.getCity());
em.getTransaction().commit();
} catch (Exception e) {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
throw new RuntimeException(e);
} finally {
if (em.isOpen()) {
em.close();
LOG.info("New Weather entry for " + weather.getCity().getCityName());
}
}
return weather;
}
#Override
public List<Weather> addWeatherWithList(List<Weather> weather) throws Exception {
for (int i = 0; i < weather.size() - 1; i++) {
EntityManager em = JpaUtil.createEntityManager();
em.getTransaction().begin();
try {
em.persist(weather.get(i));
em.persist(weather.get(i).getCity());
em.getTransaction().commit();
} catch (Exception e) {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
throw new RuntimeException(e);
} finally {
if (em.isOpen()) {
em.close();
LOG.info(weather.get(i).toString() + " added to db");
}
}
}
return weather;
}
My table weather:
My table city: (at the moment my weather data only comes from this one city, that's right)
Here a list what I tried so far (all i can remember of at least) and didn't work.
cascade = CascadeType.PERSIST (now I persist both objects, otherwise I get "not marked cascade PERSIST" error)
removing generatedvalue ID's
without OneToMany (inside city) declaration
only using ManyToOne without any specific declarations (like fetchtype)
without join.column
That's all I can remember. If you need further information let me know.
EDIT:
I get my weather data from a webservice.
My WeatherReader:
public class WeatherReader extends RESTReader {
private RESTReader client = new RESTReader();
public List<Weather> getAllWeatherData() {
try {
ObjectMapper mapper = new ObjectMapper();
List<City> citiesToBeCalled = client.deserialize(); // list resulting from deserialization
ArrayList<List<Weather>> allWeatherList = new ArrayList<>();
for (int i = 0; i < 1; i++) { //TODO: replace 1 with citiesToBeCalled.size() to have all cities
String json = client.weatherData(citiesToBeCalled.get(i).getCityName());
List<RawWeatherData> rawWeatherList = Arrays.asList(mapper.readValue(json, RawWeatherData[].class));
List<Weather> weatherList = new ArrayList<>();
for (int j = 0; j < rawWeatherList.size(); j++){
weatherList.add(rawWeatherList.get(j).convertToWeather());
}
allWeatherList.add(weatherList);
}
return allWeatherList.stream().flatMap(x -> x.stream()).collect(Collectors.toList());
} catch (Exception e) {
System.out.println("Error:" + e.getMessage());
return null;
}
}
}
My RestReader.class:
public class RESTReader {
private String masterDataCityFilePath = "t.tmp";
private static final String BASE_URI = "removed because of privacy reasons";
private HttpClient httpClient = HttpClient.newHttpClient();
private String mimeType = "application/json";
//TODO: this is already good and can be used for the CityReader
public String allCitiesAsJson() throws Exception {
HttpRequest req = HttpRequest.newBuilder(URI.create(BASE_URI + "cities")).headers("Accept", mimeType).GET().build();
System.out.println("REQUEST SENT:" + req);
HttpResponse<String> res = httpClient.send(req, HttpResponse.BodyHandlers.ofString());
if (res.statusCode() == 200) {
return res.body().toString();
} else {
throw new Exception("Status-code:" + res.statusCode());
}
}
public String weatherData(String cityname) throws Exception{
String realcityname = cityname.replace(" ", "%20");
HttpRequest req = HttpRequest.newBuilder(URI.create(BASE_URI + realcityname)).headers("Accept", mimeType).GET().build();
System.out.println("REQUEST SENT:" + req);
HttpResponse<String> res = httpClient.send(req, HttpResponse.BodyHandlers.ofString());
if (res.statusCode() == 200) {
return res.body().toString();
} else {
throw new Exception("Status-code:" + res.statusCode());
}
}
public void serialize(List<City> cityList) { //Creating
try {
FileOutputStream fileOut = new FileOutputStream(masterDataCityFilePath); //(MasterdataCities)
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(cityList);
out.close();
fileOut.close();
System.out
.println("Master data file saved under: " + masterDataCityFilePath);
} catch (IOException i) {
System.err.println("There was an error saving the file!");
System.err.println("Wrong directory?");
i.printStackTrace();
}
}
public List<City> deserialize() {
try {
FileInputStream fileIn = new FileInputStream(masterDataCityFilePath);
ObjectInputStream in = new ObjectInputStream(fileIn);
List<City> cityList = (List<City>) in.readObject();
in.close();
System.out
.println("Loaded cities from: " + masterDataCityFilePath);
return cityList;
} catch (IOException | ClassNotFoundException e) {
System.err.println("There was an error loading from:" + masterDataCityFilePath);
System.err.println("Wrong directory?\n");
System.out.println("Directory is: " + masterDataCityFilePath);
e.printStackTrace();
}
return null;
}
public String getMasterDataCityFilePath() {
return masterDataCityFilePath;
}
public void setMasterDataCityFilePath(String masterDataCityFilePath) {
this.masterDataCityFilePath = masterDataCityFilePath;
}
}
EDIT 2:
my convertToWeather();
public Weather convertToWeather(){
try {
Weather weather = new Weather();
weather.setCity(city);
String str = lastUpdateTime;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse(str, formatter);
weather.setTimeStamp(dateTime);
//assign wind speed
String datacontent[] = data.split("#");
String windSpeedValue[] = datacontent[12].split(":", 2); // specify data content number
if (windSpeedValue[1].equals("unknown")){
weather.setWindSpeed(null);
} else {
weather.setWindSpeed(Float.parseFloat(windSpeedValue[1])); //general just gimme the value specifier
}
//assign wind direction
String windDirValue[] = datacontent[13].split(":", 2); // specify data content number
if (windDirValue[1].equals("unknown")){
weather.setWindDir(null);
} else {
weather.setWindDir(Float.parseFloat(windDirValue[1])); //general just gimme the value specifier
}
//assign humidity
String humidityValue[] = datacontent[11].split(":", 2); // specify data content number
if (humidityValue[1].equals("unknown")){
weather.setHumidity(null);
} else {
weather.setHumidity(Float.parseFloat(humidityValue[1])); //general just gimme the value specifier
}
//assign temperature
String temperatureValue[] = datacontent[9].split(":", 2); // specify data content number
if (temperatureValue[1].equals("unknown")){
weather.setTemperature(null);
} else {
weather.setTemperature(Float.parseFloat(temperatureValue[1])); //general just gimme the value specifier
}
//assign description
String descriptionValue[] = datacontent[8].split(":", 2); // specify data content number
if (descriptionValue[1].equals("unknown")){
weather.setWeatherDescription("unknown");
} else {
weather.setWeatherDescription(descriptionValue[1]); //general just gimme the value specifier
}
return weather;
} catch (Exception e) {
System.out.println("Error:" + e.toString());
return null;
}
}

The problem is simple, for JPA, if your entity does not have any ID then it means that it will do a INSERT if ID is null and UPDATE if ID is not null.
From what I read, your city instance is always a new object or at least, an object not handle in the persistence context.
In your code, you should first check if there is already a named city in your database, if yes attach it this to your weather. If not just insert it (as you would have done in SQL...)
To avoid weird behavior I can also suggest to you to add a unique constraint on the city names.
Let me know if it solve your issue

Remove this piece of code:
#OneToMany(mappedBy = "city")
private List<Weather> weather;
I believe that this mapping in the City class is also writing the data to your db table. For ManyToOne joins, having the mapping one way should suffice. Compare this documents:
https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/ManyToOne.html
and https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/OneToMany.html
Hope it helps.

Show the code in which you create Weather instances, that should be the problem.
The codes shown in your question do not decide how your data will be. Instead, they tell JPA: hey, jpa, please create a new transaction, translate these object state into appropriate SQL INSERT queries and execute them.
So, what decides your data in DB is state of object right before you call EntityManager to persist it.

Related

Java how to combine text and combo filters to show data in tableview

I have two class:
public class Personal {
private int id;
private String name;
private String dni;
private double amount;
private int idArea;
public Personal(int id, String name, String dni, double amount, int area){
this.id = id;
this.name = name;
this.dni = dni;
this.amount = amount;
this.idArea = area;
}
//getters and setters
}
And
public class Area {
private int id;
private String name;
public Departamento(int id, String name) {
this.id = id;
this.name = name;
}
//getters and setters..}
Then in my controller I have this metodh to populate and filter tableview via a textbox`
private void InitTable() {
MySqlPersonaDAO daoP = new MySqlPersonaDAO(Conexion.getConnection());
try{
listaPersona = daoP.getAll();
}catch (DAOException e){
e.printStackTrace();
}
FilteredList<Personal> listaFiltrada = new FilteredList<>(listaPersona, p -> true);
// ADD listener to text
txtFiltrarPersona.textProperty().addListener((observable, oldValue, newValue) -> {
listaFiltrada.setPredicate(personal -> {
// If filter text is empty, display all persons.
if (newValue == null || newValue.isEmpty()) {
return true;
}
String lowerCaseFilter = newValue.toLowerCase();
if (personal.getName().toLowerCase().contains(lowerCaseFilter)) {
return true; // Filter matches name.
} else if (personal.getDni().toLowerCase().contains(lowerCaseFilter)) {
return true; // Filter matches DNI.
}
return false; // Does not match.
});
});
SortedList<Personal> sortedData = new SortedList<>(listaFiltrada);
sortedData.comparatorProperty().bind(myTable.comparatorProperty());
try {
myTable.setItems(sortedData);
}
catch(Exception e){
e.printStackTrace();
System.out.println("Error on Building Data");`
Im newbie in Java. So far my code works: Populate tableview(SQL) and filter by name or dni probability in not the best way.
My Problem:
Now I have to add a second filter in a combobox, to show in my tableview people depending on area and I have no idea how to make it.
I need a second filterList or can I use the same(listaFiltrada)?
My attempt:
comboArea.setOnAction((event) -> {
Area selectedArea = comboArea.getSelectionModel().getSelectedItem();
MySqlPersonaDAO daoP = new MySqlPersonaDAO(Conexion.getConnection());
try {
NewObservableList = daoP.getByArea(selectedArea.getId());
}catch (DAOException e){
System.out.print("Dao exception: " + e.getCause());
}
//Just for check:
for (Personal p:NewObservableList ){
System.out.println(p.getNombre());
//The data is fine.
}
});
But I need to combine with my other filter, any help/guide is fine for me.
and of course sorry for my terrible English.
Saludos!

How to input data in the very best way in object programming Java

Just to let you know:
I know how to use Scanner od BufferedReader, just dont know where to use it in this case.
I am working on my first bigger app in Java.
(I had to use SQLite as a DB)
That's some kind of gym app, where I will add my workouts (4 simple variables)
And then it will be saved in DB and sorted to read out.
My question is...
How should I add an Input from the user?
I have setters and getters and no Idea where this input should be added.
In main class? Should I build a new method?
package bazadanych;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
DBConnector d = new DBConnector();
d.addWorkout( "bicek", 12, 5,22052019);
List<Workout> workouts = d.allWorkouts();
for (int i=0; i < workouts.size(); i++) {
System.out.println("---------------------------------");
System.out.println("The name of the excersise: " + workouts.get(i).getName());
System.out.println(" Number of reps: " + workouts.get(i).getReps());
System.out.println(" Weight: " + workouts.get(i).getWeight() + "kg");
System.out.println("Date: " + workouts.get(i).getDate());
System.out.println("---------------------------------");
}
}
package bazadanych;
public class Workout extends DBConnector {
private int workoutId;
private String name;
private int reps;
private int weight;
private int date;
public Workout(int workoutId, String name, int weight, int reps, int date)
{
setWorkoutId(workoutId);
setName(name);
setWeight(weight);
setReps(reps);
setDate(date);
}
// Getters
public int getDate()
{
return date;
}
public int getWorkoutId()
{
return workoutId;
}
public String getName()
{
return name;
}
public int getReps()
{
return reps;
}
public int getWeight()
{
return weight;
}
//Setters
public void setDate(int date)
{
this.date = date;
}
public void setName(String name)
{
this.name = name;
}
public void setReps(int reps)
{
this.reps = reps;
}
public void setWorkoutId(int workoutId)
{
this.workoutId = workoutId;
}
public void setWeight(int weight)
{
this.weight = weight;
}
}
package bazadanych;
import java.sql.*;
import java.util.LinkedList;
import java.util.List;
public class DBConnector {
// connection with datebase
private Connection conn;
// The object used to execute a static SQL statement and returning the results
private Statement stat;
// Construct
public DBConnector()
{
try
{
Class.forName("org.sqlite.JDBC");
}
catch (ClassNotFoundException e)
{
System.err.println("There is no JDBC driver");
e.printStackTrace();
}
try
{
conn = DriverManager.getConnection("jdbc:sqlite:GymApp.db"); // GymApp will be the name of the datebase
stat = conn.createStatement();
}
catch (SQLException e)
{
System.err.println("I can not connect");
}
CreateStructure();
}
public boolean CreateStructure()
{
// Rule to delete the table and create new, when we want to rework number of columnes etc.
// String dropFirst = "DROP TABLE IF EXISTS workouts;";
String sql = "CREATE TABLE IF NOT EXISTS workouts"
+ "("
+ "workoutId INTEGER PRIMARY KEY AUTOINCREMENT,"
+ "name varchar(100),"
+ "reps INTEGER, "
+ " weight INTEGER,"
+ " date INTEGER"
+ ")";
try
{
// stat.execute(dropFirst);
stat.execute(sql);
}
catch (SQLException e)
{
System.err.println("There is a problem by Structure creation");
e.printStackTrace();
return false;
}
return true;
}
public boolean addWorkout( String name, int reps, int weight, int date)
{ String sql = " insert into workouts values (Null,?,?,?,?);";
try
(PreparedStatement pStmt = conn.prepareStatement(sql)){
pStmt.setString(1, name);
pStmt.setInt(2,reps);
pStmt.setInt(3,weight);
pStmt.setInt(4, date);
pStmt.execute();
}
catch(SQLException e)
{
System.err.println("Can not add a new contact");
e.printStackTrace();
return false;
}
return true;
}
public List<Workout> allWorkouts()
{
List<Workout> workouts = new LinkedList<Workout>();
try {
ResultSet show = stat.executeQuery("SELECT * FROM workouts ORDER BY date");
int id;
String name;
int reps;
int weight;
int date;
while (show.next())
{
id = show.getInt("workoutId");
name = show.getString("name");
reps = show.getInt("reps");
weight = show.getInt("weight");
date = show.getInt("date");
workouts.add(new Workout(id, name,reps,weight,date));
}
}
catch (SQLException e)
{
e.printStackTrace();
return null;
}
return workouts;
}
public void closeConnection() {
try{
conn.close();
}
catch (SQLException e) {
System.err.println("There is connection closing error");
e.printStackTrace();
}
}
}
To answer your main question, you should add the input from the user in the main method. You'd use an instance of Scanner to read the values of workout name, reps and weight. Date you could simply pick up the current date, code sample below.
A few other recommendations:
1 - Change the workout date to long, that's a standard in the industry.
2 - The method CreateStructure does not follow Java coding standards, rename it to createStructure.
3 - You are storing the workout ID as NULL, that could cause you trouble later when trying to retrieve the data from the database.
Code sample:
public static void main(String[] args) {
DBConnector d = new DBConnector();
// Retrieve input from the user
Scanner sc = new Scanner(System.in);
String name = sc.nextLine();
int reps = sc.nextInt();
int weight = sc.nextInt();
// create the workout with the data
d.addWorkout( name, reps, weight, LocalDate.now().toEpochDay());
List<Workout> workouts = d.allWorkouts();
// print workouts
}

ArrayList cannot be case to Set In hibernate using Texo generated Models

i have generated texo model from EMF.
Following is the code
try{
Session session = factory.openSession();
Transaction tx = null;
Integer employeeID = null;
try{
tx = session.beginTransaction();
Country country = new Country();
country.setCode("PK");;
country.setCountry("PAKISTAN");
System.out.println((Integer) session.save(country));
//^ HERE THE ERROR COMES
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}
}catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
When i try to add country object with or without locations, I get the error
Failed to create sessionFactory object.java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.util.Set
The model is generated by Texo have List and simple getter and setter generated.
I have checked this link. but i dont find any answer.
COUNTRY.java
import java.util.ArrayList;
import java.util.List;
public class Country {
private int iD = 0;
private String country = null;
private String code = null;
private List<Location> locations = new ArrayList<Location>();
public int getID() {
return iD;
}
public void setID(int newID) {
iD = newID;
}
public String getCountry() {
return country;
}
public void setCountry(String newCountry) {
country = newCountry;
}
public String getCode() {
return code;
}
public void setCode(String newCode) {
code = newCode;
}
public List<Location> getLocations() {
return locations;
}
public void setLocations(List<Location> newLocations) {
locations = newLocations;
}
#Override
public String toString() {
return "Country " + " [iD: " + getID() + "]" + " [country: "
+ getCountry() + "]" + " [code: " + getCode() + "]";
}
}
As discussed in Texo , I have to generate SET instead of LIST in java entities in order to work with Hibernate.
So i had to configure the TEXO to do this for all entities.
Generate the Annotation Model.
Find the entity ( locations ) and add new annotation. goto its properties and set USE LIST = FALSE
Generate the texo models and all the required entities will be change from List to Set
please try changing Set<Location> sLoc = new HashSet<Location>(locations); to List<Location> sLoc = new ArrayList<Location>(locations);. U have ur locations as array and sLoc as Hashset so it is giving casting exception..
Hope this solves your problem

get specified value from Json Array

how r u
I need to access a database and read data from a table then get the values of it so I create a php file to print a database in JSON format to access data:
<?php
try{
$db=new PDO('mysql:host=localhost;dbname='database','table','password');
$row=$db->prepare('select * from users' );
$row->execute();
$json_data=array();
foreach($row as $rec)
{
$json_array['userId']=$rec['userId'];
$json_array['user']=$rec['user'];
$json_array['pass']=$rec['pass'];
$json_array['name']=$rec['name'];
$json_array['family']=$rec['family'];
$json_array['gender']=$rec['gender'];
$json_array['birthday']=$rec['birthday'];
array_push($json_data,$json_array);
}
echo json_encode($json_data);
} catch(PDOExcetion $e)
{
print "Error: " . $e->getMessage()."<br/>";
die();
}
?>
and this is the output:
[
{"userId":"1","user":"saly","pass":"666","name":"SalyR","family":"manson","gender":"male","birthday":"1988\/11\/10"},
{"userId":"1","user":"foo","pass":"2657","name":"foo","family":"rocki","gender":"male","birthday":"13989\/2\/07"},
{"userId":"1","user":"mil","pass":"63495","name":"milo","family":"toufa","gender":"male","birthday":"13987\/04\/21"},
{"userId":"1","user":"soos","pass":"03468","name":"soro","family":"radi","gender":"female","birthday":"13990\/08\/09"}
]
I wanna get access to specified value like 'userId' and 'name' and 'birthday'.
I use three methods to get values:
1) getJSONFromDatabase method gets a database URL and returns an JSON String.
public String getJSONFromDatabase(String getDatabaseURL) {
HttpClient client = new DefaultHttpClient();
HttpPost method = new HttpPost(getDatabaseURL);
String result = "";
try {
HttpResponse response = client.execute(method);
int code = response.getStatusLine().getStatusCode();
InputStream stream = response.getEntity().getContent();
result = inputstreamToString(stream);
Log.i("LOG", "Code :" + code);
} catch (IOException e) {
Log.e("Database", "Error Connect to Database!");
e.printStackTrace();
}
return result;
}
2) inputstreamToString method gets an Inputstream and read all lines.
private String inputstreamToString(InputStream getStream) {
BufferedReader reader = new BufferedReader(new InputStreamReader(getStream));
StringBuilder builder = new StringBuilder();
String line;
try {
while ((line = reader.readLine()) != null) {
builder.append(line);
}
return builder.toString();
} catch (IOException e) {
Log.e("Reader", "Error reading stream!");
e.printStackTrace();
}
return "";
}
3) jsonToString method gets JSON String with a String value that we want to get.
public String jsonToString(String getJSONString, String value) {
String userId = "";
try {
JSONObject object = new JSONObject(getJSONString);
userId = object.getString(value);
return userId;
} catch (JSONException e) {
Log.e("JSON", "Error converting!");
e.printStackTrace();
}
return "";
}
so I call methods like this:
String databaseURL = "http://192.168.56.1/saly/getDatabaseTable.php";
String jsonFormat = getJSONFromDatabase(databaseURL);
String userId = jsonToString(jsonFormat, "userId");
String name= jsonToString(jsonFormat, "name");
String birthday= jsonToString(jsonFormat, "birthday");
at the end I get this errors in Log:
JSON: Error converting!
JSON: Error converting!
JSON: Error converting!
when I remove [ ] and write one line just like this JSON String, it works properly, just one line!:
{
"userId":"1",
"user":"saly",
"pass":"666",
"name":"SalyR",
"family":"manson",
"gender":"male",
"birthday":"1988\/11\/10"
}
but it's not gonna work for me because when I print all table of database in JSON format the whole data will print.
I wrote too much and sorry for that, I tried explanation every things.
would you gyus please help me where I wrong?
thank you.
You have to parse it as jsonArray. The following snip will help you.
JSONArray jsonarray = new JSONArray(str);//str= your json string.
for(int i=0; i<jsonarray.length(); i++){
JSONObject obj = jsonarray.getJSONObject(i);
String name = obj.getString("name");
String url = obj.getString("url");
System.out.println(name);
System.out.println(url);
}
Here is the answer for this question.
User.java
it's the user class.
public class User {
private String userId = "";
private String user = "";
private String pass = "";
private String name = "";
private String family = "";
private String gender = "";
private String birthday = "";
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFamily() {
return family;
}
public void setFamily(String family) {
this.family = family;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
#Override
public String toString() {
// TODO Auto-generated method stub
return userId+" "+user+ " "+pass+ " "+name+" "+family+" "+ gender+ " "+ " ";
}
}
you can run this as a test, this example shows how easy it would be to deal with JSON by using Gson library
public class SIx {
public static void main(String[] args) {
ArrayList<User> list = new ArrayList<User>();
System.out.println("#### Object ####");
for (int i = 0; i < 4; i++) {
User user = new User();
user.setUserId("UserId_"+i);
user.setUser("User_"+i);
user.setPass("Pass_"+i);
user.setName("Name_"+i);
user.setGender("Gender_"+i);
user.setFamily("Family_"+i);
user.setBirthday("Birthday_"+i);
list.add(user);
System.out.println(user.toString());
}
String string = (new Gson()).toJson(list);
System.out.println();
System.out.println();
System.out.println(string);
System.out.println();
System.out.println();
ArrayList<User> newList = (new Gson()).fromJson(string, new TypeToken<ArrayList<User>>() {}.getType());
for (int i = 0; i < newList.size(); i++) {
User user = newList.get(i);
System.out.println("UserId_: "+user.getUserId());
System.out.println("User_: "+user.getUser());
System.out.println("Pass_: "+user.getPass());
System.out.println("Name_: "+user.getName());
System.out.println("Gender_: "+user.getGender());
System.out.println("Family_: "+user.getFamily());
System.out.println("Birthday_: "+user.getBirthday());
System.out.println();
}
}
}
output

java.lang.NullPointerException when deserializing

public class ViewBooking extends javax.swing.JFrame {
/**
* Creates new form ViewBooking
*/
public ViewBooking() {
initComponents();
}
public void dispBookingInfo(){
Reservation[] reservations = new Reservation[1];
try {
String searchCust = SearchName.getText();
FileInputStream inStream = new FileInputStream(searchCust +
"booking.dat");
ObjectInputStream objectInputFile = new ObjectInputStream(inStream);
reservations[0] = (Reservation) objectInputFile.readObject();
objectInputFile.close();
} catch (Exception e) {
}
JOptionPane.showMessageDialog(null, reservations[0].getDetails());
}
This is my Reservation class
public class Reservation implements Serializable {
private String name;
private String sDate;
private String eDate;
private String noOfDays;
private String roomNo;
private String totalAmt;
Reservation(String name, String sDate, String eDate, String noOfDays,
String totalAmt, String roomNo) {
this.name = name;
this.totalAmt = totalAmt;
this.roomNo = roomNo;
//throw new UnsupportedOperationException("Not supported yet.");
//To change body of generated methods, choose Tools | Templates.
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getsDate() {
return sDate;
}
public void setsDate(String sDate) {
this.sDate = sDate;
}
public String geteDate() {
return eDate;
}
public void seteDate(String eDate) {
this.eDate = eDate;
}
public String getNoOfDays() {
return noOfDays;
}
public void setNoOfDays(String noOfDays) {
this.noOfDays = noOfDays;
}
public String getRoomNo() {
return roomNo;
}
public void setRoomNo(String roomNo) {
this.roomNo = roomNo;
}
public String getTotalAmt() {
return totalAmt;
}
public void setTotalAmt(String totalAmt) {
this.totalAmt = totalAmt;
}
public String getDetails(){
return "Name: " + name + "\n" + "From: " + sDate + " to " + eDate
+ "\n" + "Duration: " + noOfDays + "Room No: " + roomNo
+ "Total amount: RM" + totalAmt;
}
}
I am able to serialize the Reservation object but when i try to deserialize it and read the data, i get a NullPointerException error at this line:
JOptionPane.showMessageDialog(null, reservations[0].getDetails());
What is the problem here?
I have changed my code into the following:
public void dispBookingInfo() throws Exception{
String searchCust = SearchName.getText();
FileInputStream inStream = new FileInputStream(searchCust + " booking.dat");
ObjectInputStream objectInputFile = new ObjectInputStream(inStream);
Reservation[] reservations = new Reservation[1];
try {
if (reservations[0] != null) {
reservations[0] = (Reservation) objectInputFile.readObject();
}
objectInputFile.close();
} catch (Exception e) {
System.out.println("error!");
}
JOptionPane.showMessageDialog(null, reservations[0].getDetails());
}
The NullPointerException error is gone but I still cant retrieve any data. Why is my reservation[0] null?
In your
try {
...
} catch () {
...
}
statement you ignore any exception thrown. Hence it is possible that
reservations[0] = (Reservation) objectInputFile.readObject();
does not initialize reservation[0] at all, which would cause an NullPointerException when accessing:
reservation[0].getDetails();
Here is your problem:
if (reservations[0] != null) {
reservations[0] = (Reservation) objectInputFile.readObject();
}
reservations[0] will always be null at this point because you've only just initialised the array. This stops the call that would populate the data into here, so when you try and access it later on with reservations[0].getDetails() that element is inevitably still null. The null check is completely unneeded, so remove it.
You may also wish to consider defining a serialVersionUID for your class.
To do so, add this as a class variable:
private static final long serialVersionUID = <some_long_number>;
Replace <some_long_number> with any long that you like. Once done, you'll have to re-create your file with a 'new' version of your class, otherwise the version numbers won't match.
If you don't do this, the JVM automatically generates a serialVersionUID for you based upon the class itself, so if you've changed certain things about the class, you may suddenly find that you have problems deserialising older versions of the class.

Categories