I have two tables (command and commandLine), i want to write in both when i insert a new command
Here is my Command Object, I use a OneToMany to map with the object CommandLine
#Entity
#Table(name = "t_commands")
public class Command {
#Id #Getter
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idCommand;
#Getter #Setter
#ManyToOne(targetEntity = User.class)
#JoinColumn(name = "idUser", nullable = false)
private User user;
#Getter #Setter
#Column(name = "commandDate")
private String date;
#Getter #Setter
#OneToMany(targetEntity = CommandLine.class, mappedBy = "idCommand")
private List<CommandLine> lines = new ArrayList<>();
public Command(User user, String date) {
this.user = user;
this.date = date;
}
public Command() {
}
and my CommandLine object, I use ManyToOne to map with the object Command
#Entity
#Table(name = "t_commandlines")
public class CommandLine {
#Id #Getter
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idCommandLine;
#Getter
#ManyToOne(targetEntity = Command.class, cascade = CascadeType.ALL)
#JoinColumn(name = "idCommand", nullable = false)
private Command idCommand;
#Getter #Setter
#ManyToOne(targetEntity = Article.class)
#JoinColumn(name = "idArticle", nullable = false)
private Article article;
#Getter #Setter
private int quantity;
public CommandLine(Article article, int quantity) {
this.article = article;
this.quantity = quantity;
}
and my CommandDAO
public class CommandDAO implements IDao<Command> {
#Override
public boolean create(Command object) {
connect().persist(object);
return true;
}
}
I use interface
public interface IDao<T> {
default EntityManager connect() {
EntityManagerFactory entityManagerFactory;
EntityManager entityManager;
entityManagerFactory = Persistence.createEntityManagerFactory("webstore");
entityManager = entityManagerFactory.createEntityManager();
return entityManager;
}
default T read(Long id){return null;}
default List<T> getAll() {return null;}
default boolean create(T object) {return false;}
default boolean update(T object) {return false;}
default boolean delete(T object) {return false;}
default Long getCount() {return 1L;}
}
I have no error, but nothing is writing in my db, I have no problem to retrieve data from the db with this structure, but impossible to write
It's not applying the changes because there is no transaction and so the persist operation is not flushed to the database.
Here a simplified example of what the code should look like:
public class CommandDAO implements IDao<Command> {
#Override
public boolean create(Command object) {
EntityManager em = connect();
try {
em.getTransaction().begin();
em.persist(object);
em.getTransaction().commit();
return true;
}
finally {
em.close();
}
}
}
Also, there is no reason to create the EntityManagerFactory every time connect() is called. The creation of the factory is quite heavy but the factory is thread safe, you can reuse it when you need it.
It makes sense to create an EntityManager every time you need it, but you have to close it when you are done with it.
Related
Spring version: 5.3.19
Hibernate: 5.4.24.Final
The problem: When trying to get the List compartments from class CriticalFlight after ScrollableData gets Cleaned up #Cleanup, the list is empty since fetch was never executed.
Custom class ScrollableData execution snipped code:
List<ENTITY> filteredEntities;
#Cleanup ScrollableData<ENTITY> scrollableData =
getScrollableData(
filter,
myMarketChecker,
additionalFilters,
staticPredicateBuilders);
filteredEntities = scrollableData.getAll();
return filteredEntities;
I loop into the list returned and try to access List compartments
then got: "org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.pros.travel.services.oandd.optimizer.alerts.entity.CriticalFlight.compartments, could not initialize proxy - no Session
"
Classes
Embeddable Class: CriticalFlightKey
#Data
#Embeddable
public class CriticalFlightKey implements Serializable
{
#DTOMapping(CriticalFlightDTO.FIELD_FLIGHTDATE)
#Convert(converter = DateToLocalDateAttributeConverter.class)
#Column(name = "FLTDATE", nullable = false)
private LocalDate flightDate;
#DTOMapping(CriticalFlightDTO.FIELD_DIM_CRRCODE)
#Column(name = "CRRCODE", nullable = false)
private String carrierCode;
#DTOMapping(CriticalFlightDTO.FIELD_DIM_FLTNUM)
#Column(name = "FLTNUM", nullable = false)
private String flightNumber;
#DTOMapping(CriticalFlightDTO.FIELD_DIM_ORGN)
#Column(name = "ORGN", nullable = false)
private String origin;
#DTOMapping(CriticalFlightDTO.FIELD_DIM_DSTN)
#Column(name = "DSTN", nullable = false)
private String destination;
}
Parent Class: CriticalFlight
#Data
#EqualsAndHashCode(of = {"id"})
#Entity
#Table(name = "OD_CRITICAL_FLIGHTS")
public class CriticalFlight implements
{
#JsonUnwrapped
#EmbeddedId
#DTOMapped
public CriticalFlightKey id;
...
....
#JsonManagedReference
#OneToMany(fetch = FetchType.EAGER)
#Fetch(FetchMode.SUBSELECT)
#JoinColumns({
#JoinColumn(name="FLTDATE", referencedColumnName="FLTDATE"),
#JoinColumn(name="CRRCODE", referencedColumnName="CRRCODE"),
#JoinColumn(name="FLTNUM", referencedColumnName="FLTNUM"),
#JoinColumn(name="ORGN", referencedColumnName="ORGN"),
#JoinColumn(name="DSTN", referencedColumnName="DSTN")
})
private List<CriticalFlightCmp> compartments = new ArrayList<>();
}
Embeddable class for child: CriticalFlightCmpKey
#Data
#Embeddable
public class CriticalFlightCmpKey implements Serializable
{
#Convert(converter = DateToLocalDateAttributeConverter.class)
#Column(name = "FLTDATE", nullable = false)
private LocalDate flightDate;
#Column(name = "CRRCODE", nullable = false)
private String carrierCode;
#Column(name = "FLTNUM", nullable = false)
private String flightNumber;
#Column(name = "ORGN", nullable = false)
private String origin;
#Column(name = "DSTN", nullable = false)
private String destination;
#Column(name = "CMPCODE", nullable = false)
private String cmpCode;
}
Child Class: CriticalFlightCmp
#Data
#EqualsAndHashCode(of = {"id"})
#Entity
#Table(name = "OD_CRITICAL_FLIGHTS_CMP")
public class CriticalFlightCmp implements IPersistable<CriticalFlightCmpKey>
{
#EmbeddedId
private CriticalFlightCmpKey id;
..
...
}
Custom class ScrollableData which uses org.hibernate.ScrollableResults to execute the query
#Slf4j
public class ScrollableData<ENTITY extends IPersistable> implements Closeable
{
private static final int SCROLLABLE_FETCH_SIZE = 10000;
private final Class<ENTITY> entityClass;
private final ScrollableResults results;
private final EntityManager entityManager;
private final List<IScrollableFilter<ENTITY>> filters = new ArrayList<>();
public ScrollableData(
Class<ENTITY> entityClass,
ScrollableResults results,
EntityManager entityManager)
{
this.entityClass = entityClass;
this.results = results;
this.entityManager = entityManager;
}
/**
* Create scrollable data from a query and entity manager session.
*
* #param entityManager Entity manager from which the query was built from.
* #param query Query to scroll on.
* #return Scrollable data
*/
static <ENTITY extends IPersistable> ScrollableData<ENTITY> fromQuery(
Class<ENTITY> entityClass,
EntityManager entityManager,
CriteriaQuery query)
{
ScrollableResults results = entityManager.createQuery(query)
.unwrap(Query.class)
.setReadOnly(true)
.setFetchSize(SCROLLABLE_FETCH_SIZE)
.setCacheable(false)
.scroll(ScrollMode.FORWARD_ONLY);
return new ScrollableData<>(entityClass, results, entityManager);
}
public List<ENTITY> getAll()
{
List<ENTITY> allEntities = new ArrayList<>();
while (next())
{
allEntities.add(get());
}
return allEntities;
}
/**
* Clears the hibernate session of any entities it's caching.
*/
public void clearSession()
{
log.debug("Clearing Session for {}", entityClass.getSimpleName());
Session hibernateSession = entityManager.unwrap(Session.class);
hibernateSession.clear();
}
/**
* Closes the scrollable results and the session contained in the entity manager.
*/
public void close()
{
clearSession();
if (results != null)
{
log.debug("Closing ScrollableResults for {}",
entityClass.getSimpleName());
results.close();
}
if (entityManager != null)
{
log.debug("Clearing EntityManager for {}", entityClass.getSimpleName());
entityManager.close();
}
}
}
I am having an issue where the Domain (child) is not getting the Business (parents) id. I have the business created and the domain but the domain does not have the business_id. Below is what I was doing originally. I then made a test path that I called which gave the same behavior unless I used the setBusiness method of the domain. Is this the expectation? Do I need to loop over the domains that are passed from a client and set the business?
Test
public void test() {
Business b = new Business();
b.setName("Test Test");
Domain d1 = new Domain();
d1.setName("Domain 1");
d1.setBusiness(b);
em.persist(b);
em.flush();
}
Code
#Entity
#Table(name = "Business")
public class Business {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#OneToMany(mappedBy="business", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Domain> domains = new ArrayList<>();
//...getters and setters
}
-
#Entity
#Table(name = "Domain")
public class Domain {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "business_id", nullable = false)
private Business business;
//...getters and setters
}
I was calling a rest service using the below JSON which then persisted the business.
{
"name": "Business Test ",
"domains": [{"name": "test domain"}]
}
#Path("business")
public class BusinesResouce {
#EJB
BusinessService service;
#Path("create")
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public void create(Business entity) {
service.persist(entity);
}
//other paths
}
-
#Stateless
public class BusinessService {
private static final String PERSISTENCE_UNIT_NAME = "edc";
#PersistenceContext(unitName = PERSISTENCE_UNIT_NAME)
private EntityManager em;
public void persist(Business entity) {
em.persist(entity);
//Do I really need to loop entity.getDomains and setBusiness?
em.flush();
}
}
I have to implementes Auditing in my aplication.. i inserting this data correctly
but i want to save all atributter from my Entity ,
Exemple, name, epigrafe, .. and olthers.
I implemented the mothod but dosent work, just dont save the atributte..
lets see..
#Entity
#EntityListeners(AuditingEntityListener.class)
#Table(name = "logradouros_historico", schema = "aud")
public class LogradourosHistorico {
#Id
#GeneratedValue
private Long id;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "id_logradouro")
private Logradouros logradouro;
#CreatedBy
private String modificadoPor;
#CreatedDate
#Temporal(TemporalType.TIMESTAMP)
private Date modifiedDate = new Date();
#Enumerated(EnumType.STRING)
private Acoes acao;
#Column(name = "nome")
private String nome; //nome do logradouro
public LogradourosHistorico() {
super();
}
public LogradourosHistorico(Logradouros logradouro, String modificadoPor,
Acoes acao) {
super();
this.logradouro = logradouro;
this.modificadoPor = modificadoPor;
this.acao = acao;
}
//getters and setters
my class entityListner
public class LogradourosEntityListener {
#PostPersist
public void prePersist(Logradouros target) {
perform(target, Acoes.INSERTED);
}
#PreUpdate
public void preUpdate(Logradouros target) {
perform(target, Acoes.UPDATED);
}
#PreRemove
public void preRemove(Logradouros target) {
perform(target, Acoes.DELETED);
}
#Transactional()
private void perform(Logradouros target, Acoes acao) {
target.getNome();
EntityManager entityManager = BeanUtil.getBean(EntityManager.class);
entityManager.persist(new LogradourosHistorico(target, acao));
}
}
my class Logradouros
#Entity
#EntityListeners(LogradourosEntityListener.class)
#Table(name = "logradouros", schema = "glb", uniqueConstraints= #UniqueConstraint(columnNames={"id_entidade", "idLogradouro"}))
public class Logradouros extends Auditable<String> implements Serializable {
private static final long serialVersionUID = 3703309412387185484L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int idLogradouro;
#Column(name = "cep_geral")
private String cepGeral;
#Column(name = "epigrafe")
private String epigrafe;
#NotNull
#Column(name = "nome")
private String nome;
#Column(name = "nome_exibicao")
private String nomeExibicao;
#JoinColumn(name = "id_entidade")
#ManyToOne(/*cascade = CascadeType.ALL*/)
private Entidades entidade;
#NotNull
#JoinColumn(name = "id_municipio")
#ManyToOne(/*cascade = CascadeType.ALL*/)
private Municipios municipio;
// gettrs and settrs
so what i did wrong because i cant get the nome of entity Logradouros
I am stuck with this error message, that appears every time I want to add a ManytoOne relationship with another entity class.
The class must use a consistent access type (either field or property). There is no ID defined for this entity hierarchy
This is my entity Transaction
#Entity
#Table(name = "CustomerTransaction")
public class CustomerTransaction implements Serializable {//this is the line with the error message
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne //This generates the problem
#JoinColumns({
#JoinColumn(name = "CUS_ID", referencedColumnName = "IDCUSTOMER") })
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
private long transactionID;
#Temporal(TemporalType.TIMESTAMP)
private Date buyDate;
public Date getBuyDate() {
return buyDate;
}
public void setBuyDate(Date buyDate) {
this.buyDate = buyDate;
}
public long getTransactionID() {
return transactionID;
}
public void setTransactionID(long transactionID) {
this.transactionID = transactionID;
}
public String getCarYear() {
return carYear;
}
public void setCarYear(String carYear) {
this.carYear = carYear;
}
public Date getTransactionDate() {
return transactionDate;
}
public void setTransactionDate(Date transactionDate) {
this.transactionDate = transactionDate;
}
private String carYear;
#Temporal(TemporalType.TIMESTAMP)
private Date transactionDate;
JPA annotation should all be placed either on fields or on accessor methods. You've placed the #Id and #GeneratedValue annotation on a field (private Long id), but #ManyToOne and #JoinColumns on a getter (public Long getId()). Move the latter on a field as well.
i had similar error but in the end, i realized #Id was referencing this package org.springframework.data.annotation.Id instead of javax.persistence.Id. i was using #MappedSuperClass approach so as soon as i corrected this, everything worked fine
You need to import #Id from "import javax.persistence.Id;"
I have an existing JPA entity ("Reference") with an ID column as its primary key that it inherits from a base class "BaseEntity" (using the #MappedSuperclass annotation on the superclass).
I also have a 1-M relationship between a Reference and another entity called Violation. Violation was previously defined with a foreign key "REFERENCE_ID" to the "ID" column of the Reference entity.
Recently, I tried to add an unrelated composite key to the Reference entity. This should not have affected the 1-M relationship between Reference and Violation. However, when I run the code in my tomcat server, I see the following stack trace:
Caused by: org.hibernate.AnnotationException: referencedColumnNames(ID) of org.qcri.copydetection.sdk.metastore.entity.Violation.reference referencing org.qcri.copydetection.sdk.metastore.entity.Reference not mapped to a single property
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:205) ~[hibernate-annotations-3.5.6-Final.jar:3.5.6-Final]
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:110) ~[hibernate-annotations-3.5.6-Final.jar:3.5.6-Final]
at org.hibernate.cfg.AnnotationConfiguration.processEndOfQueue(AnnotationConfiguration.java:541) ~[hibernate-annotations-3.5.6-Final.jar:3.5.6-Final]
at org.hibernate.cfg.AnnotationConfiguration.processFkSecondPassInOrder(AnnotationConfiguration.java:523) ~[hibernate-annotations-3.5.6-Final.jar:3.5.6-Final]
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:380) ~[hibernate-annotations-3.5.6-Final.jar:3.5.6-Final]
at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1206) ~[hibernate-core-3.5.6-Final.jar:3.5.6-Final]
at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1459) ~[hibernate-entitymanager-3.5.6-Final.jar:3.5.6-Final]
at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:193) ~[hibernate-entitymanager-3.5.6-Final.jar:3.5.6-Final]
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:1086) ~[hibernate-entitymanager-3.5.6-Final.jar:3.5.6-Final]
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:685) ~[hibernate-entitymanager-3.5.6-Final.jar:3.5.6-Final]
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:73) ~[hibernate-entitymanager-3.5.6-Final.jar:3.5.6-Final]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:268) ~[spring-orm-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310) ~[spring-orm-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
... 39 common frames omitted
Here is the code for the 3 classes involved:
#Entity
#Table(name = "REFERENCE")
#XmlRootElement
#XmlAccessorType(XmlAccessType.PROPERTY)
#IdClass(Reference.ContextualName.class)
public class Reference extends BaseEntity {
#Column(name= "LOCATION", unique=true)
#XmlElement
private String location;
#Id
#AttributeOverrides({
#AttributeOverride(name = "name", column = #Column(name = "NAME")),
#AttributeOverride(name = "account", column = #Column(name = "ACCOUNT_ID"))
})
#Column(name = "NAME")
#XmlElement
private String name;
#ManyToOne(optional=false)
#XmlTransient
#JoinColumn(name = "ACCOUNT_ID", referencedColumnName = "ID")
private Account account;
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Reference() {}
public Reference(String name) {
setName(name);
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public Account getAccount() {
return this.account;
}
public void setAccount(Account account) {
this.account = account;
}
#Embeddable
private class ContextualName implements Serializable {
private static final long serialVersionUID = -3687389984589209378L;
#Basic(optional = false)
#Column(name = "NAME")
#XmlElement
private String name;
#ManyToOne(optional=false)
#XmlTransient
#JoinColumn(name = "ACCOUNT_ID", referencedColumnName = "ID")
private Account account;
ContextualName() {}
}
}
#MappedSuperclass
#XmlAccessorType(XmlAccessType.FIELD)
public abstract class BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID")
#XmlElement
private Long id;
#Basic(optional = true)
#Column(name = "CREATED", insertable = false, updatable = false, columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
#Temporal(TemporalType.TIMESTAMP)
#XmlElement
private Date creationDate;
protected BaseEntity() {}
public Long getId() {
return id;
}
public void setId(Long id) {
if(this.id==null) {
this.id = id;
} else if (this.id!=id) {
throw new IllegalArgumentException("Cannot change the id after it has been set, as it is a generated field.");
}
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
if(this.creationDate==null) {
this.creationDate = creationDate;
} else if (this.creationDate!=creationDate) {
throw new IllegalArgumentException("Cannot change the creation-date after it has been set, as it is a generated field.");
}
}
}
#Entity
#Table(name = "VIOLATION")
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Violation extends BaseEntity {
#ManyToOne (optional=false, fetch= FetchType.EAGER)
#JoinColumn(name = "REFERENCE_ID", referencedColumnName = "ID")
private Reference reference;
#ManyToOne (optional=false, fetch= FetchType.EAGER)
#JoinColumn(name = "SUSPECT_ID", referencedColumnName = "ID")
private Suspect suspect;
#ManyToOne (optional=false, fetch= FetchType.EAGER)
#XmlTransient
#JoinColumn(name = "SEARCH_ID", referencedColumnName = "ID")
private Search search;
#Basic(optional = false)
#Column(name = "SCORE")
#XmlElement
private double score;
public Violation() {}
public Violation(Search search, Reference ref, Suspect sus, double score) {
this.search = search;
this.reference = ref;
this.suspect = sus;
this.score = score;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public Reference getReference() {
return reference;
}
public void setReference(Reference reference) {
this.reference = reference;
}
public Suspect getSuspect() {
return suspect;
}
public void setSuspect(Suspect suspect) {
this.suspect = suspect;
}
public Search getSearch() {
return search;
}
public void setSearch(Search search) {
if(this.search!=null && this.search!=search) {
this.search.removeViolation(this);
}
this.search = search;
if(search!=null) {
if(!search.getViolations().contains(this)) {
search.addViolation(this);
}
}
}
}
To cut a long story short, I'm totally confused how to go about adding a composite key to an existing (legacy) entity that already has an ID column. I can't remove the ID column, nor can I change the 1-M relationship between Reference and Violation. I can't for the life of me understand the error message because the "REFERENCE_ID" foreign key column of the Violation entity is being mapped to a single "ID" column of the Reference entity.
Many thanks in advance!