Saving value in Hibernate to another table than entity table - postgresql

I have two tables bo_operator and hist_bo_operator_password. In bo_operator the id column is foreign key to hist_bo_operator_password and I can have many the same operator_id in hist_bo_operator_password and only one id in bo_operator.
My entity:
#Entity
#Table(name="bo_operator")
public class Operator implements Serializable
and that's how I am getting values from hist_bo_operator_password:
#ElementCollection
#CollectionTable(name="hist_bo_operator_password", joinColumns=#JoinColumn(name="id_operator"))
#Column(name="password")
public List<String> oldPasswords = new ArrayList<String>();
but when I'm trying to get only one value by:
#ElementCollection
#CollectionTable(name="hist_bo_operator_password", joinColumns=#JoinColumn(name="id_operator"))
#Column(name="password")
public String oldPassword;
I'm getting error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Illegal attempt to map a non collection as a #OneToMany, #ManyToMany or #CollectionOfElements: local.vlex.operator.model.Operator.oldPassword
and all I want to do is makeing an insert into hist_bo_operator_password by
operator.setOldPassword(oldPassword);. I think the problem is that it doesn't know which password take if there is many values for the same id.
How to achive it?
#Edit
I also tried:
#Table(name="bo_operator")
#SecondaryTable(name = "hist_bo_operator_password",pkJoinColumns=#PrimaryKeyJoinColumn(name="id_operator", referencedColumnName="id"))
I even found ORDER BY so:
#Column(name="password", table="hist_bo_operator_password")
#OrderBy("data_ins")
public String oldPassword;
but seems like there is no #Limit or something like this in JPA and I still have many values to the same id which cause error:
org.hibernate.HibernateException: Duplicate identifier in table for: [local.vlex.operator.model.Operator#1]

As you described at the first sentence you have one-to-many relationship
#ElementCollection
#CollectionTable(name="hist_bo_operator_password", joinColumns=#JoinColumn(name="id_operator"))
#Column(name="password")
#OrderBy("data_ins")
public List<String> oldPasswords = new ArrayList<String>();
Then add necessary getter
Optional<String> getPassword() {
return oldPasswords.size() > 0
? Optional.of(oldPasswords.get(0))
: Optional.empty();
}
And setter
void setPassword(String password) { // or maybe addPassword?
oldPasswords.add(password);
}

Why don't you create entity of hist_bo_operator_password?
Then you could have List of that entities (instead of just String List) and just add another object to List and save entity Operator.

Related

Why does EntityFramework populate my NotMapped field with a trash value

Hello i am retrieving a IEnumerable<Something> using Entity Framework and this Something has an IEnumerable<SomethingElse> property that has the attribute [NotMapped] over it.
Why does entity framework populate this IEnumerable<SomethingElse> field with some unknown object that is neither null but can't be interogated with Linq throwing the following exception:
System.ArgumentNullException: 'Value cannot be null. (Parameter 'source')'
public class Something
{
[NotMapped]
public IEnumerable<SomethingElse> Items{get;set;}
}
public struct SomethingElse
{
//some fields
}
Insertion:
When i insert the list some elements have the NotMapped field null, while others not:
List<Something> toBeInserted=new List<Something>{ new Something{Items=null},new Something{Items=new[]{ new SomethingElse{}}};
//dbcontext insert the list....
Retrieval
List<Something>somethings=(await this.[SomeDBContext].Somethings).ToList();
Now at retrieval some elements have the NotMapped property null as it should be,while someothers have this weird non-null IEnumerable<SomethingElse>d_6that throws exception on any Linq interogation:
var weirdElement=somethings.First();
weirdElement.Items.Count(); //throws
weirdElement.Items.Any();throws
P.S I have checked this post regarding computed properties and it says: Materialize the list when you fetch it from the database to resolve the computed properties.That is what i have done.
I issue (await this.DBContext.Somethings).ToList() to no avail.
Some Something's still have their IEnumerable<SomethingElse> property not null.
Later Edit
This is a picture with what the
not mapped property of the element looks like:
I am computing the IEnumerable<SomethingElse> using an extension method:
public class Extension
{
public static IEnumerable<SomethingElse> Compute(this IEnumerable<SomethingSomethingElse> someOthers){}
}
The name of the type of the field IEnumerable<SomethingElse> is <Compute>d_6

Spring Data JPA + JpaSpecificationExecutor + NamedEntityGraph

I have two Entities. Parent and Child.
#Entity
public class Parent {
#Id
#Column(name = "PARENT_ID")
private BigInteger id;
#Column(name = "FIRST_NAME")
private String firstName;
#Column(name = "LAST_NAME")
private String lastName;
}
#Entity
#NamedEntityGraph(name = "Child.parentObj", attributeNodes = #NamedAttributeNodes("parentObj"))
public class Child{
//blah blah blah
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name="PARENT_ID")
Parent parentObj;
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name="CHILD_ID")
Set<Address> address
//blah blah blah
}
ChildRepository.java
public interface ChildRepository extends JpaRepository<T, ID>, JpaSpecificationExecutor<T>{
#EntityGraph(value="Child.parentObj")
public List<Child> findAll(Specification<Child> spec);
}
I am trying to find child entities by criteria and it should always have parent.
I am getting exception that it is trying to find parentObj in Address table.
Caused by: org.hibernate.QueryException: could not resolve property: parentObj of: com.xxx.Address [..]
I found this link and tried solution given by Joep but same error.
Spring Data JPA + JpaSpecificationExecutor + EntityGraph
what am I missing. I am not able to understand why/how i limit to look for parentObj in just Child Object as Address has no reference to Parent.
I am doing search by Address.street.
I have tried ad-hoc entity graph too. exception:
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.QueryException: could not resolve property: parentObj of: com.xxx.Address
Caused by: org.hibernate.QueryException: could not resolve property: parentObj of: com.xxx.Address
at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:83)
at org.hibernate.persister.entity.AbstractPropertyMapping.toType(AbstractPropertyMapping.java:77)
at org.hibernate.persister.entity.AbstractEntityPersister.toType(AbstractEntityPersister.java:1978)
at org.hibernate.hql.internal.ast.tree.FromElementType.getPropertyType(FromElementType.java:367)
at org.hibernate.hql.internal.ast.tree.FromElement.getPropertyType(FromElement.java:500)
at org.hibernate.engine.query.spi.EntityGraphQueryHint.getFromElements(EntityGraphQueryHint.java:95)
at org.hibernate.engine.query.spi.EntityGraphQueryHint.toFromElements(EntityGraphQueryHint.java:68)
at org.hibernate.hql.internal.ast.HqlSqlWalker.processQuery(HqlSqlWalker.java:676)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:665)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.collectionFunctionOrSubselect(HqlSqlBaseWalker.java:4905)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.comparisonExpr(HqlSqlBaseWalker.java:4606)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2104)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2029)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2029)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.whereClause(HqlSqlBaseWalker.java:796)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:597)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:301)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:249)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:278)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:206)
... 60 more
I wanted to find Child entries by criteria search and get ParentObj for each child. I wanted to do join and not individual select for Parent. I was trying to solve that by using EntityGraph but it didn't work. As #EKlavya pointed out Specification and EntityGraph don't work togather.
The way I solved was:
root.fetch("parentObj", JOIN.LEFT);
in my toPredicate method. this will get Child entity with Parent in 1 query.
You are using Child.parentObj as Entity graph name but you named the entity graph as Child.parent. Use
#EntityGraph(value="Child.parent")
Without #NamedEntityGraph
we can define an ad-hoc entity graph, without #NamedEntityGraph just use
#EntityGraph(attributePaths = {"parentObj"})
Update:
Entity graph and specification both are not working together.
There is a way to solve this. Don't do eager for parent fetch child only first then make a list of child ids from child's and get parents using in clause query using child ids. Total only 2 queries needed. If you want to solve this using 1 query use DSL to do raw query.

Error: Parameter value did not match expected type

I am trying to retrieve a USER from my database using the ID in the WHERE clause. However I am receiving an error and my program is failing.
This is the error I'm receiving when I run my program:
ERROR [org.jboss.as.ejb3.invocation] (default task-19)
JBAS014134: EJB Invocation failed on component CustomerServiceBeanImpl
for method public abstract package.name.entity.ICustomer
package.name.bean.CustomerServiceBean.getCustomerById(long):
javax.ejb.EJBException: java.lang.IllegalArgumentException:
Parameter value [19533] did not match expected type [package.name.entity.User (n/a)]
Note: [19533] is a test value I used.
This is the method that is having the error in the CustomerServiceBeanImpl.java:
#Override
public Customer getCustomerById (final long id)
{
return Customer.getById (this.em, id);
}
This is the method that's being called by the component CustomerServiceBeanImpl:
public static Customer getById (final EntityManager em, final long id)
{
for (final Customer c : em.createNamedQuery ("Customer.getById", Customer.class)
.setParameter ("id", id).setMaxResults (1).getResultList ())
{
return c;
}
return null;
}
The name query is this:
#NamedQuery (name = "Customer.getById",
query = "SELECT o FROM gnf.Customer o WHERE o.user = :id")
In the Customer.java class itself the relevant column is this one:
#ManyToOne (fetch = FetchType.LAZY)
#JoinColumn (name = "user_id")
private User user;
Doing a quick check of my ERD the "id" column in my "customer" table has a data type of BIGINT. However I'm not sure if that matters. (PostgreSQL database by the way.)
How can I fix this error?
The WHERE clause in your named query seems to be the problem. The attribute user in your Customer.class is of type User and your query expects it to be a type compatible to long.
...
Parameter value [19533] did not match expected type [package.name.entity.User ...
So if you need more help on this it would be great to see the complete entities User and Customer.
It is happening because in your database the parameter will be a #oneToOne object and you have to call the id inside the Object so you have to give the query as following :
"select user from User user where user.customer.id=:param"

How to use composite entity in spring-data-cassandra?

I am setting up spring-data-cassandra for the first time and have a class like so:
#Table(value = "contact")
public class Contact {
#Id
UUID id;
...
Location Location;
...
public void setLocation(Location location) {
this.location = location;
}
public Location getLocation() {
return location;
}
}
This gives me an error when starting up:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mySQLTransactionRepository': Invocation of init method failed; nested exception is org.springframework.data.cassandra.mapping.VerifierMappingExceptions: com.foo.backend.core.Location:
Cassandra entities must have the #Table, #Persistent or #PrimaryKeyClass Annotation
....
Coming from a spring-data-jpa background simply annotating Location with #Embeddable has previously been enough. It looks like this doesn't work with spring-data-cassandra. How do I use compound entities with spring-data-cassandra?
Will have to annotate location as #Transient and do some serialization myself? I tried to annotate my class with #Persistent but was getting an error about PrimaryKey missing on Location. I can't comprehend why a primary key would be necessary...
Because of the non-relational details of Cassandra, you are going to find it doesn't work like JPA.
There are no joins in Cassandra, so embedding another table as as an attribute of a table is not allowed.
Embeddable types are not supported at this time. If you would like to elaborate on the feature request, please create a Jira for SDC*.
Thanks.

Entity bean 3.0 composite key issue

1: I have a table as shown below :
Name Null? Type
ATX_ID NOT NULL NUMBER(16)
ATX_GLM_CD NOT NULL NUMBER(5)
ATX_CRDR_FLG NOT NULL VARCHAR2(1)
ATX_AMT NOT NULL NUMBER(15,2)
ATX_STTS NOT NULL VARCHAR2(1)
ATX_TCM_ID NOT NULL NUMBER(16)
ATX_TXN_DT NOT NULL DATE
ATX_CRTE_BY NOT NULL VARCHAR2(30)
ATX_CRTE_DT NOT NULL DATE
The columns ATX_ID,ATX_GLM_CD and ATX_CRDR_FLG form a composite primary key.
2: I have created an entity bean class for the above table as follows :
#Entity
public class AcctngTxns implements Serializable {
private BigDecimal atxAmt;
private String atxStts;
private BigDecimal atxTcmId;
private Date atxTxnDt;
private String atxCrteBy;
private Date atxCrteDt;
#EmbeddedId
private AcctngTxnsPK acctngTxnsPK;
public AcctngTxns() {
//super();
}
/*getters and setters*/
}
#Embeddable
public class AcctngTxnsPK implements Serializable {
private long atxId;
private long atxGlmCd;
private String atxCrdrFlg;
private static final long serialVersionUID = 1L;
public AcctngTxnsPK() {
//super();
}
/*necessary overrides*/
}
3: /orm.xml/
http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
version="1.0">
4: /persistence.xml/
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
DataSource
com.nseit.ncfm2.data.ejb.entity.AcctngTxns
5: While accessing the entity bean via a session bean,I am getting the following exception :
<[weblogic.servlet.internal.WebAppServletContext#1a1bc8f - appName: '_auto_generated_ear_', name: 'AWebApp', context-path: '/AWebApp', spec-version: '2.5'] Servlet failed with Exception
javax.ejb.EJBException: EJB Exception: ; nested exception is:
org.apache.openjpa.persistence.ArgumentException: Fields "com.nseit.ncfm2.data.ejb.entity.AcctngTxns.acctngTxnsPK" are not a default persistent type, and do not have any annotations indicating their persistence strategy. If you do not want these fields to be persisted, annotate them with #Transient.
at weblogic.ejb.container.internal.RemoteBusinessIntfProxy.unwrapRemoteException(RemoteBusinessIntfProxy.java:105)
at weblogic.ejb.container.internal.RemoteBusinessIntfProxy.invoke(RemoteBusinessIntfProxy.java:87)
at $Proxy127.gottaAccessEntity3(Unknown Source)
at jsp_servlet.__result.jspService(_result.java:115)
at weblogic.servlet.jsp.JspBase.service(JspBase.java:34)
Truncated. see log file for complete stacktrace
org.apache.openjpa.persistence.ArgumentException: Fields "com.nseit.ncfm2.data.ejb.entity.AcctngTxns.acctngTxnsPK" are not a default persistent type, and do not have any annotations indicating their persistence strategy. If you do not want these fields to be persisted, annotate them with #Transient.
at org.apache.openjpa.persistence.PersistenceMetaDataFactory.validateStrategies(PersistenceMetaDataFactory.java:399)
at org.apache.openjpa.persistence.PersistenceMetaDataFactory.load(PersistenceMetaDataFactory.java:205)
at org.apache.openjpa.meta.MetaDataRepository.getMetaDataInternal(MetaDataRepository.java:474)
at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:294)
at org.apache.openjpa.kernel.BrokerImpl.newObjectId(BrokerImpl.java:1114)
Truncated. see log file for complete stacktrace
7: Certainly,I do not want the primary key fields to be updated.
8: I tried to figure out the implementation of the below points mentioned in JPA documentation :
A composite primary key must be represented and mapped to multiple fields or properties of the entity class, or must be represented and mapped as an embeddable class.
If the class is mapped to multiple fields or properties of the entity class, the names and types of the primary key fields or properties in the primary key class must match those of the entity class.
8: Please help me in resolving the issue.
Thanks !
I found a solution by trial-and-error method. It seems that with JPA 1.0,it is necessary to mention the embedded-id in orm.xml file as follows :
Thanks.