Hibernate One-to-one Mapping with interface.i need advice - java

i'm developing an application where all the pojos are exposed as interface but we map the real implementation class.we are using spring and JPA annotation.i'm about to test the one-to-one relationship and i'm having a light problem with the interface.
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionContainer' defined in class path resource [META-INF/model-config.xml]:
Cannot resolve reference to bean 'sessionFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'sessionFactory' defined in class path resource [META-INF/model-config.xml]:
Invocation of init method failed; nested exception is org.hibernate.AnnotationException:
#OneToOne or #ManyToOne on com.mycompany.project.subproject.model.UserAccountImpl.profile references an unknown entity: com.mycompany.project.
so before this class all the other mapped class are working as expected so i'll only post part of the applicationContext file that i named model-config.xml
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
...
<value>com.mycompany.project.subproject.model.UserProfileImpl</value>
<value>com.mycompany.project.subproject.model.UserAccountImpl</value>
...
</list>
</property>
here are the two involved class UserProfileImpl.java and UserAccountImpl.java
//UserAccountImpl Class
#Entity
#Table(name ="USER_ACCOUNT")
public class UserAccountImpl implements UserAccount {
#Id #GeneratedValue
#Column(name="USER_ACCOUNT_ID")
private Long ID;
...
#OneToOne
#JoinColumn(name="USER_PROFILE_ID")
private UserProfile profile;
...
}
//UserProfileImpl class
#Entity
#Table(name="USER_PROFILE")
public class UserProfileImpl implements UserProfile {
#Id #GeneratedValue
#Column(name="USER_PROFILE_ID")
private Long ID;
....
#OneToOne(mappedBy="profile")
private UserAccount userAccount;
....
}
i'm still not very confortable with hibernate yet so i'm wondering if i should Change the UserProfile reference in UserAccountImpl to UserProfileImpl.Then again the same can happen in the UserProfileImpl for userAccount reference since it's a bidirectional navigation stuff.
What's the best option that will no break the consistency of the structure?
Thanks for reading this

You have these options:
You must tell Hibernate somehow which class to use for the interface UserAccount. Currently, the most simple solution is to use a concrete type instead of the interface in your UserProfileImpl.
You can use #Target to specify the implementation to use (see [the docs][1]).
You can map the field with a custom UserType. This allows to chose the mapping (which implementation to use for an interface) at runtime but you must write the code to copy the fields between your business objects and the DB yourself (no automatic mapping anymore).

You could try the following:
#OneToOne(mappedBy="profile", targetEntity=UserAccountImpl.class)
private UserAccount userAccount

Does UserProfile have to be a separate Entity? You could model this as a Component, and combine the UserAccount and UserProfile tables into one. Your object model would still have a separate UserProfile object, it would just be a value object owned by UserAccount.
Not every object has to be implemented as an Entity,and One-to-One mappings are quite rare in practice ....

Related

How to specify bean`s "id" property in Spring?

I have a class MyBean with some fields including String "id".
I have a lot of xml-defined beans with IDs.
I want to fill "id" fields of MyBean java objects to xml-specified bean IDs. How to implement this without code duplicaton?
package just.artmmslv.example.MyBean
public class MyBean {
private String id;
private String foo;
//getters, setters, other fields
}
<beans xmlns="foobar+util">
<util:list value-type="just.artmmslv.example.MyBean">
<bean id="exampleBean01" class="just.artmmslv.example.MyBean">
<property name="foo" value="bar"/>
</bean>
<!--Other beans-->
</util:list>
</beans>
So, how to make exampleBean01`s field id to be equal to "exampleBean01" in convenient way?
Make id in MyBean of type String, not int (I see int in your code)
Make MyBean implements BeanNameAware
Implement method setBeanName in MyBean:
#Override
public void setBeanName(String s) {
this.id = s;
}
That's all you need
I think Spring provides a way to do this via BeanNameAware.
Read through: https://docs.spring.io/spring/docs/2.5.x/reference/beans.html#beans-factory-aware-beannameaware
Interface to be implemented by beans that want to be aware of their bean name in a bean factory. Note that it is not usually recommended that an object depend on its bean name, as this represents a potentially brittle dependence on external
configuration, as well as a possibly unnecessary dependence on a Spring API.

#Component Hibernate classes

I have hibernated annotated classes in my program. Since I'm running a Spring project, I have included them in the servlet.xml file(com.student.dto is the actual package name) and added #Component on the Contacts Entity..Is there a way to automate adding #Component on all the hibernate classes..Each time I create a model, I end up doing this and feel there should be a better to do this.
<context:component-scan base-package="com.student.dto" />
#Component
#Entity
#Table(name = "Contacts", catalog = "javadb")
public class ContactsDTO implements java.io.Serializable {
private int idContacts;
private StudentDTO StudentDTO;
private String addr1;
private String addr2;
private String city;
private String state;
private String pinCode;
private String country;
private String phone;
private String mobile;
private String email;
private String contactscol;
public ContactsDTO() {
}
public ContactsDTO(int idContacts) {
this.idContacts = idContacts;
}
public ContactsDTO(int idContacts, StudentDTO StudentDTO, String addr1,
String addr2, String city, String state, String pinCode,
String country, String phone, String mobile, String email,
String contactscol) {
this.idContacts = idContacts;
this.StudentDTO = StudentDTO;
this.addr1 = addr1;
this.addr2 = addr2;
this.city = city;
this.state = state;
this.pinCode = pinCode;
this.country = country;
this.phone = phone;
this.mobile = mobile;
this.email = email;
this.contactscol = contactscol;
}
getters & setters
You are doing it all wrong. Spring Beans are singleton by default and your entities are not thread safe and neither they should ever be.
Entities should be local variables bound to a Persistent Context. They are not meant to be accessed in a multi-threaded environment.
Concurrency control is handled by the database and your application logic should mostly be concern about preventing lost updates through application-level repeatable reads.
Your DAO and Services should be Spring singleton components. Your Entities and request bound DTOs should never be singleton. These objects are short-lived and scoped to the request that generated them.
Check the Spring Data JPA docs for a solid data access layer design.
The #Component javadocs says this.
Indicates that an annotated class is a "component". Such classes are considered as candidates for auto-detection when using annotation-based configuration and classpath scanning.
The #Component, #Repository etc are Typically used for Auto scanning (during application bootstrap)and for the dependency injection. I dont see a point in making your entity as a Spring Component. The typical use of an entity is that it represents your Relational database Table. Entity (Java)= Table (RDBMS). Here is the definition of an Entity
An entity is a lightweight persistence domain object. Typically, an entity represents a table in a relational database, and each entity instance corresponds to a row in that table. The primary programming artifact of an entity is the entity class, although entities can use helper classes.
The way to include your entities should be something like this:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<!-- Here are your Entities annotated with #Entity -->
</list>
</bean>
Note that you can also define a property called "annotatedPackages" and define your packages
Personally, i havent tested "annotatedPackages". But, "annotatedClasses" work perfectly.
As suggested by #Vlad Mihalcea, Entities are not meant to be Singleton. They are more of "Local" scope, and are to be intialized per "request".
You can configure this by convention. In the servlet.xml you can add a bean that does class path scanning and can automatically add the #Component using a regex and a common naming approach. See here for details:
http://www.mkyong.com/spring/spring-filtering-components-in-auto-scanning/

How to use Hibernate composite-id without class?

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.

How to map parent's bean class variable in Hibernate?

I have a Bean class called Bean_A that is map to table_A, and this Bean_A class is inherited from a base bean class, and the base bean class will have a unique_reference_key variable that will going to save into the database together with the Bean_A class. I already have the hibernate file ready for the Bean_A and the unique_reference_key field in table_A.
May I know how could I map the base bean class in hibernate to ensure this unique_reference_key variable is save into database when I was saving the Bean_A object? Take note that this base bean class is not map to any table in database, and there is no such table that "represent" the base bean.
Before I throw out this question, I have consult the following article but still couldn't get any clue on it.
Hibernate simplifies inheritance mapping
Hibernate Chapter 5.Basic O/R Mapping
Your descriptiin would be much clearer if you added some code. But I think you're just looking for the MappedSuperclass annotation, described in the documentation:
5.1.6.4. Inherit properties from superclasses
This is sometimes useful to share common properties through a
technical or a business superclass without including it as a regular
mapped entity (ie no specific table for this entity). For that purpose
you can map them as #MappedSuperclass.
#MappedSuperclass
public class BaseEntity {
#Basic
#Temporal(TemporalType.TIMESTAMP)
public Date getLastUpdate() { ... }
public String getLastUpdater() { ... }
...
}
#Entity class Order extends BaseEntity {
#Id public Integer getId() { ... }
...
}
I have found the solution on how to map the base bean property into Bean_A in hibernate.
In hibernate:
<class name="com.dao.pojo.BaseBean" abstract="true">
<id name="theId" type="string">
<column name="primary_key" length="15" />
</id>
<property name="unique_ref_key" type="java.lang.String" column="unique_ref_key"/>
<union-subclass name="com.dao.pojo.Bean_A" table="table_A" lazy="false">
...
</union-subclass>
</class>
Please note that theId was originally from Bean_A and it has been move to BaseBean. A new field, unique_ref_key, is created inside table_A.
In JAVA:
public abstract class BaseBean {
private String theId;
private String unique_ref_key;
// getter and setter
}
public class Bean_A extends BeseBean {
...
}
Hope this solution can help others.

org.hibernate.InstantiationException: How to tell Hibernate which class to use for object instantiation

I am currently trying to replace my own database controller implementation with Hibernate and I have the following problem creating an appropriate mapping file.
(I am very new to Hibernate, so please be gentle :-) - I've read through the whole Hibernate Reference documentation but I don't have any practical experience yet).
(The whole thing should represent the relationship between email accounts and their server settings).
I have a class called MailAccount which has 2 properties (see code below):
public class MailAccount{
long id;
IncomingMailServer incomingServer;
OutgoingMailServer outgoingServer;
public MailAccount(){
super();
}
// Getter and setter omitted
}
The server class hierachy looks like this:
MailServer.java
public abstract class MailServer {
String password;
String host;
String username;
String port;
// Getter and setter omitted
}
IncomingMailServer.java
public abstract class IncomingMailServer extends MailServer {
}
OutgoingMailServer.java
public abstract class OutgoingMailServer extends MailServer {
}
Pop3Server.java
public class Pop3Server extends IncomingMailServer{
public Pop3Server(){
super();
}
}
ImapServer.java
public class ImapServer extends IncomingMailServer{
public ImapServer(){
super();
}
}
SmtpServer.java
public class SmtpServer extends OutgoingMailServer{
public SmtpServer(){
super();
}
}
The properties incomingServer and outgoingServer in MailAccount.java of course only hold instances of either Pop3Server, ImapServer (for incomingServer) or SmtpServer (for outgoingServer).
Now, I tried to create the mapping file for MailAccount:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test.account">
<class name="MailAccount" table="MAILACCOUNTS" dynamic-update="true">
<id name="id" column="MAIL_ACCOUNT_ID">
<generator class="native" />
</id>
<component name="incomingServer" class="test.server.incoming.IncomingMailServer">
<property name="password" column="INCOMING_SERVER_PASSWORD" />
<property name="host" column="INCOMING_SERVER_PASSWORD" />
<property name="username" column="INCOMING_SERVER_PASSWORD" />
<property name="port" column="INCOMING_SERVER_PASSWORD" />
</component>
<component name="outgoingServer" class="test.server.outgoing.OutgoingMailServer">
<property name="password" column="OUTGOING_SERVER_PASSWORD" />
<property name="host" column="OUTGOING_SERVER_PASSWORD" />
<property name="username" column="OUTGOING_SERVER_PASSWORD" />
<property name="port" column="OUTGOING_SERVER_PASSWORD" />
</component>
</class>
</hibernate-mapping>
Note: Since I got a 1:1 relation between MailAccount and IncomingMailServer as well as MailAccount and OutgoingMailServer, I want everything in 1 table in order to prevent unnecessary joins.
The problem: Whenever I tell Hibernate to save an instance of MailAccount, like this:
session = getSession();
transaction = session.beginTransaction();
session.save(mailAccount);
transaction.commit();
.. I get the following exception:
org.hibernate.InstantiationException:
Cannot instantiate abstract class or
interface:
test.server.incoming.IncomingMailServer
This totally makes sense since abstract classes cannot be instantiated.
However, here comes my question: How can I tell Hibernate to create an instance of the right class (Pop3Server, SmtpServer, ImapServer) instead of the abstract ones?
Example: If the property incomingServer holds an instance of Pop3Server, then Hiberante should store that into my database and when I load the according MailAccount back, I want Hibernate to recreate an instance of Pop3Server.
The problem is occurring because a component is not a stand-alone entity, but "a class whose instances are stored as an intrinsic part of an owning entity and share the identity of the entity". In JPA terms it is considered an Embeddable class. These classes are usually used to create a class object out of a number of table columns that would normally have to be stored as individual attributes in an entity (you can almost look at it as grouping).
While there are a number of benefits to this approach, there are some restrictions. One of these restrictions are that the component or embeddable cannot be an abstract class. The reason being that there isn't any way for hibernate to associate a particular concrete subclass with the value you are trying to store or read. Think of it this way: would you be able to tell what instance to create by only looking at the column data? It's usually not that straight forward, especially for the persistence engine.
In order to get the functionality you desire, you will want to look into storing MailServer data as a separate entity with its own primary key field. Doing so allows you to manage the data with subclasses using various inheritance methods such as including a DiscriminatorColumn or separate tables (depending on your configuration).
Here are some links that should help you with setting up these mappings and using entity inheritance:
One-to-One mapping example
(useful if not reusing MailServer
data.
Inheritance overview
Useful Hibernate examples (not
latest spec, but gives you good
overview)
Hope this helps.
http://www.vaannila.com/hibernate/hibernate-example/hibernate-example.html
If you were to use this approach using Hibernate (I personally prefer JPA-based Annotation configurations), you could configure MailServer as an abstract entity that would define the common column mappings between the classes and a DiscriminatorColumn (if using same table inheritance). The subclasses would be built off of this definition, adding custom attributes as needed.

Categories

Resources