I am having a problem with hibernate. I am updating a previously created database created in Oracle SQL in order to get some practice with hibernate. The thing is that I am getting an AnnotationException that one class object is trying to reference something from the other class. Here is the error:
org.hibernate.AnnotationException: #OneToOne or #ManyToOne on com.revature.bank.POJO.BankAccount.customer references an unknown entity: com.revature.bank.POJO.Customer
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:107)
at org.hibernate.cfg.Configuration.processEndOfQueue(Configuration.java:1580)
at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1503)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1419)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1856)
at com.revature.bank.POJO.DataFuncImp.createCustomer(DataFuncImp.java:16)
at com.revature.bank.POJO.Main.main(Main.java:9)
So, this is pointing to the line:
SessionFactory sf = new Configuration().configure().buildSessionFactory();
I have read that it might be happening because the annotations but none of the previously asked questions here seemed to work.
Here are my two classes: (i will only put the variables as that's where the error points to):
Customer.java
#Entity
#Table(name="USER_TABLE")
public class Customer {
#Id
#GeneratedValue
private int user_id;
#Column
private String user_fname;
#Column
private String user_lname;
#Column
private String user_email;
#Column
private String user_address;
#Column
private String user_city;
#Column
private String user_state;
#Column
private long cell_num;
#OneToMany(cascade= {CascadeType.ALL}, mappedBy="customer")
#JoinColumn(name="user_id")
private List<BankAccount> bacct;
BankAccount.java
#Entity
#Table(name="USER_ACCOUNT")
public class BankAccount {
#Id
#GeneratedValue
private long acct_id;
#Column
private double balance;
#ManyToOne
#JoinColumn(name="user_id")
private Customer customer;
And here is my hibernate config file as well(edited out the database connection info):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:#localhost:1521:xe</property>
<property name="hibernate.connection.username">adminone</property>
<property name="hibernate.connection.password">adminpass</property>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle11gDialect</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<!-- <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property> -->
<!-- <mapping resource="students.hbm.xml"></mapping> -->
<mapping class="com.revature.bank.POJO.Customer"></mapping>
<mapping class="com.revature.bank.POJO.BankAccount"></mapping>
</session-factory>
</hibernate-configuration>
I am using hibernate 3.0. Like i mentioned earlier, i have been trying to figure out the error but none of the online help seemed to fix it. As you can see, I'm not even trying to do anything to the database yet and it is throwing that exception. Any idea on why is this happening? Thank you in advance!!
You shouldn't have JoinColumn on both sides. Just on the owner side, so remove it from the Customer class.
Customer.java:
#OneToMany(cascade= {CascadeType.ALL}, mappedBy="customer")
private List<BankAccount> bacct;
BankAccount.java:
#ManyToOne
#JoinColumn(name="user_id")
private Customer customer;
I am getting strange error Caused by:
java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint
While executing my below code:
Product DAO.java
#Id
#Column(name = "no", columnDefinition = "NUMBER")
private int serial_number;
//No getter and setter for this field
#Column(name = "fname", columnDefinition = "VARCHAR2(50)")
private int fname;
#Column(name = "lname", columnDefinition = "VARCHAR2(50)")
private int lname;
// Getter and setter for fname and lname
ProductService.java
Product po = new Product();
po.setfname = "Tom";
po.setlname = "John";
//I am not setting 'no' field value since I have created sequence in my oracle table to auto increment the value.
When I am running this code, I am getting unique constraint error on field 'no'. Can anyone help me in identifying what I am doing wrong in my code. When I have already created sequence for 'no' field in my table, do I need to make any change in config file or code? Since its the production database, I do not know the sequence name also.
hibernate-cgf.xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:#localhost:1521:xe</property>
<property name="hibernate.connection.password">pass</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<mapping class="dao.Product"></mapping>
</session-factory>
</hibernate-configuration>
Your id field serial_number is an int which is initialized to zero, and your mapping for #Id does not include a #GeneratedValue annotation, so hibernate will assume you are assigning the id manually and save it as zero every time you persist an object, causing the SQLIntegrityConstraintViolationException. You need to add a #GeneratedValue annotation and you can also choose a strategy, like this:
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "no", columnDefinition = "NUMBER")
private int serial_number;
I am using Hibernate 4 orm and search for my twitter application. The problem is when I start persisting tweets into MariaDB table, id (primary key) gets incremented by five fold:
2
7
12
17
22
27
I tried all Generation Types which are available : SEQUENCE, IDENTITY, TABLE and AUTO. But none of this provided increment by one. I guess I am missing some configuration, otherwise it should provide increment by one.
Here is my Entity class and hibernate.cfg.xml file:
#Entity
#Indexed
#Table(name="tweets_table")
public class TweetPOJO implements Serializable{
private static final long serialVersionUID = 1123211L;
#Id
#GeneratedValue (???)
#Column(name = "raw_id" )
private int raw_id;
#Column(name = "tweet_id")
private String tweet_id;
#DateBridge(resolution=Resolution.DAY)
#Column(name = "posted_time")
private String timestamp;
#Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
#Column(name = "cleaned_text")
private String tweet_text;
#Column(name = "hashtags")
#Field(index=Index.YES, analyze=Analyze.NO, store=Store.YES)
private String hashtags;
#Column(name = "media_url")
private String media_url;
#Column(name = "media_text")
private String media_text;
#Column(name = "media_type")
private String media_type;
#Column(name = "location")
private String location;
...
...
public void setUser_frind_count(int user_frind_count) {
this.user_frind_count = user_frind_count;
}
#Override
public String toString() {
return tweet_id+" : "+tweet_text;
}
}
Here is hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.bytecode.use_reflection_optimizer"> true </property>
<property name="hibernate.dialect"> org.hibernate.dialect.MySQLDialect </property>
<property name="hibernate.connection.driver_class"> com.mysql.jdbc.Driver </property>
<!-- Assume test is the database name -->
<property name="hibernate.connection.url"> jdbc:mysql://*******/clouddata </property>
<property name="hibernate.connection.username"> root </property>
<property name="hibernate.connection.password"> qwe123 </property>
<property name="connection.pool_size"> 1 </property>
<property name="hibernate.search.default.directory_provider"> filesystem </property>
<property name="hibernate.search.default.indexBase"> E:\lucene_index </property>
<!--
whether the schema will be created or just updated, every time the sessionFactory is created.
This is configured in the hibernate.hbm2ddl.auto property, which is set to update. So the schema
is only updated. If this property is set to create, then every time we run our application, the
schema will be re-created, thus deleting previous data.
-->
<property name="hibernate.hbm2ddl.auto">update</property>
<mapping class="twitter_crawling_modul.TweetPOJO"/>
</session-factory>
You can try to use sequence generator
#SequenceGenerator(name = "seq", sequenceName = "seq_name", allocationSize = 1)
#GeneratedValue (strategy = GenerationType.SEQUENCE, generator = "seq")
I am trying to make a relationship between 2 entities in different jar.
This is a first entity which is in main project:
#Entity(name = "StdyDtlLabelBean")
#Table(name = "STDY_DTL_LABEL")
public class StdyDtlLabelBean implements Serializable {
#EmbeddedId
private StdyDtlLabelBeanPk id;
#ManyToOne(targetEntity = StdyDtlSubject.class)
#JoinColumns({
#JoinColumn(name="STUDY_ID", insertable = false, updatable = false, referencedColumnName="STUDY_ID"),
#JoinColumn(name="SUBJECT_ID", insertable = false, updatable = false, referencedColumnName="SUBJECT_ID")
})
private StdyDtlSubject subject;
//getters and setters
}
This one is an entity which is in library project as a jar file:
#Entity
#Table(name = "STDY_DTL_SUBJECT")
public class StdyDtlSubject implements Serializable {
private static final long serialVersionUID = 2479124604L;
public StdyDtlSubject() {
}
#EmbeddedId
private StdyDtlSubjectPK key;
//getters and setters
}
#Embeddable
public class StdyDtlSubjectPK implements Serializable {
private static final long serialVersionUID = 6691432687933341920L;
#Column(name = "STUDY_ID")
private Integer studyId;
#Column(name = "SUBJECT_ID")
private String subjectId;
public StdyDtlSubjectPK() {
}
Here is the persistence unit:
<persistence-unit name="stdyPersistence" transaction-type="RESOURCE_LOCAL">
<jta-data-source>java:comp/env/jdbc/OraclePooledDS</jta-data-source>
<class>com.ctasc.ctpm.jpa.StdyDtlSubject</class>
<class>stdy.brms.beans.StdyDtlLabelBean</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
</properties>
</persistence-unit>
When I create an entity manager factory I gets following error:
#OneToOne or #ManyToOne on stdy.brms.beans.StdyDtlLabelBean.subject references an unknown entity: com.ctasc.ctpm.jpa.StdyDtlSubject
But if I remove a relationship annotation from StdyDtlLabelBean entity and create named queries on StdyDtlSubject entity. Those named queries work fine. Also, if I copy StdyDtlSubject class to my main project, it works fine. I gets this error only if I put relationship between them.
I've tried adding
<jar-file>ctpm.jar</jar-file>
<jar-file>lib/ctpm.jar</jar-file>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<property name="hibernate.archive.autodetection" value="class, hbm" />
<property name="packagesToScan" value="com.ctasc.ctpm.jpa" />
None of them helped me to solve this. Could you please suggest something to solve this problem?
Ensure that the jar which you want to relate to has a persisence.xml in it's META-INF with all entities in the jar enlisted.
I need help with lazy blob loading in Hibernate.
I have in my web application these servers and frameworks: MySQL, Tomcat, Spring and Hibernate.
The part of database config.
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="initialPoolSize">
<value>${jdbc.initialPoolSize}</value>
</property>
<property name="minPoolSize">
<value>${jdbc.minPoolSize}</value>
</property>
<property name="maxPoolSize">
<value>${jdbc.maxPoolSize}</value>
</property>
<property name="acquireRetryAttempts">
<value>${jdbc.acquireRetryAttempts}</value>
</property>
<property name="acquireIncrement">
<value>${jdbc.acquireIncrement}</value>
</property>
<property name="idleConnectionTestPeriod">
<value>${jdbc.idleConnectionTestPeriod}</value>
</property>
<property name="maxIdleTime">
<value>${jdbc.maxIdleTime}</value>
</property>
<property name="maxConnectionAge">
<value>${jdbc.maxConnectionAge}</value>
</property>
<property name="preferredTestQuery">
<value>${jdbc.preferredTestQuery}</value>
</property>
<property name="testConnectionOnCheckin">
<value>${jdbc.testConnectionOnCheckin}</value>
</property>
</bean>
<bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="/WEB-INF/hibernate.cfg.xml" />
<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
</props>
</property>
<property name="lobHandler" ref="lobHandler" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
The part of entity class
#Lob
#Basic(fetch=FetchType.LAZY)
#Column(name = "BlobField", columnDefinition = "LONGBLOB")
#Type(type = "org.springframework.orm.hibernate3.support.BlobByteArrayType")
private byte[] blobField;
The problem description. I'm trying to display on a web page database records related to files, which was saved in MySQL database. All works fine if a volume of data is small. But the volume of data is big I'm recieving an error java.lang.OutOfMemoryError: Java heap space
I've tried to write in blobFields null values on each row of table. In this case, application works fine, memory doesn't go out of. I have a conclusion that the blob field which is marked as lazy (#Basic(fetch=FetchType.LAZY)) isn't lazy, actually!
I'm confused. Emmanuel Bernard wrote in ANN-418 that #Lob are lazy by default (i.e. you don't even need to use the #Basic(fetch = FetchType.LAZY) annotation).
Some users report that lazy loading of a #Lob doesn't work with all drivers/database.
Some users report that it works when using bytecode instrumentation (javassit? cglib?).
But I can't find any clear reference of all this in the documentation.
At the end, the recommended workaround is to use a "fake" one-to-one mappings instead of properties. Remove the LOB fields from your existing class, create new classes referring to the same table, same primary key, and only the necessary LOB fields as properties. Specify the mappings as one-to-one, fetch="select", lazy="true". So long as your parent object is still in your session, you should get exactly what you want. (just transpose this to annotations).
I would suggest you to use inheritance to handle this scenario. Have a base class without the blob and a derived class containing the byte array. You would use the derived class only when you need to display the blob on the UI.
Of course you could extract that value and put it into a new table with a "#OneToOne" relation that is lazy, however in our application the LOBs are loaded lazily on demand using just this configuration
#Lob
#Fetch(FetchMode.SELECT)
#Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] myBlob;
This is tested in our project simultaneously on PostgreSQL, MySQL, SQLServer and Oracle, so it should work for u
Lazy property loading requires buildtime bytecode instrumentation.
Hibernate docs: Using lazy property fetching
If you want to avoid bytecode instrumentation one option is to to create two entities that use same table, one with the blob one without. Then only use the entity with blob when you need the blob.
I had the same issue and this was my fix:
My Entity:
#Entity
#Table(name = "file")
public class FileEntity {
#Id
#GeneratedValue
private UUID id;
#NotNull
private String filename;
#NotNull
#Lob #Basic(fetch = FetchType.LAZY)
private byte[] content;
...
Added plugin to pom.xml:
<plugin>
<groupId>org.hibernate.orm.tooling</groupId>
<artifactId>hibernate-enhance-maven-plugin</artifactId>
<executions>
<execution>
<phase>compile</phase>
<configuration>
<failOnError>true</failOnError>
<enableLazyInitialization>true</enableLazyInitialization>
</configuration>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
</plugin>
For me lazy load only worked by compiling and then running it, didn't work on eclipse or intellij for example.
I'm using gradle then I did the following to get it working
Annotate entity
Setup Hibernate gradle plugin
build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.hibernate:hibernate-gradle-plugin:5.4.0.Final"
}
}
apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'org.hibernate.orm'
hibernate {
enhance {
enableLazyInitialization = true
enableDirtyTracking = true
enableAssociationManagement = true
}
}
Entity.java
#Entity
public class Person {
#Id
#GeneratedValue
private Integer id;
#Lob
#Basic(fetch = FetchType.LAZY)
#Column(length = 255, nullable = false)
private String name;
Testing
./gradlew run
Full working example
Lazy loading works for me if I use Blob type instead of byte[].
#Column(name = "BlobField", nullable = false)
#Lob
#Basic(fetch = FetchType.LAZY)
private Blob blobField;
This one gets lazily loaded and if you need to retrieve its value access this field:
String value = IOUtils.toByteArray(entity.getBlobField().getBinaryStream());
A simple workarround using #OneTone notation based on the response of #MohammadReza Alagheband (Why does #Basic(fetch=lazy) doesn't work in my case?) but without the requirement of create a new table for each required lazy attribute is the following:
#Getter
#Setter
#Entity
#Table(name = "document")
#AllArgsConstructor
#NoArgsConstructor
public class DocumentBody implements java.io.Serializable{
#Column(name = "id", insertable = false)
#ReadOnlyProperty
#Id
#PrimaryKeyJoinColumn
private Integer id;
#Column(name = "body", unique = true, nullable = false, length = 254)
#JsonView({JSONViews.Simple.class, JSONViews.Complete.class})
private String content;
}
#Getter
#Entity
#Setter
#Table(name = "document")
#AllArgsConstructor
#NoArgsConstructor
public class DocumentTitle implements java.io.Serializable{
#Column(name = "id", insertable = false)
#ReadOnlyProperty
#Id
private Integer id;
#Column(name = "title", unique = true, nullable = false, length = 254)
#JsonView({JSONViews.Simple.class, JSONViews.Complete.class})
private String content;
}
public class Document implements java.io.Serializable {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
#JsonView({JSONViews.Simple.class, JSONViews.Complete.class})
private Integer id;
//Also it is posssible to prove with #ManyToOne
#OneToOne(fetch = FetchType.LAZY, optional = false, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
#JoinColumn(name = "id", referencedColumnName = "id", nullable = false)
#JsonView({JSONViews.Simple.class, JSONViews.Complete.class})
private DocumentTitle title;
#OneToOne(fetch = FetchType.LAZY, optional = false, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
#JoinColumn(name = "id", referencedColumnName = "id", nullable = false)
#JsonView({JSONViews.Simple.class, JSONViews.Complete.class})
private DocumentBody body;
}