#OneToMany and #ManyToOne in MongoDB and JPA -EISOneToOneMapping cannot be cast to - mongodb

We're trying to do a #OneToMany and #ManyToOne relation with EclipseLink/MongoDB:
The #OneToMany declaration looks like this:
#Entity
#NoSql(dataType = "ServiceCatalog", dataFormat = DataFormatType.MAPPED)
public class ServiceCatalog {
#Id
#GeneratedValue
#Field(name = "_id")
private String id;
#OneToMany
private List<ServiceCatalogNeedCategory> serviceCatalogNeedCategories;
…
On the other side, the #ManyToOne declaration:
#Entity
#NoSql(dataType = "NeedCategory", dataFormat = DataFormatType.MAPPED)
public class ServiceCatalogNeedCategory {
#Id
#GeneratedValue
#Field(name = "_id")
private String id;
#Field(name = "title")
private String Title;
#ManyToOne(fetch=FetchType.LAZY)
private ServiceCatalog serviceCatalog;
...
The above configuration leads to the following error:
org.eclipse.persistence.eis.mappings.EISOneToOneMapping cannot be cast to org.eclipse.persistence.mappings.OneToOneMapping
We really need to be able to resolve both directions.
Cheers
Michael

Please include the full exception stack.
There was an issue fixed in the 2.6 dev stream for NoSQL, it may be related.
https://twitter.com/j_b_sutherland/status/339727557928833025
What version are you using, I would try at least 2.5, or a recent 2.6 dev build.

You missed the MappedBy Annontation on the OneToMany side.
See http://www.objectdb.com/api/java/jpa/OneToMany
[edit]
OMG it's NOSQL sorry.
ORM are no more what they used to be..
I don't know so, but if you're really using JPA API then it might be the trick

Related

Querying revisions of nested object using spring-data-envers

I'm trying to implement entity auditing in my Java Spring Boot project using spring-data-envers. All the entities are being created as they should, but I've come up against a brick wall when executing the query.
parentRepository.findRevisions(id).stream().map(Parent::getEntity).collect(Collectors.toList());
During this select the repository is supposed to fetch info also from the child entity, instead I get unable to find <child object> with {id}.
According to my experiments categoryId is being searched in the Category_Aud table, instead of the actual table with desired data.
Code snippets:
#Data
#Entity
#Audited
#NoArgsConstructor
public class Parent {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Enumerated(EnumType.STRING)
private Status status;
#Enumerated(EnumType.STRING)
private Type requestType;
private String fullName;
#ManyToOne
#JoinColumn(name = "child_id")
private Child child;
}
#Data
#Entity
#Audited
#NoArgsConstructor
public class Child {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String description;
}
I've extended Parent with RevisionRepository
#Repository
public interface ParentRepository extends RevisionRepository<Parent, Long, Long>, JpaRepository<Parent, Long>
And annotated my SpringBootApplication entry class with:
#EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class)
I couldn't find any explanation for this so far, how can make parentRepository get what I need?
The underlying problem here is that the reference from a versioned entity isn't really properly defined. Which variant of the reference should be returned? The one at the start of the version you use as a basis, the one at the end? The one that exists right now?
There are scenarios for which each variant makes sense.
Therefor you have to query the revisions yourself and can't simply navigate to them.

Repository findIn confusion

My database has an Exchanges class which contains a list of CurrencyPairs.
Is it possible to use to use a Repository method to directly obtain a CurrencyPair which matches on name within a given Exchange? I'm thinking of something like
CurrencyPairDbo findByExchangeNameAndCurrencyPairIn(...)
but I can't see quite how to tie it all together. Or do I need to write a custom query for this? And does this need to be in the ExchangeRepository or the CurrencyPairRespository?
#Entity()
#Table(name = "Exchanges")
public class ExchangeDbo {
#Id #GeneratedValue
#Getter private Long id;
#Getter private String exchangeName;
#OneToMany(mappedBy = "exchange",
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.EAGER)
#BatchSize(size=100)
#Getter private List<CurrencyPairDbo> listCurrencyPair = new ArrayList<>();
...
}
#Entity()
public class CurrencyPairDbo {
#Id #GeneratedValue
#Getter private Long id;
#Column(unique=true)
private String currencyPair;
#ManyToOne(fetch=FetchType.EAGER)
#Getter private ExchangeDbo exchange;
...
}
Edit:
I'm thinking it's not Find...In that I want at all. I think that something like:
List<CurrencyPairDbo> x = exchangeRepository.findByExchangeNameLowercaseAndListCurrencyPairCurrencyPair(exchangeName.toLowerCase(), currencyPair);
might work, except that in returns an Exchange object and a:
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [biz.ianw.coindatabase.database.ExchangeDbo] to type [biz.ianw.coindatabase.database.CurrencyPairDbo]
This, in the currency pair repository, seems to do the job.
I added a lower case field for matching purposes and an index for efficiency.
CurrencyPairDbo findByExchangeExchangeNameLowercaseAndCurrencyPairNameLowercase( String exchangeName, String currencyPair );

Moving #OneToMany from Entity to Embeddable

It's my first post, so I hope I do it the right way. I have searched two days for an equivalent Problem, but did not find anything.
Here is what I did:
We have an Entity, that contains (beside others) the folowing fields:
#Entity
#Access(AccessType.FIELD)
#Table(name = "component")
public class Component {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
.
.
#OneToMany
#JoinTable(name = "component_dokumentation",
joinColumns = #JoinColumn( name = "component_id" ),
inverseJoinColumns = #JoinColumn(name = "dokumentation_id"))
private Set<FileType> dokumentation;
private Long keySisMf = 0L;
.
.
// Getter and Setter and stuff
}
After one year of usage we have found out, that our Entity became too big and that we have to use DTO Objects to transfer data to the Client, modify them and return them to the Server. For this purpose we modelled an embeddable Entity ComponentAttributes.
So right now it Looks like:
#Entity
#Access(AccessType.FIELD)
#Table(name = "component")
public class Component {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
.
.
#Embedded
private ComponentAttributes componentAttributes;
.
.
}
#Embeddable
#Access(AccessType.FIELD)
public class ComponentAttributes {
private static final long serialVersionUID = 1L;
#OneToMany
#JoinTable(name = "component_dokumentation",
joinColumns = #JoinColumn( name = "component_id" ),
inverseJoinColumns = #JoinColumn(name = "dokumentation_id"))
private Set<FileType> dokumentation;
private Long keySisMf = 0L;
.
.
// Getter and Setter and stuff
}
We did not change anything in the Database. We have encountered Problems in setting values for the set documentation. The field keySisMf is not a Problem. The Problems are just related to the documentation (I must add that FileType is just a Basic Entity consisting of an id and several Strings, so nothing Special). Getting the values and transfering them to the Client is fast and correct. Telling the Server to Change keySisMf is not a Problem. Telling the Server to add or remove a FileType instance simply does not work. No Errors but no changes.
We have logged the JPA generated SQL and there is no SQL generated for component.getComponentAttributes().setDokumentation(fileSet).
We use a Glassfish 4.1.1 Server with an ORACLE Database. Did I miss something when moving dokumentation from Component to ComponentAttributes????
Thanks for your help and patience.
Chris

how to develop JPA bi-directional entities in spring toot

I am new to spring boot and jpa/hibernate, please bear my inaccurate usage of the terminologies.
I have two entities: book and address. A book is published in a certain city which is stored in "address", a "address" can publish multiple books.
The DB schema for book is: id, name, author, price, addressid
schema for address: addressid, addressCountry, addressCity
The entity for book:
#Entity
#Table(name = "test_book")
public class Book implements Serializable {
private static final long serialVersionUID = 8025948150436422040L;
#Id
long id;
#Column(name = "name")
String name;
#Column(name = "author")
String author;
#Column(name = "price")
long price;
#ManyToOne
#JoinColumn(name = "addressid")
private Address address;
...//getter and setter
The entity for address
#Entity
#Table(name = "test_address")
public class Address implements Serializable{
private static final long serialVersionUID = -3541059157210384355L;
#Id
#Column(name= "addressid")
private long addressId;
#Column(name="addresscountry")
private String addressCountry;
#Column(name="addresscity")
private String addressCity;
#OneToMany(mappedBy = "address")
private Collection<Book> books;
...//getter setter
But when I call the Restful service, I get infinite loop...
[{"id":11,"name":"Java Book","author":"Jame Gosling","price":100,"address":{"addressId":1,"addressCountry":"China","addressCity":"Shanghai","books":[{"id":11,"name":"Java Book","author":"Jame Gosling","price":100,"address":...
I did some search. And my request is:
when I search a book, I can get the information: id, name, author, price, address..
And also I can query a address to get all the books the city published.
When I add Json Annotation #JsonManagedReference in address and #JsonBackReference in book entity, I can query book but cannot get address information.
Could you please help how to solve the problems? Thank you very much.
You can ignore the #JsonIgnore on getter for books. This will exclude the Collection<Book> books property from serialization the Address.
Link : JacksonAnnotations - Faster XML Wiki
Example:
#JsonIgnore
public Collection<Book> getBooks() {
...
}
#JsonIgnore
The Jackson annotation #JsonIgnore is used to tell Jackson to ignore a
certain property (field) of a Java object. The property is ignored
both when reading JSON into Java objects, and when writing Java
objects into JSON.
In your case this is happening as there is bidirectional relationship and so it will go into loop. To stop this you need to provide JsonIgnore
And so your code will be like :
-> The entity for address
#Entity
#Table(name = "test_address")
public class Address implements Serializable{
private static final long serialVersionUID = -3541059157210384355L;
#Id
#Column(name= "addressid")
private long addressId;
#Column(name="addresscountry")
private String addressCountry;
#Column(name="addresscity")
private String addressCity;
#OneToMany(mappedBy = "address")
#JsonIgnore
private Collection<Book> books;

JPA JoinColumn does not work

I have started with an example from a book. It was really a dummy oriented one and I am having a problem with the code the book gave.
Here is the code;
#Entity
public class Customer {
#Id
#GeneratedValue
private Long id;
private String firstName;
private String lastName;
private String email;
#OneToOne (fetch = FetchType.LAZY,
cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
#JoinColumn(name = "address_fk")
private Address address;
//getter, setter, Constructor
--//-------------------------------------
#Entity
public class Address {
#Id #GeneratedValue(strategy = GenerationType.AUTO)
private String id;
private String city;
private String street;
private String number;
In here it is complaining on the JoinColumn annotation. It says the column address_fk is not found.
Is this an IDE related issue? Am I missing something?
Edit : No table yet created in the DB. I am expecting them to be seen on the DB automatically by my persistence.xml
<property name="eclipselink.ddl-generation" value="create-tables"/>
Using #JoinColumn annotation to specify foreign column name to be address_fk instead of default address_id is fine.
What likely does not to work is #GeneratedValue with String. According specification only integral types as generated primary keys are portable.