I am trying to map a key in xml as follows:
<composite-id>
<key-property name="userId" column="USER_ID" />
<key-property name="passwordsBack" column="PASSWORDS_BACK" />
</composite-id>
I have seen this construction, without class="BlahPK", in the documentation, in "Hibernate in Action," and elsewhere. When I try to fetch, though, I get:
Initial SessionFactory creation failed.org.hibernate.MappingException: composite-id class must implement Serializable: MyClass
This is a very simple data class, it's not mutable, I don't need a key and certainly don't want to remodel my object and define a separate public class just to read it with Hibernate. Currently, I have it kludged to use rowid as the id, but I'd rather have the mapping cleanly reflect how the table and object are used.
Disclaimer: I searched StackOverflow and all I found was
how to handle composite key hibernate, which just says "don't do it but you can."
You can define multiple #Id properties in the entity class. like
#Entity
class User implements Serializable {
#Id
private String userId;
#Id
private String passwordsBack;
..
}
This will only be supported by Hibernate not with JPA. While you try to load this into session, you need to create an instance of User and set the id properties and the call the session.load(User.class, userinstance)
I found this hibernate documentation which will help understanding this.
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#entity-mapping-identifier
Section you need to look for is 2.2.3.2.2. Multiple #Id properties.
EDIT: Just realized that you need the xml description and not the annotation based solution. There might be something similar to this approach. Let me see if I can get you a reference.
Update: If you can change your class MyClass to implement Serializable, that will fix the problem and no need to have another public PK class. You need to have the equals and hashCode methods which will use you id fields.
I have an owner (Category) and a customer (Forum) entities designed this way:
Category
...
#OneToMany( fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "category" )
#OrderBy( "position" )
private List<Forum> forums;
...
Forum
...
#ManyToOne
#JoinColumn( name = "category" )
private Category category;
private Integer position;
...
Somewhere in my webapp, I display the forums list, and I execute some business action on one of them, for example changing its position.
My issue is that the change is well persisted in the database, but is not reflected on the OneToMany mapped collection. Thus when I refresh the page that displays the list, it doesn't show the new position but the previous one.
The code I use to update an element's position is equivalent to a simple em.merge( forum ). I read in many topics that I should "manually manage" the bidirectionnal relationship, otherwise I would face this kind of issues. Here are my two questions :
I tried on both EclipseLink and Hibernate, and while it works well with Hibernate (list is updated), it doens't in EclipseLink. Is it related to some caching mode difference?
How should I manually notice my list that one of its element's property has changed (e.g. the position property of a forum in the forums list) ?
[EDIT] I read this topic and I feel my issue is related to my forum being updated by a different session from the one being used to fetch the list. Am I understanding it right? If yes, how to correctly manage that case?
Assuming you set both sides of the objects (you have to!), try disabling the eclipselink cache:
<property name="eclipselink.cache.shared.default" value="false"/>
#source http://wiki.eclipse.org/EclipseLink/FAQ/How_to_disable_the_shared_cache%3F
I am trying to use Hibernate to auto increment the id, however, I try to avoid duplication.
class Service
{
Long id; // auto increment
String name;
String owner;
Boolean incremental;
// setter and getter
}
What I want to achieve is, whenever the new service object I want to save has the same name and owner(no matter if the data field incremental are the same or not) as any of the existing one in the database, it will be a duplicated entry. In this case, I don't want to add another entry into the Database anymore. How to revise the hbm.xml files to avoid this issue?
You can use annotations to do the same.
On top of your entity class you write the following:
#Table(uniqueConstraints = #UniqueConstraint(columnNames = { "name","owner"}))
#Entity
class Service
{
Long id; // auto increment
String name;
String owner;
// setter and getter
}
This will tell hibernate that the columns name and owner should be unique together.
If you need the id column, you can keep it.
What you need is
* a unique constraint at the database level on both columns.
(if you use hbmtoddl tool, you may need something like that :
<properties name="key" unique="true">
<property name="name" .../>
<property name="owner" .../>
</properties>
)
This way, you can not insert duplicates data.
After that if you don't want your code to break when you try to insert duplicates, you need to
lookup by name and owner (if you do that often, an index might be a good idea)
if you don't find the entry, insert it
you might also want to catch the exception thrown in case of unique constraint violation (yes that may still happen if two threads are inserting data at the same time) and retry a select.
You have a number of options:
define your primary key as a composite-id or natural-id
before saving, use a query to find if there is another row with the same name and owner, and if there is - get it.
Either way you should override hashCode() and equals(..) using name and owner
In this application we are developing, we noticed that a view was particularly slow. I profiled the view and noticed that there was one query executed by hibernate which took 10 seconds even if there only were two object in the database to fetch. All OneToMany and ManyToMany relations were lazy so that wasn't the problem. When inspecting the actual SQL being executed, I noticed that there were over 80 joins in the query.
Further inspecting the issue, I noticed that the problem was caused by the deep hierarchy of OneToOne and ManyToOne relations between entity classes. So, I thought, I'll just make them fetched lazy, that should solve the problem. But annotating either #OneToOne(fetch=FetchType.LAZY) or #ManyToOne(fetch=FetchType.LAZY) doesn't seem to work. Either I get an exception or then they are not actually replaced with a proxy object and thus being lazy.
Any ideas how I'll get this to work? Note that I do not use the persistence.xml to define relations or configuration details, everything is done in java code.
First off, some clarifications to KLE's answer:
Unconstrained (nullable) one-to-one association is the only one that can not be proxied without bytecode instrumentation. The reason for this is that owner entity MUST know whether association property should contain a proxy object or NULL and it can't determine that by looking at its base table's columns due to one-to-one normally being mapped via shared PK, so it has to be eagerly fetched anyway making proxy pointless. Here's a more detailed explanation.
many-to-one associations (and one-to-many, obviously) do not suffer from this issue. Owner entity can easily check its own FK (and in case of one-to-many, empty collection proxy is created initially and populated on demand), so the association can be lazy.
Replacing one-to-one with one-to-many is pretty much never a good idea. You can replace it with unique many-to-one but there are other (possibly better) options.
Rob H. has a valid point, however you may not be able to implement it depending on your model (e.g. if your one-to-one association is nullable).
Now, as far as original question goes:
A) #ManyToOne(fetch=FetchType.LAZY) should work just fine. Are you sure it's not being overwritten in the query itself? It's possible to specify join fetch in HQL and / or explicitly set fetch mode via Criteria API which would take precedence over class annotation. If that's not the case and you're still having problems, please post your classes, query and resulting SQL for more to-the-point conversation.
B) #OneToOne is trickier. If it's definitely not nullable, go with Rob H.'s suggestion and specify it as such:
#OneToOne(optional = false, fetch = FetchType.LAZY)
Otherwise, if you can change your database (add a foreign key column to owner table), do so and map it as "joined":
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name="other_entity_fk")
public OtherEntity getOther()
and in OtherEntity:
#OneToOne(mappedBy = "other")
public OwnerEntity getOwner()
If you can't do that (and can't live with eager fetching) bytecode instrumentation is your only option. I have to agree with CPerkins, however - if you have 80!!! joins due to eager OneToOne associations, you've got bigger problems then this :-)
To get lazy loading working on nullable one-to-one mappings you need to let hibernate do compile time instrumentation and add a #LazyToOne(value = LazyToOneOption.NO_PROXY) to the one-to-one relation.
Example Mapping:
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name="other_entity_fk")
#LazyToOne(value = LazyToOneOption.NO_PROXY)
public OtherEntity getOther()
Example Ant Build file extension (for doing the Hibernate compile time instrumentation):
<property name="src" value="/your/src/directory"/><!-- path of the source files -->
<property name="libs" value="/your/libs/directory"/><!-- path of your libraries -->
<property name="destination" value="/your/build/directory"/><!-- path of your build directory -->
<fileset id="applibs" dir="${libs}">
<include name="hibernate3.jar" />
<!-- include any other libraries you'll need here -->
</fileset>
<target name="compile">
<javac srcdir="${src}" destdir="${destination}" debug="yes">
<classpath>
<fileset refid="applibs"/>
</classpath>
</javac>
</target>
<target name="instrument" depends="compile">
<taskdef name="instrument" classname="org.hibernate.tool.instrument.javassist.InstrumentTask">
<classpath>
<fileset refid="applibs"/>
</classpath>
</taskdef>
<instrument verbose="true">
<fileset dir="${destination}">
<!-- substitute the package where you keep your domain objs -->
<include name="/com/mycompany/domainobjects/*.class"/>
</fileset>
</instrument>
</target>
Unless you are using Bytecode Enhancement, you cannot fetch lazily the parent-side #OneToOne association.
However, most often, you don't even need the parent-side association if you use #MapsId on the child-side:
#Entity(name = "PostDetails")
#Table(name = "post_details")
public class PostDetails {
#Id
private Long id;
#Column(name = "created_on")
private Date createdOn;
#Column(name = "created_by")
private String createdBy;
#OneToOne(fetch = FetchType.LAZY)
#MapsId
private Post post;
public PostDetails() {}
public PostDetails(String createdBy) {
createdOn = new Date();
this.createdBy = createdBy;
}
//Getters and setters omitted for brevity
}
With #MapsId, the id property in the child table serves as both Primary Key and Foreign Key to the parent table Primary Key.
So, if you have a reference to the parent Post entity, you can easily fetch the child entity using the parent entity identifier:
PostDetails details = entityManager.find(
PostDetails.class,
post.getId()
);
This way, you won't have N+1 query issues that could be caused by the mappedBy #OneToOne association on the parent side.
Here's something that has been working for me (without instrumentation):
Instead of using #OneToOne on both sides, I use #OneToMany in the inverse part of the relationship (the one with mappedBy). That makes the property a collection (List in the example below), but I translate it into an item in the getter, making it transparent to the clients.
This setup works lazily, that is, the selects are only made when getPrevious() or getNext() are called - and only one select for each call.
The table structure:
CREATE TABLE `TB_ISSUE` (
`ID` INT(9) NOT NULL AUTO_INCREMENT,
`NAME` VARCHAR(255) NULL,
`PREVIOUS` DECIMAL(9,2) NULL
CONSTRAINT `PK_ISSUE` PRIMARY KEY (`ID`)
);
ALTER TABLE `TB_ISSUE` ADD CONSTRAINT `FK_ISSUE_ISSUE_PREVIOUS`
FOREIGN KEY (`PREVIOUS`) REFERENCES `TB_ISSUE` (`ID`);
The class:
#Entity
#Table(name = "TB_ISSUE")
public class Issue {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
protected Integer id;
#Column
private String name;
#OneToOne(fetch=FetchType.LAZY) // one to one, as expected
#JoinColumn(name="previous")
private Issue previous;
// use #OneToMany instead of #OneToOne to "fake" the lazy loading
#OneToMany(mappedBy="previous", fetch=FetchType.LAZY)
// notice the type isnt Issue, but a collection (that will have 0 or 1 items)
private List<Issue> next;
public Integer getId() { return id; }
public String getName() { return name; }
public Issue getPrevious() { return previous; }
// in the getter, transform the collection into an Issue for the clients
public Issue getNext() { return next.isEmpty() ? null : next.get(0); }
}
The basic idea behing the XToOnes in Hibernate is that they are not lazy in most case.
One reason is that, when Hibernate have to decide to put a proxy (with the id) or a null,
it has to look into the other table anyway to join. The cost of accessing the other table in the database is significant, so it might as well fetch the data for that table at that moment (non-lazy behaviour), instead of fetching that in a later request that would require a second access to the same table.
Edited: for details, please refer to ChssPly76 's answer. This one is less accurate and detailed, it has nothing to offer. Thanks ChssPly76.
In native Hibernate XML mappings, you can accomplish this by declaring a one-to-one mapping with the constrained attribute set to true. I am not sure what the Hibernate/JPA annotation equivalent of that is, and a quick search of the doc provided no answer, but hopefully that gives you a lead to go on.
As already perfectly explained by ChssPly76, Hibernate's proxies don't help with unconstrained (nullable) one-to-one associations, BUT there is a trick explained here to avoid to set up instrumentation. The idea is to fool Hibernate that the entity class which we want to use has been already instrumented: you instrument it manually in the source code. It's easy! I've implemented it with CGLib as bytecode provider and it works (ensure that you configure lazy="no-proxy" and fetch="select", not "join", in your HBM).
I think this is a good alternative to real (I mean automatic) instrumentation when you have just one one-to-one nullable relation that you want to make lazy. The main drawback is that the solution depends on the bytecode provider you are using, so comment your class accurately because you could have to change the bytecode provider in the future; of course, you are also modifying your model bean for a technical reason and this is not fine.
This question is quite old, but with Hibernate 5.1.10, there are some new better comfortable solution.
Lazy loading works except for the parent side of a #OneToOne association. This is because Hibernate has no other way of knowing whether to assign a null or a Proxy to this variable. More details you can find in this article
You can activate lazy loading bytecode enhancement
Or, you can just remove the parent side and use the client side with #MapsId as explained in the article above. This way, you will find that you don’t really need the parent side since the child shares the same id with the parent so you can easily fetch the child by knowing the parent id
.
For Kotlin devs: To allow Hibernate to inherit from the #Entity types that you want to be lazy-loadable they have to be inheritable/open, which they in Kotlin by default are not. To work around this issue we can make use of the all-open compiler plugin and instruct it to also handle the JPA annotations by adding this to our build.gradle:
allOpen {
annotation("javax.persistence.Entity")
annotation("javax.persistence.MappedSuperclass")
annotation("javax.persistence.Embeddable")
}
If you are using Kotlin and Spring like me, you are most probably also using the kotlin-jpa/no-args and kotlin-spring/all-open compiler plugins already. However, you will still need to add the above lines, as that combination of plugins neither makes such classes open.
Read the great article of Léo Millon for further explanations.
Most efficient mapping of a one-to-one association
You can avoid all these problems and get rid of the foreign key column by using the same primary key value for both associated entities. You can do that by annotating the owning side of the association with #MapsId.
#Entity
public class Book {
#Id
#GeneratedValue
private Long id;
#OneToOne(mappedBy = "book", fetch = FetchType.LAZY, optional = false)
private Manuscript manuscript;
...
}
#Entity
public class Manuscript {
#Id
private Long id;
#OneToOne
#MapsId
#JoinColumn(name = "id")
private Book book;
...
}
Book b = em.find(Book.class, 100L);
Manuscript m = em.find(Manuscript.class, b.getId());
More Detail click on this url
If the relation must not be bidirectional then an #ElementCollection might be easier than using a lazy One2Many collection.
If the child entity is used readonly, then it's possible to simply lie and set optional=false.
Then ensure that every use of that mapped entity is preloaded via queries.
public class App {
...
#OneToOne(mappedBy = "app", fetch = FetchType.LAZY, optional = false)
private Attributes additional;
and
String sql = " ... FROM App a LEFT JOIN FETCH a.additional aa ...";
... maybe even persisting would work...
I would like to map a many-to-many in Hibernate using a link table. I have two classes, Parent and Child class, for example:
public class Parent{
private List<Child> _children;
//...getters and setters
}
I use a link table (link_table) with three columns link_id, parent_id, and child_id. The database is SQL server and id types are uniqueidentifier. So, I usually use guid for the id fields.
How can you implement this using the <list /> tag if this is the correct tag to use? Do you know of any good documentation to accomplish this?
I am currently getting a ConstraintViolationException but have not been able to find any good documentation or examples of this.
I think a main issue is: how to specify the link_id to be automatically generated in the link table.
I do this using annotations, specifically #ManyToMany and #JoinTable:
Hibernate Docs:
#Entity
public class Employer implements Serializable {
#ManyToMany(
targetEntity=org.hibernate.test.metadata.manytomany.Employee.class,
cascade={CascadeType.PERSIST, CascadeType.MERGE}
)
#JoinTable(
name="EMPLOYER_EMPLOYEE",
joinColumns=#JoinColumn(name="EMPER_ID"),
inverseJoinColumns=#JoinColumn(name="EMPEE_ID")
)
public Collection getEmployees() {
return employees;
}
}
#Entity
public class Employee implements Serializable {
#ManyToMany(
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
mappedBy = "employees",
targetEntity = Employer.class
)
public Collection getEmployers() {
return employers;
}
}
I don't think that it is possible (or necessary) to add a link_id primary key to the join table. The join table will usually consist of the primary keys of the two participating tables.
Using XML you will need syntax like this:
<class name="Parent">
....
<list name="children" table="link_table">
<key column="parent_id"/>
<many-to-many column="child_id"
class="Children"/>
</list>
...
</class>
<class name="Child">
...
<list name="parents" inverse="true" table="link_table">
<key column="child_id"/>
<many-to-many column="parent_id"
class="Parent"/>
</list>
...
</class>
Although I find annotations better to use.
I am not sure that you can pull this off easily for an existing database with existing data. Hibernate is usually better off defining its own data schema the first time you connect...
I've only pulled off many-to-many with annotations, but I think the hibernate documentation offers XML based examples: link text
I found a very good blog online which gives 2 ways to add additional fields to the many to many mapped hibernate column.
Traditionally we expect the many to many mapping to give a new table will FK's of tables mapped. But there are ways to tweak that and add more fields/column to this joined table.
This joined table may contain a PK or may contain some extra fields without PK.
See this blog for exact implementation See Here
And as per your example, you need an extra PK in the table so you declare a new table ParentChildren and declare your primary key as linkId. I am showing just the annoated parentchildren class, as annotations for many to many mapping in parent and children class can be referenced from post above.
#Entity
#Table(name = "parent_children")
public class ParentChildren{
#Id #GeneratedValue
private long linkId;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "parent_id")
private Parent parent;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "children_id)
private Children children;
// additional fields if you want
private boolean activated;
//getters and setters
}
}
So this will create a mapping table which has linkId as primary key and parent_id and children_id as Foreign Key. Just be clear on why you want a link_id separately as primary key and how you are going to use it.