Implement Subtotal feature of Excel - java

Excel provides the Subtotal option from the Menu Data -> Outline -> Subtotal. It creates automatically the sub-sums and the possibility to fold the data. The image below demonstrates how the action transforms the sheet.
And this is exactly what I need to do via POI. I know how to set a subtotal function into a cell so I could calculate the intermediate sums by myself. But how do I enable this folding on the left border?
I realised there is the groupRow() method but those nested groups doesn't work like they should. If I use the following code I only get two groups. One large (1-7) and (1-3). The group (5-7) is missing and changing the order of the calls has no effect.
sheet.groupRow(1, 7);
sheet.groupRow(1, 3);
sheet.groupRow(5, 7);

I use a quite old verion of POI but this is how I did it:
I also needed multiple nested groups so I had a model for the rows where the indent level was stored as well (it was a tree so the indent was implicit). I traversed the model with a visitor to get the group start and end row numbers. Then called HSSFSheet.groupRow subsequently for each group. If I remember correctly, the order of the group calls is important.

I think this is exactly what you are looking for:
http://www.mysamplecode.com/2011/10/apache-poi-excel-row-group-collapse.html
if you use subtotal(9,<range>) instead of sum(<range>), you can perform nested groups as subtotal ignores cell with subtotal in its range

With following library you can to calculate the subtotals that you want
<dependency>
<groupId>com.github.bld-commons.excel</groupId>
<artifactId>generator-excel</artifactId>
<version>3.1.1</version>
</dependency>
This library is wrapper of apache poi.
Below the source code:
You create a class that represents the row of the table.
package bld.generator.report.junit.entity;
import org.apache.poi.ss.usermodel.DataConsolidateFunction;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import bld.generator.report.excel.RowSheet;
import bld.generator.report.excel.annotation.ExcelCellLayout;
import bld.generator.report.excel.annotation.ExcelColumn;
import bld.generator.report.excel.annotation.ExcelFont;
import bld.generator.report.excel.annotation.ExcelSubtotal;
import bld.generator.report.excel.annotation.ExcelSubtotals;
#ExcelSubtotals(labelTotalGroup = "Total",endLabel = "total")
public class SalaryRow implements RowSheet {
#ExcelColumn(columnName = "Name", indexColumn = 0)
#ExcelCellLayout
private String name;
#ExcelColumn(columnName = "Amount", indexColumn = 1)
#ExcelCellLayout(horizontalAlignment = HorizontalAlignment.RIGHT)
#ExcelSubtotal(dataConsolidateFunction = DataConsolidateFunction.SUM,excelCellLayout = #ExcelCellLayout(horizontalAlignment = HorizontalAlignment.RIGHT,font=#ExcelFont(bold = true)))
private Double amount;
public SalaryRow() {
super();
}
public SalaryRow(String name, Double amount) {
super();
this.name = name;
this.amount = amount;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getAmount() {
return amount;
}
public void setAmount(Double amount) {
this.amount = amount;
}
}
You create a class that represents the sheet.
package bld.generator.report.junit.entity;
import javax.validation.constraints.Size;
import bld.generator.report.excel.SheetData;
import bld.generator.report.excel.annotation.ExcelHeaderLayout;
import bld.generator.report.excel.annotation.ExcelMarginSheet;
import bld.generator.report.excel.annotation.ExcelSheetLayout;
#ExcelSheetLayout
#ExcelHeaderLayout
#ExcelMarginSheet(bottom = 1.5,left = 1.5,right = 1.5,top = 1.5)
public class SalarySheet extends SheetData<SalaryRow> {
public SalarySheet(#Size(max = 31) String sheetName) {
super(sheetName);
}
}
Class test
package bld.generator.report.junit;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import bld.generator.report.excel.BaseSheet;
import bld.generator.report.excel.GenerateExcel;
import bld.generator.report.excel.data.ReportExcel;
import bld.generator.report.junit.entity.SalaryRow;
import bld.generator.report.junit.entity.SalarySheet;
import bld.generator.report.utils.ExcelUtils;
#RunWith(SpringRunner.class)
#SpringBootTest
#ConfigurationProperties
#ComponentScan(basePackages = {"bld.generator","bld.read"})
#EnableTransactionManagement
public class SalaryTest {
private static final String PATH_FILE = "/mnt/report/";
#Autowired
private GenerateExcel generateExcel;
/**
* Sets the up.
*
* #throws Exception the exception
*/
#Before
public void setUp() throws Exception {
}
#Test
public void testSalary() throws Exception {
List<BaseSheet> listBaseSheet = new ArrayList<>();
SalarySheet salarySheet=new SalarySheet("salary");
salarySheet.getListRowSheet().add(new SalaryRow("a",2.0));
salarySheet.getListRowSheet().add(new SalaryRow("a",2.0));
salarySheet.getListRowSheet().add(new SalaryRow("a",2.0));
salarySheet.getListRowSheet().add(new SalaryRow("a",2.0));
salarySheet.getListRowSheet().add(new SalaryRow("c",1.0));
salarySheet.getListRowSheet().add(new SalaryRow("c",1.0));
salarySheet.getListRowSheet().add(new SalaryRow("c",1.0));
salarySheet.getListRowSheet().add(new SalaryRow("c",1.0));
listBaseSheet.add(salarySheet);
ReportExcel report=new ReportExcel("test", listBaseSheet);
byte[] byteReport = this.generateExcel.createFileXlsx(report);
ExcelUtils.writeToFile(PATH_FILE,report.getTitle(), ".xlsx", byteReport);
}
}
Below the link of the project on github:
https://github.com/bld-commons/dev-excel
Below the result.
enter image description here

Related

Performance issue in Spring Boot Java app with SQL Server

I am facing performance issues with a Spring Boot Java App which gets data from a SQL Server database. A simple query like:
SELECT a, b, SUM(c)
FROM table
WHERE date = '2023-02-01' AND year = 2023
GROUP BY a, b
is executed. The result of the query is 12 rows. When I execute this query in SSMS, the result is there immediately. If the query gets executed via the Spring Boot app in a browser window or with Postman, it takes randomly 3.5 to 10 seconds to get the result.
The table contains roughly 8 million rows and 14 columns:
1 PK INT column
1 DATE column
2 DECIMAL(12,2)
10 NVARCHAR(x)
The query in the Spring Boot app is written in Native SQL annotated with #Query. All my colleagues use ASP.NET as back-end, and they are taking the same SQL Server. Their performance is great. It looks like there are configuration issues.
What I have tried so far:
I added sendParametersAsUnicode=false to application.properties
I copied the entire table: instead of NVARCHAR(x) I took VARCHAR(x) for all string-related columns.
I tracked the execution time with Postman: >99% of execution time falls in the category transfer time.
I tried to annotate NVARCHAR(x) columns to annotate with #Nationalized
I read about this: https://vladmihalcea.com/sql-server-jdbc-sendstringparametersasunicode/ to understand the difference between NVARCHAR(x) and VARCHAR(x) in terms of Spring Boot and SQL Server.
Any ideas what might be the game changer to decrease execution time from multiple seconds to far less than a second?
Here is more code of my project:
application.properties:
spring.datasource.url=jdbc:sqlserver://10.191.144.180:1433;database=Spring;encrypt=true;trustServerCertificate=true;sendStringParametersAsUnicode=false
spring.datasource.username=username
spring.datasource.password=pw123456
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.show-sql=true
spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
spring.jpa.open-in-view=false
Table Class:
#Entity
#Table(name="Fact_Snapshots_Agg")
public class FSAGG {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Long id;
Date filedate;
String jahr;
String a;
String b;
String d;
String e;
String f;
String g;
String h;
float c;
float i;
String j;
String k;
}
plus constructors and getters and setters
Resource File:
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.analytics_test.model.FSAGGTInterface;
import com.analytics_test.service.FSAGGService;
#RestController
#CrossOrigin
#RequestMapping("/FSAGG")
public class FSAGGResource {
private final FSAGGService fsaggService;
#Autowired
public FSAGGResource(FSAGGService fsaggService) { this.fsaggService = fsaggService; }
#GetMapping("/Actuals/Total/{jahr}/gesamt")
public List<FSAGGTInterface> getActualsTotalGesamt(#PathVariable("jahr") String jahr) { return fsaggService.getActualsTotalGesamt(jahr); }
}
Repository File:
package com.analytics_test.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.analytics_test.model.FSAGG;
import com.analytics_test.model.FSAGGTInterface;
public interface FSAGGRepository extends JpaRepository<FSAGG, Long> {
#Query(value = "a as a, b as b, SELECT SUM(c) as c "
+ "FROM FSAGG WHERE filedate = '2023-02-01' AND year = :year "
+ "GROUP BY a, b"
)
List<FSAGGTInterface> getActualsTotalGesamt(#Param("year") String year);
}
Service Class:
package com.analytics_test.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import com.analytics_test.model.FSAGGTInterface;
import com.analytics_test.repository.FSAGGRepository;
#Component
#Service
public class FSAGGService {
private final FSAGGRepository fsaggRepository;
#Autowired
public FSAGGService(FSAGGRepository fsaggRepository) { this.fsaggRepository = fsaggRepository; }
public List<FSAGGTInterface> getStuff() { return fsaggRepository.getStuff(); }
public List<FSAGGTInterface> getActualsTotalGesamt(String jahr) { return fsaggRepository.getActualsTotalGesamt(jahr); }
}
Rewrite the service method getActualsTotalGesamt to confirm that the slow query is the issue rather than something else in spring boot.
public List<FSAGGTInterface> getActualsTotalGesamt(String jahr) {
Date start = new Date();
List<FSAGGTInterface> retVal = fsaggRepository.getActualsTotalGesamt(jahr);
System.out.println(“repo call duration ms: “ + ((new Date()).getTime() - start.getTime()));
return retVal;
}

Quarkus - How to test reactive flow for onFailure()

I have reactive quarkus resource where I am using Mongo Reactive Panache. I have a logic that if the emailId of person exist then code should throw BusinessException.
I am able to test the happy path but how do I trigger negative test. Here's my code and test class.
PersonResource.java
#POST
public Uni<Response> create(Person person){
return repository.persist(person). map(r ->
Response.ok(r).build())
.onFailure()
.recoverWithItem(f-> {
AStatus status = createErrorStatus(f.getMessage());
return Response.serverError().entity(status).build();
}) ;
}
PersonRepositoryTest.java
package com.eventu.resource;
import com.eventu.exception.BusinessException;
import com.eventu.repository.PersonRepository;
import com.eventu.vo.Address;
import com.eventu.vo.Person;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.mockito.InjectMock;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.helpers.test.UniAssertSubscriber;
import org.bson.types.ObjectId;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import javax.inject.Inject;
import javax.ws.rs.core.Response;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
#QuarkusTest
class PersonResourceTest {
#InjectMock
PersonRepository repository;
#Inject
PersonResource resource;
Uni<Person> uniPerson;
Person person;
#BeforeEach
public void setUp(){
person = Person.builder().address(Address.builder()
.addressLine_1("1000 Test dr")
.addressLine_2("opposite crescent dr").suiteNumber("Ste. 200").city("testCity")
.countryCode("US").state("CA")
.build()).emailAddress("test#test.com").firstName("John").lastName("Barista")
.mobileNumber("70444444444")
.id(new ObjectId())
.build();
uniPerson = Uni.createFrom().item(person);
when(repository.persist(any(Person.class))).thenReturn(uniPerson);
}
// THIS TEST IS WORKING
#Test
#DisplayName("When a new person object is passed then person object with Id should be returned")
void create_success() {
final Uni<Response> p = resource.create(person);
Person respPerson = (Person) p.subscribe().withSubscriber(UniAssertSubscriber.create()).assertCompleted().getItem().getEntity();
Assertions.assertNotNull(p);
Assertions.assertEquals(person, respPerson);
}
/**
* THIS ONE FAILS WITH at line 63 with the message
* org.mockito.exceptions.base.MockitoException:
* Checked exception is invalid for this method!
* Invalid: com.eventu.exception.BusinessException
*/
#Test
#DisplayName("When a new person object is passed but email exists then AStatus object with error description")
void create_duplicate_emailId() {
when(repository.persist(any(Person.class))).thenThrow(BusinessException.class); /// **FAILS HERE. Tried replacing with RunTimeException.class as well**
final Uni<Response> p = resource.create(person);
Person respPerson = (Person) p.subscribe().withSubscriber(UniAssertSubscriber.create()).assertCompleted().getItem().getEntity();
//**SHOULD FAIL HERE as I EXPECT AStatus.java object**
Assertions.assertEquals(person, respPerson);
}
}
I found the solution after trying an error. The documentation on Mutiny/Quarkus leaves a lot to be desired.
This is what's needed -
#Test
#DisplayName("When a new person object is passed but email exists then AStatus object with error description")
void create_duplicate_emailId() {
when(repository.persist(any(Person.class)))
.thenReturn(Uni.createFrom().failure(new MongoException(11000, "Email does not exist")));
final Uni<Response> p = resource.create(person);
Person respPerson = (Person) p.subscribe().withSubscriber(UniAssertSubscriber.create()).assertCompleted().getItem().getEntity();
.....
}

Does findById() actually load data from a JPA repository?

I am a Hibernate beginner. I did a couple of simple tutorials and am trying to write a simple shop backend. Everything works as it should, but I am seeing strange things in my unit tests. When I save an entity, then retrieve it using findById(), it seems that I am simply getting the same object I called save() on, without even retrieving actual values from the database:
package com.bo.learnjava.shop1.repository;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "PRODUCTS")
public class Product {
#Id
#GeneratedValue
#Column(name="ID")
long id;
#Column(name="NAME")
String name = "";
#Column(name="PRICE_CENTS")
int priceCents = 0;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPriceCents() {
return priceCents;
}
public void setPriceCents(int priceCents) {
this.priceCents = priceCents;
}
public long getId() {
return id;
}
}
package com.bo.learnjava.shop1.repository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface ProductRepository extends PagingAndSortingRepository<Product,Long> {
}
package com.bo.learnjava.shop1.repository;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
#DataJpaTest
public class ProductRepositoryTest {
#Autowired
ProductRepository repo;
#Test
void testProductRepository() {
Product p=new Product();
p.setName("Milk");
p.setPriceCents(134);
repo.save(p);
// Modify the value to check that repo.findById() actually retrieves *saved* data
p.setPriceCents(9999);
Optional<Product> productFromRepo=repo.findById(p.getId());**
// I expect productFromRepo to contain the values I called save() with
// (price == 134). But productFromRepo.get() returns exactly the same Java object
// as p (with price == 9999), so no actual data was retrieved from the database - why?
assertTrue(productFromRepo.isPresent());
System.out.println("productFromRepo.priceCents="+productFromRepo.get().getPriceCents()); // Outputs 9999!
assertEquals(134,productFromRepo.get().getPriceCents()); // THIS FAILS!!!
}
}
Why does Hibernate behave like that, and how do I test that stuff I write to the database via Hibernate actually gets retrieved back from the database?
Additionaly to comment about first level cache.
If you are extending JpaRepository you can use
repo.saveAndFlush(p);
or
repo.save(p); repo.flush();
to immediately save data in DB.
After it - repo.findById(p.getId()); will return updated data.

[Spark Dataset]: CreateDataset API fails with Java object containing Abstract Class

I am trying to convert JavaRDD to Dataset using createDataFrame(RDD<T> data, Encoder<T> evidence) function, but I am getting the following error. I have used a subset of my use case.
My Usecase:
I am trying to convert a JavaRDD with a complex nested object(with abstract classes) to Dataset So that I can write the data in ORC/Parquet format(JavaRDD doesn't support ORC/Parquet)
The input data is in Avro format, there is an infinite recursion problem in createDataFrame for Avro types, referring to this https://issues.apache.org/jira/browse/SPARK-25789, that's why I am loading the data in JavaRDD first.
Requirements:
Encoders.kryo(), Encoders.javaSerialization() works here but i want to use Encoders.bean()
Encoders.bean(T) leverages the structure of an object, to provide class-specific storage layout, as I am using parquet(columnar storage) format for storage, each class variable can be stored in a different column using Encoders.bean(T), whereas
Encoders.Kryo(T) and EncodersjavaSerialization(T), these encoder maps T into a single byte array (binary) field. and thus store the object into one single column.
If a custom serializer is required then please elaborate on the solution.
Classes Used:
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Map;
#AllArgsConstructor
#NoArgsConstructor
#lombok.Data
public class Data implements Serializable {
private String id;
private Map<Type, Aclass> data;
}
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
#AllArgsConstructor
#NoArgsConstructor
#Data
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "uad")
#JsonSubTypes(value = {#JsonSubTypes.Type(name = "UADAffinity", value = Bclass.class)})
public abstract class Aclass implements Serializable {
String t;
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
#AllArgsConstructor
#NoArgsConstructor
#Data
public class Bclass extends Aclass {
private Map<String, String> data;
public Bclass(String t, Map<String, String> data) {
super(t);
this.data = data;
}
}
public enum Type {
A, B;
}
Logic:
import com.flipkart.ads.neo.schema.Type;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xyz.schema.Aclass;
import com.xyz.schema.Bclass;
import com.xyz.schema.Data;
import org.apache.spark.SparkConf;
import org.apache.spark.SparkContext;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Encoders;
import org.apache.spark.sql.SparkSession;
import java.util.List;
import java.util.Map;
public class DataSetConverter {
private SparkSession session;
public DataSetConverter() {
session = initSpark();
}
SparkSession initSpark() {
SparkConf conf = new SparkConf().setMaster("local[*]").setAppName("123");
return SparkSession.builder()
.sparkContext(new SparkContext(conf))
.getOrCreate();
}
public void dataset_test() {
List<Data> dataList = prepareData();
JavaSparkContext jsc = new JavaSparkContext(session.sparkContext());
JavaRDD<Data> rowsrdd = jsc.parallelize(dataList);
Dataset<Data> rows = session.createDataset(rowsrdd.rdd(), Encoders.bean(Data.class));
System.out.println(rows.takeAsList(3));
}
public static void main(String[] args) {
new DataSetConverter().dataset_test();
}
private List<Data> prepareData() {
List<Data> dataList = Lists.newArrayList();
Data sample1 = getData();
Data sample2 = getData();
dataList.add(sample1);
dataList.add(sample2);
return dataList;
}
private Data getData() {
Map<Type, Aclass> data = getUadData("ppv");
return new Data("123", data);
}
private Map<Type, Aclass> getUadData(String id) {
Map<Type, Aclass> result = Maps.newHashMap();
Map<String, String> data = Maps.newHashMap();
data.put(id + "11", "11");
result.put(Type.A, new Bclass("123", data));
return result;
}
}
Error:
org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 150, Column 11: Cannot instantiate abstract "com.xyz.schema.Aclass"
at org.codehaus.janino.UnitCompiler.compileError(UnitCompiler.java:12124)
at org.codehaus.janino.UnitCompiler.compileGet2(UnitCompiler.java:5260)
at org.codehaus.janino.UnitCompiler.access$9800(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$16.visitNewClassInstance(UnitCompiler.java:4433)
at org.codehaus.janino.UnitCompiler$16.visitNewClassInstance(UnitCompiler.java:4394)
at org.codehaus.janino.Java$NewClassInstance.accept(Java.java:5179)
at org.codehaus.janino.UnitCompiler.compileGet(UnitCompiler.java:4394)
at org.codehaus.janino.UnitCompiler.compileGetValue(UnitCompiler.java:5575)
at org.codehaus.janino.UnitCompiler.compileGet2(UnitCompiler.java:4703)
at org.codehaus.janino.UnitCompiler.access$8800(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$16.visitConditionalExpression(UnitCompiler.java:4418)
at org.codehaus.janino.UnitCompiler$16.visitConditionalExpression(UnitCompiler.java:4394)
at org.codehaus.janino.Java$ConditionalExpression.accept(Java.java:4504)
at org.codehaus.janino.UnitCompiler.compileGet(UnitCompiler.java:4394)
at org.codehaus.janino.UnitCompiler.compileGetValue(UnitCompiler.java:5575)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:2580)
at org.codehaus.janino.UnitCompiler.access$2700(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$6.visitLocalVariableDeclarationStatement(UnitCompiler.java:1503)
at org.codehaus.janino.UnitCompiler$6.visitLocalVariableDeclarationStatement(UnitCompiler.java:1487)
at org.codehaus.janino.Java$LocalVariableDeclarationStatement.accept(Java.java:3511)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1487)
at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1567)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:3388)
at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1357)
at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1330)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:822)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:981)
at org.codehaus.janino.UnitCompiler.access$700(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$2.visitMemberClassDeclaration(UnitCompiler.java:414)
at org.codehaus.janino.UnitCompiler$2.visitMemberClassDeclaration(UnitCompiler.java:406)
at org.codehaus.janino.Java$MemberClassDeclaration.accept(Java.java:1295)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:406)
at org.codehaus.janino.UnitCompiler.compileDeclaredMemberTypes(UnitCompiler.java:1306)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:848)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:432)
Please Help!!

JPA and Java SE - Table not created for Entity class, due to additional convenience methods

I am currently writing a Netbeans platform application for persistence I use JPA 2.1 and eclipse link as provider. I have the following entity class:
import java.util.UUID;
import javafx.beans.property.SimpleStringProperty;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Transient;
/**
*
* #author forell
*/
#Entity
#Access(AccessType.FIELD)
public class MaterialAbc {
#Id
private String id;
//... several additional fields, that all work fine
private String substanceInstances = "";
public MaterialAbc(){
id = UUID.randomUUID().toString();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
//.. getters and setters for the omitted fields
public String getSubstanceInstances() {
return substanceInstances;
}
public void setSubstanceInstances(String substanceInstances) {
this.substanceInstances = substanceInstances;
}
/* IF I UNCOMMENT THESE LINES THE DATATABLE IS NOT CREATED ANYMORE
IS THERE A WAY TO SOLVE THIS?
public List<SubstanceInstance2> getSubs() {
List<SubstanceInstance2> subs = new ArrayList<>();
if (!"".equals(substanceInstances)){
List<String> values = Arrays.asList(substanceInstances.split("|"));
values.forEach(value->{
subs.add(SubstanceInstance2.unSerialize(value));
});
}
return subs;
}
public void setSubs(List<SubstanceInstance2> subs) {
substanceInstances = "";
subs.forEach(sub->{
substanceInstances =substanceInstances + sub.serialize() + "|";
});
substanceInstances = substanceInstances.substring(0, substanceInstances.length()-1);
}
*/
As is the class works fine, as soon as I uncomment the two methods at the bottom that "unserialize" an object that is nested in the string substanceInstances, eclipselink is not creating the datatables anymore. Is there a way to solve this, or do need to add an extra layer.
In the meantime I actually found a solution to the problem. It seems eclipselink does not convert the Entity-bean into a table, if there are lambda expressions used in the methods. In the end I converted
values.forEach(value->{
subs.add(SubstanceInstance2.unSerialize(value));
});
into
for (String value:values){
subs.add(SubstanceInstance2.unSerialize(value));
}
And everthing works nicely. As to the reason why, no idea!

Categories

Resources