I'm trying to use JPA for the first time in a project. Most of my entities are working fine, but I am having trouble with one which is part of a Joined Inheritance Strategy.The entities are also being serialised by Jackson so they also have Json annotations.
The parent "User" class:
(Edit: added "Type" field)
#JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include= JsonTypeInfo.As.WRAPPER_OBJECT)
#JsonTypeName("user")
#JsonSubTypes({
#JsonSubTypes.Type(name="customer", value=Customer.class),
#JsonSubTypes.Type(name="employee", value=Employee.class)})
#Entity(name = "User")
#Table(name="user")
#Inheritance(strategy = InheritanceType.JOINED)
#DiscriminatorColumn(name="type",discriminatorType = DiscriminatorType.INTEGER)
#NamedQuery(name="User.all",query = "select u from User u")
public abstract class User {
#Id
private String username;
#Column(name = "type",nullable = false)
private int type;
public User(){
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public abstract Set<Order> getOrders();
}
A Child "Employee"
#JsonTypeName("employee")
#Entity(name="Employee")
#Table(name="employee")
#PrimaryKeyJoinColumn(name = "username",referencedColumnName = "username")
#DiscriminatorValue("1")
#NamedQuery(name = "Employee.all",query = "select e from Employee e")
public class Employee extends User implements Serializable{
private String username;
private String firstName;
private String lastName;
private String email;
#Convert(converter = LocalDatePersistenceConverter.class)
private LocalDate dateStarted;
#Convert(converter = LocalDatePersistenceConverter.class)
private LocalDate dateEnded;
#OneToMany(mappedBy = "employee",targetEntity = Order.class,fetch = FetchType.EAGER,cascade = CascadeType.PERSIST)
#JsonIgnore
private Set<Order> orders = new HashSet<>();
public Employee() {
}
#Override
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
public void addOrder(Order order){
orders.add(order);
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setEmail(String email) {
this.email = email;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getEmail() {
return email;
}
public String getDateStarted() {
if(dateStarted != null)
return dateStarted.toString();
else return null;
}
public void setDateStarted(LocalDate dateStarted) {
this.dateStarted = dateStarted;
}
public String getDateEnded() {
if(dateEnded != null)
return dateEnded.toString();
else return null;
}
public void setDateEnded(LocalDate dateEnded) {
this.dateEnded = dateEnded;
}
#Override
public String toString(){
return getUsername();
}
}
And a child "Customer":
(Edit: removed #Id field)
#JsonTypeName("customer")
#Entity(name="Customer")
#Table(name="customer")
#PrimaryKeyJoinColumn(name = "username",referencedColumnName = "username")
#DiscriminatorValue("2")
#NamedQueries({
#NamedQuery(name="Customer.all",query = "select c from Customer c")
})
public class Customer extends User implements Serializable{
public enum VIP_TYPE {NORMAL,SILVER,GOLD,DIAMOND}
#Transient
private static final int SILVER_THRESHOLD = 1000;
#Transient
private static final int GOLD_THRESHOLD = 2000;
#Transient
private static final int DIAMOND_THRESHOLD = 3000;
private String firstName;
private String lastName;
private String email;
private String address;
private String postcode;
private String mobileNumber;
private String homeNumber;
#Convert(converter = VipTypeConverter.class)
private VIP_TYPE vipGroup;
private String discount;
#OneToMany(mappedBy = "customer",targetEntity = Order.class,fetch=FetchType.EAGER,cascade = CascadeType.ALL)
#JsonIgnore
private Set<Order> orders = new HashSet<>();
public Customer() {
}
#Override
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
public void addOrder(final Order order){
orders.add(order);
updateVipGroup();
}
private void updateVipGroup() {
int sum = orders.stream().map(Order::getPayment).distinct().mapToInt(p->p.getAmmount()).sum();
if(sum > DIAMOND_THRESHOLD){
vipGroup = VIP_TYPE.DIAMOND;
return;
}
if(sum > GOLD_THRESHOLD){
vipGroup = VIP_TYPE.GOLD;
return;
}
if(sum > SILVER_THRESHOLD){
vipGroup = VIP_TYPE.SILVER;
return;
}
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setEmail(String email) {
this.email = email;
}
public void setAddress(String address) {
this.address = address;
}
public void setDiscount(String discount) {
this.discount = discount;
}
public void setVipGroup(VIP_TYPE vipGroup) {
this.vipGroup = vipGroup;
}
public void setHomeNumber(String homeNumber) {
this.homeNumber = homeNumber;
}
public void setMobileNumber(String mobileNumber) {
this.mobileNumber = mobileNumber;
}
public void setPostcode(String postcode) {
this.postcode = postcode;
}
public String getDiscount() {
return discount;
}
public VIP_TYPE getVipGroup() {
return vipGroup;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getEmail() {
return email;
}
public String getAddress() {
return address;
}
public String getPostcode() {
return postcode;
}
public String getMobileNumber() {
return mobileNumber;
}
public String getHomeNumber() {
return homeNumber;
}
}
Persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="local" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/cod</jta-data-source>
<class>com.technicalpioneers.cod.user.Customer</class>
<class>com.technicalpioneers.cod.user.Employee</class>
<class>com.technicalpioneers.cod.user.User</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
</persistence-unit>
</persistence>
Everything to do with "employee" works file, I can use the named query Employee.all to find all the employees in the database.
However, If I try to retrieve any customers I get errors. If I try to run the named query Customer.all I get:
java.lang.IllegalArgumentException: NamedQuery of name: Customer.all not found.
If I try to use EntityManager's find() method to find a particular customer I get:
javax.servlet.ServletException: Exception [EclipseLink-43] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Missing class for indicator field value [2] of type [class java.lang.Integer].
Descriptor: RelationalDescriptor(com.technicalpioneers.cod.user.User --> [DatabaseTable(user)])
I don't understand why the Customer entity is not being found by JPA. I've checked the user table and the "type" column is there with correct numbers, and #DescriminatorValue is set correctly. It's almost like the annotations are being ignored?
Have done many clean rebuilds and redeploys too. Any help would be very much appreciated!
I found this eventually. https://bugs.eclipse.org/bugs/show_bug.cgi?id=429992
It turns out EclipseLink will silently ignore entities with lambda expressions! Very annoying for it to not be at least mentioned in logs!
Thanks to everyone who took the time!
Related
I'm fairly new to Spring, and coding in general. I want to build an application from which a user can update existing records in a database from a CSV file. I'm using spring batch to do so, but when I execute the test, I get the famous:
java.lang.IllegalStateException: Existing transaction detected in JobRepository. Please fix this and try again (e.g. remove #Transactional annotations from client).
If I remove the #Transactional, I get this error instead:
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.hql.internal.QueryExecutionRequestException: Not supported for DML operations [UPDATE com.example.testApp.Models.Person p SET p.address = p.address, p.country = p.country, p.cellphone = p.cellphone, p.city = p.city, p.phone = p.cellphone, p.email = p.email, p.age = p.age WHERE p.pplId IN (:ids_0, :ids_1, :ids_2, :ids_3, :ids_4, :ids_5, :ids_6, :ids_7, :ids_8, :ids_9, :ids_10)]
I've looked around some other solutions here, but they don't seem to work for what I want to do. I'm aware that hibernate supports batch updates, but again, I'm not sure how to make it work with what I already have.
Here's my test class (obviously with just the method I've been having problems with):
#SpringBootTest
public class PersonTests {
#Autowired
private PeopleRepository peopleRepository;
#Autowired
JobLauncher jobLauncher;
#Autowired
Job peopleInsertJob; //Separate job for inserting from a CSV file
#Autowired
Job peopleUpdateJob;
#Order(4) //executes after the insert from CSV test, for obvious reasons.
#Test
public void updateRecordsFromCsvFile() throws Exception {
Map<String, JobParameter> maps = new HashMap<>();
maps.put("time", new JobParameter(System.currentTimeMillis()));
JobParameters parameters = new JobParameters(maps);
JobExecution jobExecution = jobLauncher.run(peopleUpdateJob, parameters);
assertEquals("COMPLETED", jobExecution.getStatus().name());
}
}
Here's my Batch configuration file for the update:
#Bean
public Job peopleUpdateJob(JobBuilderFactory jobBuilderFactory,
StepBuilderFactory stepBuilderFactory,
ItemReader<Person> itemReaderForUpdate,
ItemProcessor<Person, Person> itemProcessor,
#Qualifier("DBPeopleUpdater") ItemWriter<Person> itemUpdater)
{
Step step = stepBuilderFactory.get("ETL-file-load")
.<People, People>chunk(100)
.reader(itemReaderForUpdate)
.processor(itemProcessor)
.writer(itemUpdater)
.build();
return jobBuilderFactory.get("ETL-Load")
.incrementer(new RunIdIncrementer())
.start(step)
.build();
}
#Bean
public FlatFileItemReader itemReaderForUpdate() throws Exception
{
FlatFileItemReader<Person> flatFileItemReader = new FlatFileItemReader<>();
flatFileItemReader.setResource(new FileSystemResource("src/main/resources/CSV/TestFilePeople-UpdateBatch.csv"));
flatFileItemReader.setName("PeopleCSV-Update-Reader");
flatFileItemReader.setLinesToSkip(1);
flatFileItemReader.setLineMapper(lineMapper());
return flatFileItemReader;
}
#Bean
public LineMapper<Person> lineMapper()
{
DefaultLineMapper<Person> defaultLineMapper = new DefaultLineMapper<>();
DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();
lineTokenizer.setDelimiter(",");
lineTokenizer.setStrict(false);
lineTokenizer.setNames("Id","lastname", "lastname2", "firstname",
"midname","phone", "cellphone", "email", "status", "address", "city", "region", "country");
BeanWrapperFieldSetMapper<Person> fieldSetMapper = new BeanWrapperFieldSetMapper<>();
fieldSetMapper.setTargetType(Person.class);
defaultLineMapper.setLineTokenizer(lineTokenizer);
defaultLineMapper.setFieldSetMapper(fieldSetMapper);
return defaultLineMapper;
}
This is the ItemWriter I'm using for the update:
#Component
public class DBPeopleUpdater implements ItemWriter<Person> {
#Autowired
PeopleRepository peopleRepository;
#Override
public void write(List<? extends Person> list) throws Exception
{
List<String> pplIds = new ArrayList<>();
for(People p : list)
{
pplIds.add(p.getpplId());
}
peopleRepository.updatePersonsByIdIsIn(pplIds);
}
}
This is the method that I'm using from my PeopleRepository. It's the only method I have. My repository is extends CrudRepository:
#Modifying
#Query("UPDATE Person p SET p.address= p.address, p.country = p.country," +
"p.cellphone = p.cellphone, p.city = p.city, p.phone = p.cellphone," +
"p.email = p.email, p.status = p.status WHERE p.pplId IN :ids")
List<Person>updatePersonsByPplIdIsIn(List<String> ids);
I'm mapping my Person class as an entity that connects to a PostgreSQL database table. I don't have any local sql files in my project. I have no other tables in the database.
If it's not possible to solve this using spring batch, if you could guide me towards jpa/hibernate resources I could use to understand how to solve this problem, I would really appreciate it.
EDIT
Here's the code for the entity
#Entity
#Table(name = "people", schema = "example_schema")
public class Person {
#NonNull
#Id
#Column(name = "ppl_id")
private String pplId;
#Column(name = "ppl_last_name")
private String lastname;
#Column(name = "ppl_sec_last_name")
private String lastname2;
#Column(name = "ppl_first_name")
private String firstname;
#Column(name = "ppl_mid_name")
private String midname;
#Column(name = "ppl_phone_no")
private String phone;
#Column(name = "ppl_cell_no")
private String cellphone;
#Column(name = "ppl_corp_email")
private String email;
#Column(name="ppl_status")
private String status;
#Column(name="ppl_address")
private String address;
#Column(name="ppl_city")
private String city;
#Column(name="ppl_region")
private String region;
#Column(name="ppl_country")
private String country;
//Default constructor
public Person()
{
super();
}
public Person(#NonNull String pplId, String lastname, String lastname2, String firstname, String midname, String phone, String cellphone, String email, String status, String address, String city, String region, String country) {
this.pplId = pplId;
this.lastname = lastname;
this.lastname2 = lastname2;
this.firstname = firstname;
this.midname = midname;
this.phone = phone;
this.cellphone = cellphone;
this.email = email;
this.status = status;
this.address = address;
this.city = city;
this.region = region;
this.country = country;
}
public String getPplId() {
return pplId;
}
public void setWrkId(String pplId) {
this.pplId = pplId;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getLastname2() {
return lastname2;
}
public void setLastname2(String lastname2) {
this.lastname2 = lastname2;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getMidname() {
return midname;
}
public void setMidname(String midname) {
this.midname = midname;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getCellphone() {
return cellphone;
}
public void setCellphone(String cellphone) {
this.cellphone = cellphone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
I have a application written in Spring, Hibernate and SpringBoot,
I have 2 entities class with one to many mapping,
Here are my LeadUserDb entity class
#Entity
#Table(name="lead_user_db")
#NamedQuery(name="LeadUserDb.findAll", query="SELECT l FROM LeadUserDb l")
public class LeadUserDb implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(name="branchcode")
private String branchcode;
#Column(name="reporting_level")
private int reportingLevel;
//bi-directional many-to-one association to UserBasicDetailsDb
#ManyToOne
#JoinColumn(name="email_Id")
private UserBasicDetailsDb userBasicDetailsDb;
public LeadUserDb() {
}
public String getBranchcode() {
return this.branchcode;
}
public void setBranchcode(String branchcode) {
this.branchcode = branchcode;
}
public int getReportingLevel() {
return this.reportingLevel;
}
public void setReportingLevel(int reportingLevel) {
this.reportingLevel = reportingLevel;
}
public UserBasicDetailsDb getUserBasicDetailsDb() {
return this.userBasicDetailsDb;
}
public void setUserBasicDetailsDb(UserBasicDetailsDb userBasicDetailsDb) {
this.userBasicDetailsDb = userBasicDetailsDb;
}
And This is my UserBasicDetailsDb Entity Class
#Entity
#Table(name="user_basic_details_db")
public class UserBasicDetailsDb implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private String email;
private String address;
private String city;
private String dob;
private String mobile;
private String name;
private String pan;
private String pincode;
private String state;
#OneToMany(mappedBy="userBasicDetailsDb")
private List<LeadUserDb> leadUserDbs;
public UserBasicDetailsDb() {
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getDob() {
return this.dob;
}
public void setDob(String dob) {
this.dob = dob;
}
public String getMobile() {
return this.mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getPan() {
return this.pan;
}
public void setPan(String pan) {
this.pan = pan;
}
public String getPincode() {
return this.pincode;
}
public void setPincode(String pincode) {
this.pincode = pincode;
}
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
public List<LeadUserDb> getLeadUserDbs() {
return this.leadUserDbs;
}
public void setLeadUserDbs(List<LeadUserDb> leadUserDbs) {
this.leadUserDbs = leadUserDbs;
}
public LeadUserDb addLeadUserDb(LeadUserDb leadUserDb) {
getLeadUserDbs().add(leadUserDb);
leadUserDb.setUserBasicDetailsDb(this);
return leadUserDb;
}
public LeadUserDb removeLeadUserDb(LeadUserDb leadUserDb) {
getLeadUserDbs().remove(leadUserDb);
leadUserDb.setUserBasicDetailsDb(null);
return leadUserDb;
}
what i want to achieve is to create a query like this one
SELECT a.branchcode as branchCode,b.name FROM lead_user_db a
inner join user_basic_details_db b
where b.email = a.email_id and a.reporting_level = 3
here is what I have written my Repository class
public interface GetUserList extends CrudRepository<LeadUserDb, Integer> {
#Query(value = "SELECT a.id, a.branchcode as branchCode,b.name as name,a.reporting_level,a.email_id FROM lead_user_db a\n" +
"inner join user_basic_details_db b\n" +
"where b.email = a.email_id and a.reporting_level = ?1", nativeQuery = true)
List<LeadUserDb> findByReportingLevel(int reportingLevel);
}
and this is how I am calling it
UserBasicDetailsDb details = GetUserList.findByReportingLevel(3);
NOTE
Getting a new error Cannot determine value type from string test#dev.com
I am getting a hell lot of data, and the actual output have only 2 records
My question is how can i fetch the list of user based on reportingLevel
Any help would be appreciated
I have three entity classes, I have written the query which includes join of two tables.
Table: ExpensesCategories
#Entity
#Table(name = "ExpensesCategories")
public class ExpensesCategories {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "category_id", unique = true)
private int categoryId;
#NotNull
private String categoryName;
#NotNull
private String categoryCodeInBankStats;
public int getCategoryId() {
return categoryId;
}
public void setCategoryId(int categoryId) {
this.categoryId = categoryId;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public String getCategoryCodeInBankStats() {
return categoryCodeInBankStats;
}
public void setCategoryCodeInBankStats(String categoryCodeInBankStats) {
this.categoryCodeInBankStats = categoryCodeInBankStats;
}
}
Table: Transactions
#Entity
#Table(name = "TransactionHistory")
public class TransactionHistory {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Temporal(TemporalType.DATE)
private Date dateOfTransaction;
private String transactionType;
private String refNo;
private Date valueDate;
private double withdrawalAmount;
private double depositAmount;
private double closingBalance;
#ManyToOne
#JoinColumn(name="userDetailsId", referencedColumnName="user_id")
private UserDetails userDetails;
#ManyToOne
#JoinColumn(name="expenseCategoriesId", referencedColumnName="category_id")
private ExpensesCategories expenseCategories;
public TransactionHistory(int userId, Date dateOfTransaction, String transactionType, String refNo, Date valueDate,
double withdrawalAmount, double depositAmount, double closingBalance) {
this.dateOfTransaction = dateOfTransaction;
this.transactionType = transactionType;
this.refNo = refNo;
this.valueDate = valueDate;
this.withdrawalAmount = withdrawalAmount;
this.depositAmount = depositAmount;
this.closingBalance = closingBalance;
}
public TransactionHistory() {
}
public Date getDateOfTransaction() {
return dateOfTransaction;
}
public void setDateOfTransaction(Date date) {
this.dateOfTransaction = date;
}
public String getTransactionType() {
return transactionType;
}
public void setTransactionType(String transactionType) {
this.transactionType = transactionType;
}
public String getRefNo() {
return refNo;
}
public void setRefNo(String refNo) {
this.refNo = refNo;
}
public Date getValueDate() {
return valueDate;
}
public void setValueDate(Date valueDate) {
this.valueDate = valueDate;
}
public double getWithdrawalAmount() {
return withdrawalAmount;
}
public void setWithdrawalAmount(double withdrawalAmount) {
this.withdrawalAmount = withdrawalAmount;
}
public double getDepositAmount() {
return depositAmount;
}
public void setDepositAmount(double depositAmount) {
this.depositAmount = depositAmount;
}
public double getClosingBalance() {
return closingBalance;
}
public void setClosingBalance(double closingBalance) {
this.closingBalance = closingBalance;
}
public UserDetails getUserDetails() {
return userDetails;
}
public void setUserDetails(UserDetails userDetails) {
this.userDetails = userDetails;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public ExpensesCategories getExpenseCategories() {
return expenseCategories;
}
public void setExpenseCategories(ExpensesCategories expenseCategories) {
this.expenseCategories = expenseCategories;
}
}
Table: User Details
#Entity
#Table(name = "Employee")
public class UserDetails {
#Id
#Column(name = "user_id", unique = true)
private int id;
#NotNull
private String firstname;
#NotNull
private String lastname;
#Column(unique = true)
#NotNull
private String emailaddress;
#NotNull
private String role;
public UserDetails(String firstname, String lastname, String emailaddress, String role) {
this.firstname = firstname;
this.lastname = lastname;
this.emailaddress = emailaddress;
this.role = role;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public UserDetails() {
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmailaddress() {
return emailaddress;
}
public void setEmailaddress(String emailaddress) {
this.emailaddress = emailaddress;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
#Override
public String toString() {
return "Employee [id=" + id + ", firstname=" + firstname + ", lastname=" + lastname + ", emailaddress="
+ emailaddress + ", role=" + role + "]";
}
I have written query like this in transaction entity.
#Query( nativeQuery=true, value="SELECT a.expense_categories_id, a.Total_withdrawal_Amount, b.category_code_in_bank_stats, b.category_name FROM (SELECT expense_categories_id , SUM(withdrawal_amount) AS Total_withdrawal_Amount FROM transaction_history GROUP BY expense_categories_id) a join expenses_categories b on a.expense_categories_id = b.category_id
")
List<Object[]> getCategorizedExpenses();
My Json Response is like:
[
[
1,
21,
"UPI",
"UPI Payments"
],
[
2,
3733.59,
"POS",
"Shopping"
]
]
But i want json response with column names as well:
[
[
expense_categories_id: 1,
Total_withdrawal_Amount: 21,
category_code_in_bank_stats: "UPI",
category_name: "UPI Payments"
],
[
expense_categories_id: 2,
Total_withdrawal_Amount: 3733.59,
category_code_in_bank_stats: "POS",
category_name: "Shopping"
]
]
Please help me out..
You would need to map the results directly to a POJO class and ad some json config:
1) Define the pojo
public ResultClass implements Serializable{
#JsonProperty("expense_categories_id")
private Integer expenseCategoriesId;
...
public ResultClass(Integer expenseCategoriesId ... // rest params){
this.expenseCategoriesId = expenseCategoriesId;
...
}
}
2) Define the mapping:
#SqlResultSetMapping(
name="myMapping",
classes={
#ConstructorResult(
targetClass=ResultClass.class,
columns={
#ColumnResult(name="expenseCategoriesId"),
#ColumnResult(name="totalWithdrawalAmount")
// further mappings ...
}
)
}
)
3) Define a native query
#NamedNativeQuery(name="TransactionHistory.myQuery"
, query="SELECT new mypackage.ResultClass(a.expense_categories_id as expeneCategoriesId ... ) from ...")
4) Define this method in the CrudRepository without the #Query annotation:
public List<ResultClass> myQuery();
Teh #SqlResultSetMapping and #NamedNativeQuery would need to be defined on one of your mapped entities.
Your native query will give you an object[][] as an result. So, it actually a mxn rows.
So,
I think you should create a class names Response
public class Response{
private Long expense_categories_id;
private Double Total_withdrawal_Amount;
private String category_code_in_bank_stats;
private String category_name;
//getters and setters for all attributes
}
List<Response> fillCategorizedExpenses(){
List<Response> response_List = new ArrayList<>();
Response response = null;
Object[][] // fill each object with by accessing their index from
//this array.
for() //iterate the object array. {
response = new Response();
response.setExpense_categories_id(value); // set all attributes.
....
....
....
response_List.add(response);
}
return response_List; //this will print as you need in your project.
}
Thank You :) Hope this might help you out.
I feel my app runs slow. I use Java for my server, so except java itself,the first reason of slow run, I think, is the account of database access. Hibernate could search all attribute associate with the entity which you are using, so I think it may send a lot of SQL language when finding one entity. If there's a large concurrent happening ,the trouble will happen.
#Component("user")
#Entity
#Table(name="users")
public class User implements Serializable{
#Id
#GenericGenerator(strategy="assigned",name="idGenerator")
#GeneratedValue(generator="idGenerator")
private String client_id;
#Column(name="username")
private String username;
#Column(name="password")
private String password;
#Column(name="email")
private String email;
#Column(name="phone")
private String phone;
#Column(name="sex")
private String sex;
#Column(name="birth")
private String birth;
#Column(name="status")
public String status;
#Column(name="isonline")
private String isonline;
#Column(name="province")
private String province;
#Column(name="city")
private String city;
#ManyToOne()
#JoinColumn(name="channel_id")
private Channel channel;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="created_at",updatable=true)
private Date created_at = new Date();
#Column(name="last_login_at")
private Date last_login_at;
#ManyToMany()
#JoinTable(name = "users_labels",
joinColumns = #JoinColumn(name = "client_id"),
inverseJoinColumns = #JoinColumn(name = "label_name"))
#LazyCollection(LazyCollectionOption.FALSE)
private Set<Label> labellist;
#ManyToOne()
#JoinTable(name = "user_topics",
joinColumns = #JoinColumn(name = "client_id"),
inverseJoinColumns = #JoinColumn(name = "huanxin_group_id"))
private Topic topic;
#ManyToMany()
#JoinTable(name="friends",
joinColumns=#JoinColumn(name="client_id"),
inverseJoinColumns=#JoinColumn(name="friend_id"))
#LazyCollection(LazyCollectionOption.FALSE)
private Set<User> friends;
#OneToMany(mappedBy="user")
private Set<FeedBack> feedbacks;
#ManyToMany()
#JoinTable(name="blacklist",
joinColumns=#JoinColumn(name="client_id"),
inverseJoinColumns=#JoinColumn(name="blocker_id"))
#LazyCollection(LazyCollectionOption.FALSE)
private Set<User> blacklist;
public Topic getTopic() {
return topic;
}
public void setTopic(Topic topic) {
this.topic = topic;
}
public Set<Label> getLabellist() {
return labellist;
}
public void setLabellist(Set<Label> labellist) {
this.labellist = labellist;
}
public String getClient_id() {
return client_id;
}
public void setClient_id(String client_id) {
this.client_id = client_id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getBirth() {
return birth;
}
public void setBirth(String birth) {
this.birth = birth;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getIsonline() {
return isonline;
}
public void setIsonline(String isonline) {
this.isonline = isonline;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public Channel getChannel() {
return channel;
}
public void setChannel(Channel channel) {
this.channel = channel;
}
public Date getCreated_at() {
return created_at;
}
public void setCreated_at(Date created_at) {
this.created_at = created_at;
}
public Date getLast_login_at() {
return last_login_at;
}
public void setLast_login_at(Date last_login_at) {
this.last_login_at = last_login_at;
}
public Set<User> getFriends() {
return friends;
}
public void setFriends(Set<User> friends) {
this.friends = friends;
}
public Set<FeedBack> getFeedbacks() {
return feedbacks;
}
public void setFeedbacks(Set<FeedBack> feedbacks) {
this.feedbacks = feedbacks;
}
public Set<User> getBlacklist() {
return blacklist;
}
public void setBlacklist(Set<User> blacklist) {
this.blacklist = blacklist;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((client_id == null) ? 0 : client_id.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (client_id == null) {
if (other.client_id != null)
return false;
} else if (!client_id.equals(other.client_id))
return false;
return true;
}
#Override
public String toString() {
return "User [client_id=" + client_id + ", username=" + username
+ ", labellist=" + labellist+ "]";
}
}
Just like this, User contains Topic, Label or other Entity in future. So I think that is not possible to remove this association. How could I improve my database access to improve access speed?
Another reason influncing the app speed may be my algorithm. I use bubble sort, selection sort, and quick sort. Each sort seems to cost little time on little data. But what if the concurrent occurs? 300 users may cost only 20 msec but 300 000 I couldn't imagine.
Here is my sort code:
private static List<Map<String,Object>> sortInteger(List<Map<String,Object>> list){
int index = 0;
int max = 0;
Map<String,Object> temp = new HashMap<String, Object>();
for(int i=0;i<list.size();i++){
for(int j=0;j<list.size()-i-1;j++){
Map<String,Object> pre = (Map<String, Object>) list.get(j);
Map<String,Object> next = (Map<String, Object>) list.get(j+1);
if((Integer)pre.get("sortnum")<(Integer)next.get("sortnum")){
temp = pre;
list.set(j, next);
list.set(j+1,pre);
}
}
}
return list;
}
So in terms of above, I need some suggestion to solve my question,either theory or code.
Hi I can't get merge working it only makes new record but don't update record
EDIT:
Object:
#Entity(name = "ALLEGRO_TRANSACTION")
public class AllegroTransactionImpl implements AllegroTransaction{
#Id
#Column(name = "ID")
#GeneratedValue(strategy = GenerationType.AUTO)
protected Long id;
#Column(name = "ALIEXPRESS_NUMBER")
protected String aliexpressNumber;
#Column(name = "CREATE_DATE")
protected Date createDate;
#OneToOne(optional = true, targetEntity = PaymentTypeImpl.class)
#JoinColumn(name = "PAYMENT_ID")
protected PaymentTypeImpl paymentType;
#Column(name = "FIRST_NAME")
protected String firstName;
#Column(name = "LAST_NAME")
protected String lastName;
#Column(name = "PRICE")
protected float price;
#Column(name = "EMAIL")
protected String email;
#Column(name = "PHONE", nullable = true)
protected String phone;
#Column(name = "ADDRESS", columnDefinition="LONGTEXT")
protected String address;
#Column(name = "ATTENTION", columnDefinition="LONGTEXT")
protected String attention;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getAliexpressNumber() {
return aliexpressNumber;
}
public void setAliexpressNumber(String aliexpressNumber){
this.aliexpressNumber = aliexpressNumber;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public PaymentTypeImpl getPaymentType() {
return paymentType;
}
public void setPaymentType(PaymentTypeImpl paymentType) {
this.paymentType = paymentType;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getAttention() {
return attention;
}
public void setAttention(String attention) {
this.attention = attention;
}
}
Manager:
#Service
public class AllegroTransactionService {
private final static Logger logger = Logger.getLogger(AllegroTransactionService.class);
#PersistenceContext( unitName = "allegroTransactionPersistenceUnit", type= PersistenceContextType.EXTENDED )
protected EntityManager em;
public List<AllegroTransactionImpl> readAllegroTransactionByCreateDate()
{
Query query = this.em.createQuery( "SELECT allegroTransaction FROM com.springapp.mvc.classes.AllegroTransactionImpl allegroTransaction ORDER BY createDate DESC" );
return query.getResultList();
}
#Transactional
public AllegroTransactionImpl saveAllegroTransaction(AllegroTransactionImpl allegroTransaction)
{
this.em.merge( allegroTransaction );
return allegroTransaction;
}
}
Still can't get this working ... Maybe you guys figure something out ? Entity manager works i can easly get readAllegroTransaction function working but merge don't work - its create another object.
Problem was not passing correctly ID parameter