Updating JDO M-N relation in Datanucleus is not persisted - many-to-many

I have been exploring the Datanucleus framework and was trying some of the examples provided in the documentation. I got stuck in the M-N relation example using Sets. When I try to remove an object from the Set it is removed from the Set, but once I persist the container objects, the entry in the join table is not removed. This results in my container objects still holding the removed object.
I have a unit test that exposes the issue:
#Test
public void testMNRelation() {
final Product product = new Product();
product.setName("Product 1");
product.setPrice(100);
final Product product2 = new Product();
product2.setName("Product 2");
product2.setPrice(130);
final Supplier supplier = new Supplier();
supplier.setName("Supplier 1");
Set<Supplier> suppliers = product.getSuppliers();
suppliers.add(supplier);
Set<Product> products = supplier.getProducts();
products.add(product2);
final PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory("MyStore");
PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
try {
tx.begin();
pm.makePersistent(product);
pm.makePersistent(product2);
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
pm.close();
pm = pmf.getPersistenceManager();
tx = pm.currentTransaction();
try {
tx.begin();
System.out.println();
System.out.println("Fetch from store (before removal)");
Supplier s = pm.getObjectById(Supplier.class, supplier.getId());
System.out.println("supplier name: " + s.getName());
System.out.println("# products: " + s.getProducts().size());
Product p = pm.getObjectById(Product.class, product.getId());
System.out.println("product name: " + p.getName());
System.out.println("# suppliers: " + p.getSuppliers().size());
Product p2 = pm.getObjectById(Product.class, product2.getId());
System.out.println("product name: " + p2.getName());
System.out.println("# suppliers: " + p2.getSuppliers().size());
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
pm.close();
Set<Product> updatedProducts = supplier.getProducts();
updatedProducts.remove(product);
Set<Supplier> updatedSuppliers = product.getSuppliers();
updatedSuppliers.remove(supplier);
System.out.println();
System.out.println("Before persist (after removal)");
System.out.println("supplier name: " + supplier.getName());
System.out.println("# products: " + supplier.getProducts().size());
System.out.println("product name: " + product.getName());
System.out.println("# suppliers: " + product.getSuppliers().size());
System.out.println("product name: " + product2.getName());
System.out.println("# suppliers: " + product2.getSuppliers().size());
pm = pmf.getPersistenceManager();
tx = pm.currentTransaction();
try {
tx.begin();
pm.makePersistent(supplier);
pm.makePersistent(product);
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
pm.close();
System.out.println();
System.out.println("After persist");
System.out.println("supplier name: " + supplier.getName());
System.out.println("# products: " + supplier.getProducts().size());
System.out.println("product name: " + product.getName());
System.out.println("# suppliers: " + product.getSuppliers().size());
System.out.println("product name: " + product2.getName());
System.out.println("# suppliers: " + product2.getSuppliers().size());
pm = pmf.getPersistenceManager();
tx = pm.currentTransaction();
try {
tx.begin();
System.out.println();
System.out.println("Fetch from store");
Supplier s = pm.getObjectById(Supplier.class, supplier.getId());
System.out.println("supplier name: " + s.getName());
System.out.println("# products: " + s.getProducts().size());
Product p = pm.getObjectById(Product.class, product.getId());
System.out.println("product name: " + p.getName());
System.out.println("# suppliers: " + p.getSuppliers().size());
Product p2 = pm.getObjectById(Product.class, product2.getId());
System.out.println("product name: " + p2.getName());
System.out.println("# suppliers: " + p2.getSuppliers().size());
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
pm.close();
}
And the 2 types used in the example from http://www.datanucleus.org/products/datanucleus/jdo/orm/many_to_many.html
#PersistenceCapable(detachable="true")
public class Supplier {
#PrimaryKey
#Persistent(valueStrategy=IdGeneratorStrategy.INCREMENT)
private long id;
#Persistent
private String name;
#Persistent(mappedBy="suppliers")
private Set<Product> products = new HashSet<Product>();
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Product> getProducts() {
return products;
}
public void setProducts(Set<Product> products) {
this.products = products;
}
#Override
public boolean equals(Object o) {
if(this.getId() == 0) {
return false;
}
if(o instanceof Supplier) {
Supplier other = (Supplier) o;
return this.getId() == other.getId();
}
return false;
}
#Override
public int hashCode() {
return Long.toString(this.getId()).hashCode();
}
}
And
#PersistenceCapable(detachable="true")
public class Product {
#PrimaryKey
#Persistent(valueStrategy=IdGeneratorStrategy.INCREMENT)
private long id;
#Persistent
private String name;
#Persistent
private double price;
#Persistent(table="PRODUCTS_SUPPLIERS")
#Join(column="PRODUCT_ID")
#Element(column="SUPPLIER_ID")
private Set<Supplier> suppliers = new HashSet<Supplier>();
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Set<Supplier> getSuppliers() {
return suppliers;
}
public void setSuppliers(Set<Supplier> suppliers) {
this.suppliers = suppliers;
}
#Override
public boolean equals(Object o) {
if(getId() == 0) {
return false;
}
if(o instanceof Product) {
Product other = (Product) o;
return this.getId() == other.getId();
}
return false;
}
#Override
public int hashCode() {
return Long.toString(this.getId()).hashCode();
}
}
Now, in the console I get
Fetch from store (before removal)
supplier name: Supplier 1
# products: 2
product name: Product 1
# suppliers: 1
product name: Product 2
# suppliers: 1
Before persist (after removal)
supplier name: Supplier 1
# products: 1
product name: Product 1
# suppliers: 0
product name: Product 2
# suppliers: 1
After persist
supplier name: Supplier 1
# products: 1
product name: Product 1
# suppliers: 1
product name: Product 2
# suppliers: 1
Fetch from store
supplier name: Supplier 1
# products: 1
product name: Product 1
# suppliers: 1
product name: Product 2
# suppliers: 1
I would expect something like
Fetch from store (before removal)
supplier name: Supplier 1
# products: 2
product name: Product 1
# suppliers: 1
product name: Product 2
# suppliers: 1
Before persist (after removal)
supplier name: Supplier 1
# products: 1
product name: Product 1
# suppliers: 0
product name: Product 2
# suppliers: 1
After persist
supplier name: Supplier 1
# products: 1
product name: Product 1
# suppliers: 0
product name: Product 2
# suppliers: 1
Fetch from store
supplier name: Supplier 1
# products: 1
product name: Product 1
# suppliers: 0
product name: Product 2
# suppliers: 1
My persistence.xml includes:
<property name="datanucleus.DetachAllOnCommit" value="true" />
<property name="datanucleus.attachSameDatastore" value="true" />
<property name="datanucleus.CopyOnAttach" value="false" />
<property name="datanucleus.cache.collections.lazy" value="true" />
<property name="datanucleus.manageRelationships" value="true" />
<property name="datanucleus.manageRelationshipsChecks" value="true" />
Any idea on how to solve this?

I've got a solution to the issue. The issue seems to relate to my persistence settings. I changed the settings to
<property name="datanucleus.DetachAllOnCommit" value="true" />
<property name="datanucleus.attachSameDatastore" value="true" />
<property name="datanucleus.CopyOnAttach" value="true" />
<property name="datanucleus.cache.collections.lazy" value="true" />
<property name="datanucleus.manageRelationships" value="false" />
<property name="datanucleus.manageRelationshipsChecks" value="false" />
<property name="datanucleus.persistenceByReachabilityAtCommit" value="false" />
as I now handle both sides of the relation in my implementation.
Furthermore I implemented a Factory to simplify my test
public class Factory {
private static final PersistenceManagerFactory pmf = get();
private static PersistenceManagerFactory get() {
return JDOHelper.getPersistenceManagerFactory("MyStore");
}
public static Product buildProduct(String name, double price) {
Product product = new Product();
product.setName(name);
product.setPrice(price);
save(product);
return product;
}
public static Supplier buildSupplier(String name) {
Supplier supplier = new Supplier();
supplier.setName(name);
save(supplier);
return supplier;
}
public static void addRelation(final Supplier supplier, final Product product) {
product.getSuppliers().add(supplier);
supplier.getProducts().add(product);
save(product, supplier);
}
public static void removeRelation(Supplier supplier, Product product) {
product.getSuppliers().remove(supplier);
supplier.getProducts().remove(product);
save(product, supplier);
}
public static Product loadProduct(long id) {
return (Product) load(Product.class, id);
}
public static Supplier loadSupplier(long id) {
return (Supplier) load(Supplier.class, id);
}
private static void save(final Object... objects) {
PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
try {
tx.begin();
pm.makePersistentAll(objects);
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
pm.close();
}
private static Object load(Class<?> clazz, long id) {
final Object[] result = new Object[1];
PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
try {
tx.begin();
result[0] = pm.getObjectById(clazz, id);
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
pm.close();
if (result[0] == null) {
throw new NoSuchElementException(clazz.getSimpleName() + " with id=" + id + " cannot be found");
}
return result[0];
}
}
So the test is simply expressed as
#Test
public void testFactoryApproach() {
Product p1 = Factory.buildProduct("product1", 50);
Product p2 = Factory.buildProduct("product2", 70);
Supplier s1 = Factory.buildSupplier("Supplier1");
System.out.println("Initial:");
System.out.println(p1);
System.out.println(p2);
System.out.println(s1);
System.out.println();
Factory.addRelation(s1, p1);
Factory.addRelation(s1, p2);
System.out.println("Relations after add:");
System.out.println(p1);
System.out.println(p2);
System.out.println(s1);
System.out.println();
Factory.removeRelation(s1, p1);
System.out.println("Relations after remove:");
System.out.println(p1);
System.out.println(p2);
System.out.println(s1);
System.out.println();
System.out.println("Relations after load:");
System.out.println(Factory.loadProduct(p1.getId()));
System.out.println(Factory.loadProduct(p2.getId()));
System.out.println(Factory.loadSupplier(s1.getId()));
}
Which result in the following output
Initial:
Product:11 (product1) - # suppliers = 0 []
Product:12 (product2) - # suppliers = 0 []
Supplier:11 (Supplier1) - # products = 0 []
Relations after add:
Product:11 (product1) - # suppliers = 1 [11:Supplier1]
Product:12 (product2) - # suppliers = 1 [11:Supplier1]
Supplier:11 (Supplier1) - # products = 2 [11:product1, 12:product2]
Relations after remove:
Product:11 (product1) - # suppliers = 0 []
Product:12 (product2) - # suppliers = 1 [11:Supplier1]
Supplier:11 (Supplier1) - # products = 1 [12:product2]
Relations after load:
Product:11 (product1) - # suppliers = 0 []
Product:12 (product2) - # suppliers = 1 [11:Supplier1]
Supplier:11 (Supplier1) - # products = 1 [12:product2]

Related

Values changes from double to integer when saving to mysql database

Entities:
Simulation:
package Simulations.Entity;
import lombok.*;
import javax.persistence.*;
import java.util.List;
#Builder
#Table
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class Simulation {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column
private Long id;
#Column(name = "N")
private String simulation_Name;
#Column(name = "P")
private Double population_Size;
#Column(name = "I")
private Double initial_Infected_Number;
#Column(name = "R")
private Double how_Many_One_Infects;
#Column(name = "M")
private Double mortality_Rate;
#Column(name = "Ti")
private Double number_Of_Days_To_Recovery;
#Column(name = "Tm")
private Double number_Of_Days_To_Death;
#Column(name = "Ts")
private Double simulation_Time;
#OneToMany(mappedBy = "simulation", cascade = CascadeType.REMOVE)
private List<SimulationsValues> simulationsValues;
}
SimulationValues:
package Simulations.Entity;
import lombok.*;
import javax.persistence.*;
#Builder
#Table
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class SimulationsValues {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column
private Long id;
#Column(name = "Day")
private Double day;
#Column(name = "Pi")
private Double number_Of_Infected;
#Column(name = "Pv")
private Double healthy_Prone_To_Infection;
#Column(name = "Pm")
private Double dead;
#Column(name = "Pr")
private Double regained_Health_And_Immunity;
#ManyToOne
#JoinColumn(name = "simulation_id", referencedColumnName = "id")
private Simulation simulation;
}
Logic calss:
package Simulations.Services;
import Simulations.Entity.Simulation;
import Simulations.Entity.SimulationsValues;
import Simulations.Repositories.SimulationRepository;
import Simulations.Repositories.SimulationsValuesRepository;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
#RequiredArgsConstructor
#Component
#Aspect
public class EachRemainingDayService {
private final SimulationRepository simulationRepository;
private final SimulationsValuesRepository simulationsValuesRepository;
#Pointcut("#annotation(Simulations.Annotations.MyAnnotation)")
public void MyAnnotationMethod() {
}
public List<Simulation> getSimulations() {
List<Simulation> listOdIds = new ArrayList<>(simulationRepository.findAll());
listOdIds.sort(Comparator.comparing(Simulation::getId));
return listOdIds;
}
public List<SimulationsValues> getSimulationsValues() {
List<SimulationsValues> listOdIdsOfValues = new ArrayList<>(simulationsValuesRepository.findAll());
listOdIdsOfValues.sort(Comparator.comparing(SimulationsValues::getId));
return listOdIdsOfValues;
}
//3 zapis wynikow do bazy
#After("MyAnnotationMethod()")// zmienilem z Before
public void SimulationParametersForRemainingDays() {
var sim = getSimulations();
var newestSimulation = simulationRepository.getById(sim.get(sim.size() - 1).getId());
var simVal = getSimulationsValues();
var newestSimulationsVal = simulationsValuesRepository
.getById(simVal.get(simVal.size() - 1).getId());
//zapisanie do bazy TO LOGIKA!!!
for (double i = 2; i <= newestSimulation.getSimulation_Time(); i++) {
if (newestSimulationsVal.getHealthy_Prone_To_Infection() <= 0) {
break;
}
if (i >= newestSimulation.getNumber_Of_Days_To_Death()
&& i < newestSimulation.getNumber_Of_Days_To_Recovery()) {
sim = getSimulations();
newestSimulation = simulationRepository.getById(sim.get(sim.size() - 1).getId());
simVal = getSimulationsValues();
newestSimulationsVal = simulationsValuesRepository
.getById(simVal.get(simVal.size() - 1).getId());
SimulationsValues simulation_values;
Simulation finalNewestSimulation1 = newestSimulation;
double finalI = i;
simulation_values = SimulationsValues.builder()
.day(i)
.healthy_Prone_To_Infection(newestSimulation.getPopulation_Size() -
(((newestSimulation.getHow_Many_One_Infects())
* newestSimulationsVal.getNumber_Of_Infected()
+ newestSimulationsVal.getNumber_Of_Infected())))
.number_Of_Infected((((newestSimulation.getHow_Many_One_Infects())
* newestSimulationsVal.getNumber_Of_Infected()
+ newestSimulationsVal.getNumber_Of_Infected())//L24
- (newestSimulation.getMortality_Rate() * (double) ((simulationsValuesRepository
.findAll().stream().filter(e -> e.getDay() == finalI + 1 - finalNewestSimulation1
.getNumber_Of_Days_To_Death()))
.collect(Collectors.toList()).get((int) (simulationsValuesRepository.findAll().stream()
.filter(e -> e.getDay() == (finalI + 1 - finalNewestSimulation1
.getNumber_Of_Days_To_Death()))).count() - 1).getNumber_Of_Infected()))))//V24
.regained_Health_And_Immunity(0d)// Z24
.dead((newestSimulation.getMortality_Rate() * (double) ((simulationsValuesRepository
.findAll().stream().filter(e -> e.getDay() == finalI + 1 - finalNewestSimulation1
.getNumber_Of_Days_To_Death()))
.collect(Collectors.toList()).get((int) (simulationsValuesRepository.findAll().stream()
.filter(e -> e.getDay() == (finalI + 1 - finalNewestSimulation1
.getNumber_Of_Days_To_Death()))).count() - 1).getNumber_Of_Infected()))
- newestSimulationsVal.getDead())//V24
.build();
var simId = simulationsValuesRepository.save(simulation_values);
simId.setSimulation(newestSimulation);//dodane
var simVal2 = newestSimulation.getSimulationsValues();
simVal2.add(simId);
newestSimulation.setSimulationsValues(simVal2);
simulationRepository.save(newestSimulation);
} else if (i >= newestSimulation.getNumber_Of_Days_To_Recovery()) {
sim = getSimulations();
newestSimulation = simulationRepository.getById(sim.get(sim.size() - 1).getId());
simVal = getSimulationsValues();
newestSimulationsVal = simulationsValuesRepository
.getById(simVal.get(simVal.size() - 1).getId());
Simulation finalNewestSimulation1 = newestSimulation;
double finalI = i;
SimulationsValues simulation_values;
simulation_values = SimulationsValues.builder()
.day(i)
.healthy_Prone_To_Infection(newestSimulation.getPopulation_Size() -
((newestSimulation.getHow_Many_One_Infects())
* newestSimulationsVal.getNumber_Of_Infected()))
.number_Of_Infected(((newestSimulation.getHow_Many_One_Infects())
* newestSimulationsVal.getNumber_Of_Infected()
+ newestSimulationsVal.getNumber_Of_Infected())//L24
- (newestSimulation.getMortality_Rate() * (double) ((simulationsValuesRepository
.findAll().stream().filter(e -> e.getDay() == finalI + 1 - finalNewestSimulation1
.getNumber_Of_Days_To_Death()))
.collect(Collectors.toList()).get((int) (simulationsValuesRepository.findAll().stream()
.filter(e -> e.getDay() == (finalI + 1 - finalNewestSimulation1
.getNumber_Of_Days_To_Death()))).count() - 1).getNumber_Of_Infected())//V24
- (((1 - newestSimulation.getMortality_Rate()) * (simulationsValuesRepository
.findAll().stream().filter(e -> e.getDay() == finalI + 1 - finalNewestSimulation1
.getNumber_Of_Days_To_Recovery()))
.collect(Collectors.toList()).get((int) (simulationsValuesRepository.findAll().stream()
.filter(e -> e.getDay() == finalI + 1 - finalNewestSimulation1
.getNumber_Of_Days_To_Recovery())).count() - 1)
.getNumber_Of_Infected()))//Z24
))
.regained_Health_And_Immunity((1 - newestSimulation.getMortality_Rate()) *
(simulationsValuesRepository.findAll()
.stream().filter(e -> e.getDay() == finalI + 1 - finalNewestSimulation1
.getNumber_Of_Days_To_Recovery()))
.collect(Collectors.toList()).get((int) (simulationsValuesRepository.findAll()
.stream().filter(e -> e.getDay() == finalI + 1 - finalNewestSimulation1
.getNumber_Of_Days_To_Recovery())).count() - 1)
.getNumber_Of_Infected())// Z24
.dead((newestSimulation.getMortality_Rate() * (double) ((simulationsValuesRepository.findAll()
.stream().filter(e -> e.getDay() == finalI + 1 - finalNewestSimulation1
.getNumber_Of_Days_To_Death()))
.collect(Collectors.toList()).get((int) (simulationsValuesRepository.findAll().stream()
.filter(e -> e.getDay() == (finalI + 1 - finalNewestSimulation1
.getNumber_Of_Days_To_Death()))).count()1).getNumber_Of_Infected()))
- newestSimulationsVal.getDead())//V24
.build();
var simId = simulationsValuesRepository.save(simulation_values);
simId.setSimulation(newestSimulation);//dodane
var simVal2 = newestSimulation.getSimulationsValues();
simVal2.add(simId);
newestSimulation.setSimulationsValues(simVal2);
simulationRepository.save(newestSimulation);
} else if (i == 2) {
sim = getSimulations();
newestSimulation = simulationRepository.getById(sim.get(sim.size() - 1).getId());
simVal = getSimulationsValues();
newestSimulationsVal = simulationsValuesRepository
.getById(simVal.get(simVal.size() - 1).getId());
SimulationsValues simulation_values;
simulation_values = SimulationsValues.builder()
.day(i)
.healthy_Prone_To_Infection(newestSimulationsVal.getHealthy_Prone_To_Infection() -
((newestSimulation.getHow_Many_One_Infects())
* newestSimulationsVal.getNumber_Of_Infected()))
.number_Of_Infected((newestSimulation.getHow_Many_One_Infects())
* newestSimulationsVal.getNumber_Of_Infected()
+ newestSimulationsVal.getNumber_Of_Infected())
.regained_Health_And_Immunity(0d)
.dead(0d)
.build();
var simId2 = simulationsValuesRepository.save(simulation_values);
simId2.setSimulation(newestSimulation);//dodane
var simVal2 = newestSimulation.getSimulationsValues();
simVal2.add(simId2);
newestSimulation.setSimulationsValues(simVal2);
simulationRepository.save(newestSimulation);
} else {
sim = getSimulations();
newestSimulation = simulationRepository.getById(sim.get(sim.size() - 1).getId());
simVal = getSimulationsValues();
newestSimulationsVal = simulationsValuesRepository
.getById(simVal.get(simVal.size() - 1).getId());
SimulationsValues simulation_values;
simulation_values = SimulationsValues.builder()
.day(i)
.healthy_Prone_To_Infection(newestSimulationsVal.getHealthy_Prone_To_Infection() -
((newestSimulation.getHow_Many_One_Infects())
* newestSimulationsVal.getNumber_Of_Infected()))
.number_Of_Infected((newestSimulation.getHow_Many_One_Infects())
* newestSimulationsVal.getNumber_Of_Infected()
+ newestSimulationsVal.getNumber_Of_Infected())
.regained_Health_And_Immunity(0d)
.dead(0d)
.build();
var simId2 = simulationsValuesRepository.save(simulation_values);
simId2.setSimulation(newestSimulation);//dodane
var simVal2 = newestSimulation.getSimulationsValues();
simVal2.add(simId2);
newestSimulation.setSimulationsValues(simVal2);
simulationRepository.save(newestSimulation);
}
}
}
}
ViewModel:
package Simulations.ViewModels;
import Simulations.Annotations.GreaterThan;
import Simulations.Entity.SimulationsValues;
import lombok.*;
import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
#Builder
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#GreaterThan(message = "field number of days to death can not be equal or bigger than field days to recovery")
public class SimulationViewModel {
private Long id;
#NotEmpty(message = "field can not be empty")
private String simulation_Name;
#NotNull(message = "field can not be empty")
#DecimalMax("10000000000.0")
#DecimalMin("0.0")
private Double population_Size;
private Double initial_Infected_Number;
#NotNull(message = "field can not be empty")
private Double how_Many_One_Infects;
#NotNull(message = "field can not be empty")
#DecimalMax("1.0")
#DecimalMin("0.001")
private Double mortality_Rate;
private #NotNull(message = "field can not be empty") #DecimalMin("1.0")
Double number_Of_Days_To_Recovery;
private #NotNull(message = "field can not be empty") #DecimalMin("1.0")
Double number_Of_Days_To_Death;
private #NotNull(message = "field can not be empty")
Double simulation_Time;
List<SimulationsValues> simulationsValues = new ArrayList<>();
}
Hi, I have a roblem. When I create a simulationValues object (using builder) it's fields have double values as intended but when I save this object to database and look at thoese values in database (MySql) thoese values are presented as Integers i.e. without values after comma, for example when I debug my code I see that "dead" field has in 12 iteration value 0.9 but it is saved to database as 1. Why is that? I don;t do any casting and all I use for this calculations are doubles as well as all fields n SimulationValues class and SimulationViewModel are doubles. Why when saving field changes types?Thanks in advance
All columns in MySql were bigint type instead of double as I made them in coresponding entity, changed them to BigDecimal and everything works fine.

Hamcrest - Matchers.hasProperty: how to check if a List of objects contains an object with a concrete value

I have the following problem with Hamcrest:
I have a List of Employee
List<Employee> employees = hamcrest.getEmployees();
where:
public class Employee {
private String name;
private int age;
private double salary;
public Employee(String name, int age, double salary) {
super();
this.name = name;
this.age = age;
this.salary = salary;
}
and:
public List<Employee> getEmployees() {
Employee e1 = new Employee("Adam", 39, 18000);
Employee e2 = new Employee("Jola", 26, 8000);
Employee e3 = new Employee("Kamil", 64, 7700);
Employee e4 = new Employee("Mateusz", 27, 37000);
Employee e5 = new Employee("Joanna", 31, 12700);
Employee e6 = null;
return Arrays.asList(e1, e2, e3, e4, e5, e6);
}
I'd like to check if there is an object with name = Mateusz in my list.
I've tried in such a way, but something get wrong:
#Test
public void testListOfObjectsContains() {
List<Employee> employees = hamcrest.getEmployees();
assertThat(employees, Matchers.anyOf(Matchers.containsInAnyOrder(Matchers.hasProperty("name", is("Mateusz")), Matchers.hasProperty("age", is(27)))));
}
How can I check this using Hamcrest?
I've spent over 2 hours to find the solution in Internet but unfortunately without success.
Thank you very much in advance!
You need the matcher hasItem
assertThat(
x,
hasItem(allOf(
Matchers.<Employee>hasProperty("name", is("Mateusz")),
Matchers.<Employee>hasProperty("age", is(27))
))
);
You can also use hasItems, contains or containsInAnyOrder :
assertThat(
x,
hasItems( // or contains or containsInAnyOrder
Matchers.<Employee>hasProperty("name", is("Mateusz")),
Matchers.<Employee>hasProperty("age", is(27))
)
);

Spring boot - MySQL - MySQLSyntaxErrorException: Unknown column 'product0_.product_id' in 'field list'

After going through several threads similar to my problem with unsuccessful result, I am posting this. I get the error as in the heading. Below is my model file Product
Product.java
package com.ms.Products;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "product")
public class Product {
#Id
#Column(name = "ProductId")
private String ProductId = null;
#Column(name = "ProductName")
private String ProductName = null;
#Column(name = "ProductCategory")
private String ProductCategory = null;
#Column(name = "Price")
private double Price = 0;
#Column(name = "Quantity")
private int Quantity = 0;
public Product() {
}
public Product(String productId, String productName, String prodcutCategory, double princeInEuros,
int quantityAvailable) {
this.ProductId = productId;
this.ProductName = productName;
this.ProductCategory = prodcutCategory;
this.Price = princeInEuros;
this.Quantity = quantityAvailable;
}
public String getProductId() {
return ProductId;
}
public void setProductId(String productId) {
this.ProductId = productId;
}
public String getProductName() {
return ProductName;
}
public void setProductName(String productName) {
this.ProductName = productName;
}
public String getProdcutCategory() {
return ProductCategory;
}
public void setProdcutCategory(String prodcutCategory) {
this.ProductCategory = prodcutCategory;
}
public double getPrinceInEuros() {
return Price;
}
public void setPrinceInEuros(double princeInEuros) {
this.Price = princeInEuros;
}
public int getQuantityAvailable() {
return Quantity;
}
public void setQuantityAvailable(int quantityAvailable) {
this.Quantity = quantityAvailable;
}
}
Database schema
mysql> SHOW TABLES;
+--------------------+
| Tables_in_products |
+--------------------+
| category |
| product |
| users |
+--------------------
+
My product table
mysql> select * from product;
+-----------+-------------+-----------------+-------+----------+
| ProductId | ProductName | ProductCategory | Price | Quantity |
+-----------+-------------+-----------------+-------+----------+
| 1 | Cheese | L | 1.65 | 25 |
| 2 | Milk | L | 0.5 | 55 |
+-----------+-------------+-----------------+-------+----------+
2 rows in set (0.00 sec)
my application.properties
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp
spring.datasource.url=jdbc:mysql://localhost/Products
spring.datasource.username=root
spring.datasource.password=sj
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
Please any help me with an idea on what am i missing here or what i need to do here?
I get this error while trying to add or view. M controller code
PRoductController.java
#Autowired
private ProductService productService;
#RequestMapping("/allProducts")
public List<Product> getAllProducts(){
return productService.getAllProducts();
}
#RequestMapping("/addProduct")
public String addProduct(Product productFromView) {
Product product = new Product();
product.setProductId("3");
product.setProductName("Salt");
product.setProdcutCategory("L");
product.setPrinceInEuros(0.65);
product.setQuantityAvailable(20);
productService.addProduct(product);
return "Product Added";
}
ProductService.java
public List<Product> getAllProducts(){
List<Product> products = new ArrayList<Product>();
productDao.findAll().forEach(products::add);
return products;
}
public void addProduct(Product product) {
productDao.save(product);
}

Linq + nested GroupBy

We are using mySQL with WCF Restful service, we want to fetch our database content PACKAGEID wise...as mentioned below:
PackageId=2
{
StartRange = 1;
EndRange = 100;
IsDiscountAndChargeInPer = 1;
Discount =10;
ServiceCharge = 20;![enter image description here][1]
},
{
StartRange =101;
EndRange = 500;
IsDiscountAndChargeInPer = 1;
Discount =10;
ServiceCharge = 20;
}
PackageId=3
{
StartRange = 1;
EndRange = 100;
IsDiscountAndChargeInPer = 1;
Discount =10;
ServiceCharge = 20;
}
We have created a Result class to return result from out wcf service...for above service we have result class defined as below
[DataContract]
public class PackagePointRangeConfigurationResult : ResultBase
{
[DataMember]
public List<PackagePointRangeResult> Result;
}
public class PackagePointRangeResult
{
public int PackageId { get; set; }
public List<PointPlanInfo> Result { get; set; }
}
For fetching record we use following linq query:
var result = (from planinfo in db.mst_pointplan_info
join entityType in db.mst_entity_type
on planinfo.entityId equals entityType.id
where planinfo.entityId == entityId
&& planinfo.is_deleted != true
&& planinfo.system_id == systemId
&& entityType.enity_enum_id == entityId
group planinfo by planinfo.package_id into gplan
select new PackagePointRangeConfigurationResult
{
Result = (from planinfo in gplan
select new PackagePointRangeResult
{
PackageId = planinfo.package_id,
PointPlanInfo = (from pointPlanInfo in gplan
select new PointPlanInfo
{
StartRange = planinfo.start_range,
EndRange = planinfo.end_range,
IsDiscountAndChargeInPer = planinfo.is_discount_and_charge_in_per,
Discount = planinfo.discount,
ServiceCharge = planinfo.servicecharge,
AtonMerchantShare =planinfo.aton_merchant_share,
CommunityShare = planinfo.community_share
}).ToList()
}).ToList()
}).FirstOrDefault();
But it gives me below error:
LINQ to Entities does not recognize the method 'System.Collections.Generic.List1[PointPlanInfo] ToList[PointPlanInfo](System.Collections.Generic.IEnumerable1[PointPlanInfo])' method, and this method cannot be translated into a store expression.

Populate Datagridview from DB VB.NET

I have my mysql query selected fields (item_code, item_name, item quantity, item_selltype, item_selldetail) but some of these fields are variants.
Dim sqlConn As String = ("SELECT item_code, item_name, item_quantity, item_selltype, item_selldetail FROM qa_items")
Dim objDataAdapter As New MySqlDataAdapter(sqlConn, objConn)
I suppose that the query returns:
item_code, item_name, item_quantity, item_selltype, item_selldetail
01 Ball 5 unit 10.52
02 Keyoard 10 unit 50.00
03 Gasoline 5 gallon 70.45
DataGridView control looks so:
Code, Name, Inv, Unit Price, Box Price, Pound Price, Gallon Price
then I need this result in datagridview:
Code, Name, Inv, Unit Price, Box Price, Pound Price, Gallon Price
01 Ball 5 10.52 0 0 0
02 Keyboard 10 50.00 0 0 0
03 Gasoline 5 0 0 0 70.45
I searched in many ways some code that can do this but I can not succeed, help..
I think you need a translator object. Get your data from the database, and use it to populate a List<> of something like this:
class Item
{
public int Code { get; private set; }
public string Name { get; private set; }
public int Inv { get; private set; }
[DisplayName("Unit Price")]
public double UnitPrice { get; private set; }
[DisplayName("Box Price")]
public double BoxPrice { get; private set; }
[DisplayName("Pound Price")]
public double PoundPrice { get; private set; }
[DisplayName("Gallon Price")]
public double GallonPrice { get; private set; }
public Item(int item_code, string item_name, int item_quantity, string item_selltype, double item_selldetail)
{
Code = item_code;
Name = item_name;
Inv = item_quantity;
UnitPrice = 0;
BoxPrice = 0;
PoundPrice = 0;
GallonPrice = 0;
switch (item_selltype)
{
case "unit": UnitPrice = item_selldetail; break;
case "box": BoxPrice = item_selldetail; break;
case "pound": PoundPrice = item_selldetail; break;
case "gallon": GallonPrice = item_selldetail; break;
default: throw new InvalidExpressionException();
}
}
}
Then set the DataSource of the grid to that List<Item>.