Insert to DataBase Using EntityManager - java

I've been looking for a way to interact with my database using EntityManager class in Java.
The question is related to these two tables I have defined in my DB:
PARENT_TABLE:
PK_ONE
PK_TWO
CHILD TABLE:
PK_ONE
COLUMN
PK_TWO
Here is something I have so far.
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.SecondaryTable;
import javax.persistence.Table;
import javax.persistence.PrimaryKeyJoinColumn;
#Entity
#Table(name="PARENT_TABLE")
#SecondaryTable(name="CHILD_TABLE", pkJoinColumns={
#PrimaryKeyJoinColumn(name="PK_ONE"),
#PrimaryKeyJoinColumn(name="PK_TWO")})
public class ExampleTbl implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="PK_ONE")
private String pkOne;
#Id
#Column(name="COLUMN", table="CHILD_TABLE")
private String column;
#Column(name="PK_TWO")
private String pkTwo;
//GETTERS AND SETTERS
}
My questions are:
To be able to Insert to the PARENT_TABLE a new row, do I have to create a new Entity class with just two fields (PK_ONE, PK_TWO) to be able to use the merge() or persist() method?
Will I have to create another Entity class to Insert a new row to my CHILD_TABLE?
To retrieve a List with the existing data I have a method something like this:
#Transactional(readOnly = true)
public List<ExampleTbl> getFoldersList() {
em = emf.createEntityManager();
Query q = em.createQuery("SELECT e FROM ExampleTbl e WHERE e.pkTwo = :pkTwo ORDER BY e.pkOne");
q.setParameter("pkTwo", "My Test");
List<ExampleTbl> result = q.getResultList();
return result;
}
Do you think this is the best way to do it?

I think its a question with a couple of possible answers. I would recommend reviewing some of the ways they set things up in the Java EE 6 tutorial examples. You can read about that at http://docs.oracle.com/javaee/6/tutorial/doc/giqst.html

Related

Does Hibernate (JPA) allow to map custom columns (i.e. Aliased columns)

I am having simple entity with few properties as shown in image.
Query as follows
select *,concat(current_date - cre_dte::date) as _days_ago
from test."general"
where (current_date - cre_dte::date)=7 or (current_date - cre_dte::date)<11
My Entity is
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
#Data
#Entity
#Table(name = "general", schema = "test")
public class GeneralEntity implements Serializable {
private static final long serialVersionUID = -2343243243242432341L;
/**
* id
*/
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
/**
* loadNumber
*/
#Column(name="load_number")
private String loadNumber;
/**
* createdDate
*/
#Column(name="cre_dte")
private Date createdDate;
#Formula(value = "_days_ago")
private String _daysAgo;
}
I am trying to map entities to store _days_ago from my native query to pojo. for that I modified pojo to add #Formula. but seems like does not mapping this alias to my property. In my JPA interface my method is like below
#Query(nativeQuery = true,value = "select *, concat(current_date - cre_dte::date) as _days_ago from general where (current_date - cre_dte::date)=7 or (current_date - cre_dte::date)<11")
public List<GeneralEntity> getFewDaysAgo() throws Exception;
You can use #Formula for this purpose like:
public class GeneralEntity implements Serializable {
...
#Formula("current_date - cre_dte::date")
Integer daysAgo;
}
but I generally don't recommend that as that will be executed every time you fetch a GeneralEntity entity.
Usually this is best handled by using a custom DTO projection for this use case. You could use something like the following:
class GeneralEntityDto {
Long id;
String loadNumber;
Date createdDate;
String daysAgo;
// constructor + getters
}
and a query like this:
#Query("select new com.mycompany.package.GeneralEntityDto(g.id, g.loadNumber, g.createdDate, concat(current_date - cast(g.createdDate as date)) from GeneralEntity where (current_date - cast(g.createdDate as date))=7 or (current_date - cast(g.createdDate as date))<11")
public List<GeneralEntityDto> getFewDaysAgo();
If you have more complex needs like the need to map collections, you should give Blaze-Persistence Entity Views a shot.
I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.
A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:
#EntityView(GeneralEntity.class)
public interface GeneralEntityDto {
#IdMapping
Long getId();
String getLoadNumber();
Date getCreatedDate();
#Mapping("DAY_DIFF(CAST_DATE(createdDate), current_date)")
String getDaysAgo();
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
GeneralEntityDto a = entityViewManager.find(entityManager, GeneralEntityDto.class, id);
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
public default List<GeneralEntityDto> getFewDaysAgo() {
return findAll((root, query, criteriaBuilder) -> {
Expression e = criteriaBuilder.function("DAY_DIFF", root.get(createdDate).as(java.sql.Date.class), criteriaBuilder.currentDate());
return criteriaBuilder.or(
criteriaBuilder.equal(e, criteriaBuilder.literal(7)),
criteriaBuilder.lessThan(e, criteriaBuilder.literal(1))
);
});
}
public List<GeneralEntityDto> findAll(Specification s);

JPA load entities, but therein in a #OneToMany list, only load specific

Situation:
(using Payara Server)
I have multiple Groups, and each Group has their own specific set of GroupMeetings.
These GroupMeetings are tracked over multiple years.
Each Group contains 100-10000 GroupMeetings.
But usually only the current year's GroupMeetings are queried and used.
Problem:
How can I load all Groups, but only load each Group's GroupMeeting List for a specific interval, for example only the GroupMeetings of 2019? Or, if need be, specific years or ranges, i.e. 2017-2021 etc?
If I simply run a "SELECT *", then with the FetchType.LAZYI will get empty an emtpy List<GroupMeeting>, but as soon as I access it somewhere in the code, all the items will be loaded.
Question:
Whats the best strategy, i.e. somewhat efficient but not overly convoluted?
Is there an easy SQL/JPQL query that I can run with the classes below?
Is there some structural change - especially in the annotations - needed?
Should I consider Criteria API?
Do I have to use two List<GroupMeeting>s, one with the commonly used meetings, the other with the 'old' meetings?
Example:
Here are the two classes:
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
#Entity
public class Group {
#Id //
#GeneratedValue() //
private long id;
private String name;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true) #JoinTable(name = "group_meetings") //
private final List<GroupMeeting> meetings = new ArrayList<>();
}
and
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class GroupMeeting {
#Id //
#GeneratedValue() //
private long id;
private String title;
private Date start;
private Date end;
}
You can use Hibernate filters to achieve that, for instance:
#Entity
#FilterDef(name="groupMeetingFilter",
parameters={#ParamDef( name="fromDate", type="date"), #ParamDef(name="toDate", type="date")} )
public class Group {
#Id //
#GeneratedValue() //
private long id;
private String name;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true) #JoinTable(name = "group_meetings")
#Filter(
name = "groupMeetingFilter",
condition="start <= :fromDate and end >= :toDate"
)
private final List<GroupMeeting> meetings = new ArrayList<>();
}
And you need to enable your filter somewhere in your application, just like this:
Session session = HibernateUtil.getSessionFactory().openSession();
Filter filter = session.enableFilter("groupMeetingFilter");
//Define here the dates that you want
filter.setParameter("fromDate", new Date());
filter.setParameter("toDate", new Date());
You could go further with your research and make the filter global available, if you're using Spring for instance, is easier.

Hibernate : Genereting dynamic entity at runtime

I need to create entity based on information from database. Based on database I created string like this :
` package az.com.ds.entity.crudEntity;
import javax.persistence.Table;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Column;
#Table(name = "CMN_SP", schema = "CMN")
#Entity
public class CmnSpEnt {
#Id
private Integer id;
#Column(name = "NAME")
private String name;
} `
Then I created java file based on this string and compiled it at runtime. Everything works perfectly to this step. But when I want to get data based on entity it throws exception as
org.hibernate.hql.internal.ast.QuerySyntaxException: CmnSpEnt is not mapped [Select x from CmnSpEnt x ].
Now I need to map entity for hibernate in order to get data from database. Is there a way to accomplish this?

org.h2.jdbc.JdbcSQLException: Column "Id" not found during testing with H2 Database

I have a class that uses a Hibernate session to call a stored procedure via a JPA #NamedNativeQuery using an in memory H2 database for testing (the actual database is MySQL). The stored procedure inserts a record into a database table and then returns that row.
However during testing, on converting to the JPA #Entity, I am seeing an H2 database error: org.h2.jdbc.JdbcSQLException: Column "Id" not found.
I've documented a cut down version of the code below.
As far as I can tell I think it has something to do with the H2 interpretation of the #Id annotation, but don't understand why, so any help would be gratefully appreciated...
NB - I have searched Stack overflow fairly extensively, including the issue relating to the use of double quotes for column specification, but don't think that this relates to my situation...
Table
CREATE TABLE History.Status_Report (
Id INT NOT NULL AUTO_INCREMENT,
Unique_Users INT NOT NULL,
PRIMARY KEY (Id)
);
Stored Procedure
CREATE PROCEDURE History.Status_Reporting(reporting_date DATE)
BEGIN
INSERT INTO history.status_report (Unique_Users) VALUES (10);
SELECT *
 FROM History.Status_Report WHERE Id = LAST_INSERT_ID();
END;
Entity
package com.test;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedNativeQuery;
import javax.persistence.Table;
import java.io.Serializable;
#NamedNativeQuery(name = "callStatusReporting", query = "CALL Status_Reporting(:reporting_date)", resultClass = StatusReportEntity.class)
#Entity
#Table(name = "Status_Report", catalog = "History")
public class StatusReportEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name = "Id")
protected Integer id;
#Column(name = "Unique_Users")
protected int uniqueUsers;
public Integer getId() {
return this.id;
}
public int getUniqueUsers() {
return this.uniqueUsers;
}
}
Class under test
package com.test;
import org.hibernate.Query;
import org.hibernate.Session;
public class MyListener {
public StatusReportEntity doRequest(Date reportDate) {
Session session = HibernateUtil.openSession(); // returns a MySQL session or H2 if testing…
try {
Query query = session.getNamedQuery("callStatusReporting").setParameter("reporting_date", reportDate);;
StatusReportEntity statusReportEntity = (StatusReportEntity) query.uniqueResult();
return statusReportEntity;
} catch (Exception e) {
System.err.println(e);
} finally {
session.close();
return null;
}
}
H2 Aliases
To enable testing using H2, There is also a file to specify the necessary aliases:
CREATE SCHEMA IF NOT EXISTS History;
CREATE ALIAS IF NOT EXISTS Status_Reporting FOR "com.test.StoredProcs.statusReporting";
Test Class to be used by Alias
And a test class to return a default result from the SP call:
package com.test;
import com.test.StatusReportEntity;
public class StoredProcs {
public static StatusReportEntity statusReporting(Date reportingDate) {
StatusReportEntity statusReportEntity = StatusReportEntity.builder().withId(1).withUniqueUsers(10).build();
return statusReportEntity;
}
}
Test Class
package com.test;
import com.test.MyListener;
import java.util.Calendar;
import org.junit.Test;
import static org.junit.Assert.*;
public class MyListenerTest {
private MyListener listener;
#Test
public void listenerReturnsLatestData() throws Exception {
MyListener myListener = new MyListener();
assertNotNull(myListener.statusReporting(Calendar.getInstance().getTime()));
}
}
CREATE TABLE PERSON(
PERSON_ID IDENTITY PRIMARY KEY,
GIVEN_NAME VARCHAR(20),
FIRST_NAME VARCHAR(20),MIDDLE_NAME VARCHAR(20),
LAST_NAME VARCHAR(20),TITLE VARCHAR(20),NAME_SUFFIX VARCHAR(20));
The entity class must use any Generation strategy.
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name ="PERSON_ID")
private int personId;

How to use Hibernate #Index annotation properly? [duplicate]

This question already has answers here:
Creating Indexes on DB with Hibernate #Index Annotation
(4 answers)
Closed 7 years ago.
i have a java class used as an entity that has 2 classes that inherit from it. this class has some indices but these indices didn't appear in the database. this is my java super class code
import java.io.Serializable;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.persistence.Version;
import javax.persistence.OneToMany;
import org.hibernate.annotations.GenericGenerator;
#Entity
#Table(name="service", uniqueConstraints = {#UniqueConstraint(columnNames={"name"})})
#org.hibernate.annotations.Table(appliesTo = "service",
indexes = { #Index(name = "service_name", columnNames = { "name" }),
#Index(name = "service_description", columnNames = { "description" }),
#Index(name = "service_accessNumber", columnNames = { "access_number" })
})
public class Service implements Serializable {
#Column(name="access_number",length = 95,nullable=false)
String accessNumber;
#Column(length=80,nullable=false)
String name;
#Column(length=140)
String description;
}
does any one know what is my problem
Note: i have this problem in my all java classes but this is one of them. the code in all class is the same of this
Edit: i build an xml file and put it in a grails project, and when i run this project, database created
Would a single #Table annotation work? I haven't tried it, I guess the Hibernate #Table might be overridden by JPA #Table.
You may also try #Index annotation on the column fields:
public class Service implements Serializable {
#Index(name="service_accessnumber")
#Column(name="access_number",length = 95,nullable=false)
String accessNumber;
#Index(name="service_name")
#Column(length=80,nullable=false)
String name;
#Index(name="service_description")
#Column(length=140)
String description;
}
i have the same problem, but i found it's solution and it works fine with me try it, it may help you
in your DataSource.groovy file in your grails project make sure that under
environment dbCreate is not equal to "update": if it is equal to "update", change
it to "create".
This works fine just try it

Categories