I have a Java class that is mapped to a database table using JPA. Inside this class I have a List<Code> that I need to store in database.
So the Code class is not mapped into Hibernate. Is there a way to Serialize the List<Code> without mapping the Code class into Hibernate? Thanks in advance.
Error Message:
org.hibernate.exception.SQLGrammarException: could not insert collection [com.app.Account.codes#2]
Problem is that I'm getting error when Hibernate attempts to Serialize my List.
#Entity
#Table (name="account", catalog="database1")
public class Account{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column (name = "id")
private String id
#Column (name = "type")
private String type;
#CollectionOfElements
#Column (name = "codes")
List<Code> codes;
...
...
}
public class Code implements Serializable{
//This is a basic POJO that is not mapped into Hibernate. I just want this object
//to be stored in database.
}
You need to annotate the codes field with #Lob, not with #CollectionOfElements.
See http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#d0e6099 and the following paragraph.
This is a very fragile way of persisting a list of objects, though, because it uses binary serialization, which might quickly become non-backward compatible if the list or the Code class changes. It's also impossible to query or inspect using database tools.
I would rather map the Code class as an entity or as an embeddable.
Related
I have a custom POJO on which I am mapping the database records using JOOQ .fetchInto(TestClassDto.class). Most of the fields in my POJO are exactly similar to a database table's columns. However, there are a few that are different, therefore, I added java persistence and used #Column to explicitly map such columns on my POJO as described here.
Unfortunately, this is not working if I use #Column on a few specific fields. Only the fields that are annotated with #Column are mapped and the rest are ignored and set Null even though they are similar to the table column name and should be mapped implicitly.
Could you give me a hint if I am missing anything?
Sample POJO:
#Getter
#Setter
public class TestClassDto {
#Column(name = "field_AB_XYZ") // explicit mapping is required, thus need #Column
private Long myfieldAB;
/* Here, mapping could be implicitly done without using #Column because
** database column name and POJO property is same but it stays empty if I
** ignore #Column */
#Column(name = "hello_world")
private Long helloWorld;
}
Lastly, If I completely remove #Column from POJO's properties, helloWorld property is filled (implicitly) but myfieldAb remains NULL (because mapping is not found as expected).
Below is sample query:
dslContext.select()
.from(SOMETHING)
.where(SOMETHING.NAME.eq("Something"))
.fetchInto(TestClassDto.class)
As of jOOQ 3.15, you either have to annotate
all of your attributes...
none of your attributes...
... with the #Column annotation. There's a pending feature request to mimick JPA more closely and make the #Column annotation optional for some attributes: https://github.com/jOOQ/jOOQ/issues/4586.
In the meantime, instead of using those JPA annotations, you could add auxiliary getters/setters for your column:
public void setFieldAbXyz(Long v) {
this.myfieldAB = v;
}
public Long getFieldAbXyz() {
return myfieldAB;
}
I have an entity with two Embedded classes of the same type and which one has an ElementCollection of the same type two. The business logic is apparently correct, but I am experiencing some problems with lack of knowledge in JPA, I guess.
Let's check my classes:
#Entity
public class Etapa extends EntidadeBase {
#Embedded
private CronogramaDeDesembolso cronogramaDeReceita;
#Embedded
private CronogramaDeDesembolso cronogramaDeDespesa;
}
#Embeddable
public class CronogramaDeDesembolso {
#ElementCollection
private List<Parcela> parcelas;
}
I am receiving the following error log.
Caused by: org.hibernate.HibernateException: Found shared references
to a collection:
nexxus.convenioestadual.dominio.planodetrabalho.etapa.Etapa.cronogramaDeReceita.parcelas
Do you guys have any clue of what is wrong and how can I fix it?
EDIT:
Due comments I did this edit and it do not worked too
#Entity
public class Etapa extends EntidadeBase {
#Embedded
#AttributeOverride(name = "parcelas", column = #Column(name = "parcelasReceita"))
private CronogramaDeDesembolso cronogramaDeReceita;
#Embedded
#AttributeOverride(name = "parcelas", column = #Column(name = "parcelasDespesa"))
private CronogramaDeDesembolso cronogramaDeDespesa;
}
Is there any reason why you have decided to use this structure ? Typically when converting an object to an RDBMS you would need to model the relationships. When you use an embeddable it will add the column (or columns) associated with it to the table. So when you do this normally (not collections) it is fine.
When you do a collection it runs into issues. Mainly there is no way to represent a collection in a single row (since this is an entity you could have many of them so effectively for each object you only have one row) & one column. So when you represent a collection you actually have to have a second table with a column referencing it back to the first. It's really the opposite thinking of a normal object. The collection entries need to know what collection they were associated with instead of the collection being knowledgeable of its entries.
So in some POJO you could have and these....
MyListObject {
//Some implementation of things you want to collect
}
MyClass {
List<MyListObject> myListObject;
}
But to model this in JPA you would need to have these represented by two tables.
Your object that will be in the list.
#Entity
MyListObject {
#ManyToOne
#JoinColumn(name = "MY_CLASS_KEY")
private MyClass myClass;
}
Your object/entity that will have the list.
#Entity
MyClass {
#Id
#Column(name = "MY_CLASS_KEY")
private Long myClassKey;
#OneToMany(mappedBy = "myClass")
private List<MyListObject> myString;
}
I hope this helps.
A quick search on Google turned up this in StackOverflow:
JPA Multiple Embedded fields
It would seem as though you have to do some explicit annotation overriding over the fields within the embeddable class. There are some code examples in the linked answer as well that should give you a good idea of where to go.
Cheers,
I have an indexed entity, like below :
#MappedSuperclass
public static class Model{
#Id
#GeneratedValue(strategy=GenerationType.Identity)
private Integer id;
private boolean isDeleted;
}
and the indexed class is :
#Entity
#Table("USERS")
#Indexed
public class ProductModel extends Model{
#Field
private String name;
//getters & setters
}
Well, when I do a research on ProductModel, I get the value of the flag isDeleted while its not annotated with #Field.
I'm asking if this is a normal behavior, does Hibernate-search Index the whole Object Or does it fetch the missing data from data base, I need an explanation for this behavior please.
Hibernate Search only stores in the index the fields you declare explicitly (more precisely, it indexes by default and you can ask Hibernate Search to store it by adding the store option to your #Field annotation).
What you observe is that Hibernate Search hydrates the objects with the information of the database after having performed the search. This is one of the main interest in using Hibernate Search: the objects returned are managed entities.
Lets say I have a class in which i generate a DB with some keys, now I want to have an other class in which i use for example the "key123" as I named it in the following, how can I do that? Is that possible to just copy&paste the #Basic and public String key123 in that other class? Will that Basic annotation fetch it from the DB into that class? even when they both have different packages?
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic
#XmlAttribute
#XmlID
private Long id;
#Basic
private String someotherKey;
#Basic
public String key123;
You probably need to use the MVC model of development
Class Keys - the DB Table as an object using the #Entity annotation etc
Class KeysDao - The Data Access Object that does all the DB calls keysDao.update(Keys), keysDao.add(Keys), keysDao.get(id) keysDao.getAllKeys() etc.
Class KeyService - this has the Business Logic so you can say in any other class keyService.getKey(id) and get the Key from the DB returned. Then you can get it in any other class you wish.
If you mean get in another table you need to look at SQL table joins and create your query correctly (or create a view in the DB - not a lot of people know but you can update and add using a View meaning you can make one commit with the data as you use in the view and not have to even know the real normalised DB beneath.
In my use-case, I would like to #Embedded a class C in an entity.
Another entity refers to C with #OneToMany association and therefore C is annotated with #Entity.
I am aware that this seems like bad design, yet I believe that it makes perfect sense in my case.
Is it possible to force Hibernate to embed an Entity? If I try it, Hibernate complains about a missing setter for the id property of C.
I think the problem comes from this:
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private Long id;
Why not just create the entity that you want, and in that entity, embed C as well. That way you have C in both classes, one as embedded and another as embedded of the new entity.
#Embeddable
public class Contact {
private String firstname;
private String lastname;
// getters and setters removed.
}
and here is your embedding class:
#Entity
public class Student {
#Embedded
private Contact contact;
}
and here is the new entity that embeds contact also
#Entity
public class FirmContact {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int contactId;
#Embedded
private Contact contact;
}
And finally the class that insists the contact must be an entity:
#Entity
public class Business {
#OneToOne(cascade=CascadeType.ALL)
private FirmContact contacts;
}
It'll just be a couple of extra steps in java to populate the object, but it should do the mapping you want. I hope this helps.
Hibernate doesn't allow you to treat an Embeddable as an Entity or to embed an Entity. According to Hibernate types:
an Embeddable, doesn't have an identifier, since it's state is part of an owning Entity.
an Entity cannot be embedded, because each Entity has a distinct life-cycle.
Since another class already has a #OneToMany association to class C, it's obvious you cannot turn it into an Embeddable.
More, a bidirectional #OneToMany association will perform better than an embeddable collection.
What you can do, is to use it as a #OneToOne association in the entity where you wanted to embed the C entity. You can make that target entity be the owning side of the association so that the C association is bound to the target entity life-cycle.