I'm having a big problem trying to make this little program work
Here are my objects:
Class Country
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
public class Country implements Serializable {
private static final long serialVersionUID = 4947071545454L;
private String countryID;
private String countryName;
private Set<City> cities = new HashSet<City>();
public Country() {
}
public Country(String countryID, String countryName, Set<City> cities) {
this.countryID = countryID;
this.countryName = countryName;
this.cities = cities;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
public String getCountryID() {
return countryID;
}
public void setCountryID(String countryID) {
this.countryID = countryID;
}
public String getCountryName() {
return countryName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
public Set<City> getCities() {
return cities;
}
public void setCities(Set<City> cities) {
this.cities = cities;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Country country = (Country) o;
return countryID != null ? countryID.equals(country.countryID) : country.countryID == null;
}
#Override
public int hashCode() {
return countryID != null ? countryID.hashCode() : 0;
}
public boolean addCity(City c){
return cities.add(c);
}
public boolean removeCity(City c){
return cities.remove(c);
}
}
Class City
import java.io.Serializable;
public class City implements Serializable{
private static final long serialVersionUID = 49470713545454L;
private String cityName;
private Country id;
public City(String cityName, Country id) {
this.cityName = cityName;
this.id = id;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public Country getId() {
return id;
}
public void setId(Country id) {
this.id = id;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
City city = (City) o;
if (cityName != null ? !cityName.equals(city.cityName) : city.cityName != null) return false;
return id != null ? id.equals(city.id) : city.id == null;
}
#Override
public int hashCode() {
int result = cityName != null ? cityName.hashCode() : 0;
result = 31 * result + (id != null ? id.hashCode() : 0);
return result;
}
}
An here are my xml archives:
country.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.samuel.hibernate.Country" table="country" catalog="training2">
<id name="country" type="string" column="countryID">
<generator class="assign"/>
</id>
<property name="countryName" type="string">
<column name="countryName" length="40" not-null="true" unique="true" />
</property>
<set name="city" inverse="true" cascade="all">
<key column="countryID" not-null="true" />
<one-to-many class="com.samuel.hibernate.City"/>
</set>
</class>
</hibernate-mapping>
city.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.samuel.hibernate.City" table="city" catalog="training2">
<composite-id name="id">
<key-many-to-one name="countryID" class="com.samuel.hibernate.Country"
column="countryID" />
<key-property name="cityName" column="cityName" type="string"/>
</composite-id>
</class>
</hibernate-mapping>
And here's my main class:
Main class
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
System.out.println("..");
Configuration cfg=new Configuration();
cfg.configure("hibernate.cfg.xml");
// aquí es donde peta si falla conexión con Postgres
//creating seession factory object
System.out.println("Antes de crear sesion");
SessionFactory factory=cfg.buildSessionFactory();
System.out.println("Despues de crear sesion");
//creating session object
Session session=factory.openSession();
//creating transaction object
Transaction t=session.beginTransaction();
Set<City> citiesSpain = new HashSet<>();
Country spain = new Country("es","Spain",citiesSpain);
citiesSpain.add(new City("Barcelona",spain));
citiesSpain.add(new City("Madrid",spain));
session.persist(spain);
t.commit();
session.close();
factory.close();
System.out.println("END");
}
}
When I execute this code I get this error message:
Exception in thread "main" org.hibernate.HibernateException: Unable to instantiate default tuplizer [org.hibernate.tuple.component.PojoComponentTuplizer]
at org.hibernate.tuple.component.ComponentTuplizerFactory.constructTuplizer(ComponentTuplizerFactory.java:98)
at org.hibernate.tuple.component.ComponentTuplizerFactory.constructDefaultTuplizer(ComponentTuplizerFactory.java:119)
at org.hibernate.tuple.component.ComponentMetamodel.<init>(ComponentMetamodel.java:68)
at org.hibernate.mapping.Component.getType(Component.java:169)
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:422)
at org.hibernate.mapping.RootClass.validate(RootClass.java:266)
at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:329)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:451)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:710)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:726)
at com.samuel.hibernate.Main.main(Main.java:22)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.hibernate.tuple.component.ComponentTuplizerFactory.constructTuplizer(ComponentTuplizerFactory.java:95)
... 10 more
Caused by: org.hibernate.PropertyNotFoundException: Could not locate getter method for property [com.samuel.hibernate.Country#cityName]
at org.hibernate.internal.util.ReflectHelper.findGetterMethod(ReflectHelper.java:418)
at org.hibernate.property.access.internal.PropertyAccessBasicImpl.<init>(PropertyAccessBasicImpl.java:41)
at org.hibernate.property.access.internal.PropertyAccessStrategyBasicImpl.buildPropertyAccess(PropertyAccessStrategyBasicImpl.java:27)
at org.hibernate.mapping.Property.getGetter(Property.java:308)
at org.hibernate.tuple.component.PojoComponentTuplizer.buildGetter(PojoComponentTuplizer.java:138)
at org.hibernate.tuple.component.AbstractComponentTuplizer.<init>(AbstractComponentTuplizer.java:47)
at org.hibernate.tuple.component.PojoComponentTuplizer.<init>(PojoComponentTuplizer.java:41)
... 15 more
I've tried looking online but I don't seem to find the solution. In my example, one country can have many cities, but one city can only have on country.
This error means that one or more setters/getters is missing. Make sure you define matching getters/setters for all your properties. And make sure that your properties annotated correctly.
I think that problem is that your cities set name is different in a class and in hbm.xml file. In your entity class you defined set as Set<City> cities and in your XML file you defined this property as name="city". So hibernate is searching setters and getters for city named property.
Make sure that variable and property name coincides. And add empty constructor in City.class.
Is there anyway I can have the effect of #ElementCollection without actually having this annotation? I am using Hibernate 3.3, while #ElementCollection and #CollectionTable is only supported for Hibernate 3.5 and beyond. But I really need to use these annotations, for a case like this:
http://www.concretepage.com/hibernate/elementcollection_hibernate_annotation
(Where we get the List of Strings rather than List of the full entity)
You can use the <element> tag to do the same operation, refer to this link from hibernate documentation:
7.2.3. Collections of basic types and embeddable objects
The example given in the link is :
<element
column="column_name" (1)
formula="any SQL expression" (2)
type="typename" (3)
length="L"
precision="P"
scale="S"
not-null="true|false"
unique="true|false"
node="element-name"
/>
1 column (optional): the name of the column holding the collection element values.
2 formula (optional): an SQL formula used to evaluate the element.
3 type (required): the type of the collection element.
Refer to this link for an example:
Collection Mapping
Star.java
private Set<String> planets = new HashSet<String>();
Star.hbm.xml
<set name="planets" table="star_planet">
<key column="star_id" />
<element type="text"/>
</set>
Update:
You have to use either xml mapping or annotations for a given entity class but not both at a time.
If you want to see examples only using annotations then there are so many available if you search in Google, please check and let me know if you have issues in implementing them.
Finally, yes it works with Set of Strings, integers or Long etc.
Update:
Here is a simple example that shows how to use element collections:
User.java
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Table;
#Entity
#Table(name = "TB_User")
public class User {
#Id
#GeneratedValue
private int id;
private String name;
#ElementCollection
#CollectionTable(name = "Addresses", joinColumns = #JoinColumn(name = "user_id"))
#AttributeOverrides({ #AttributeOverride(name = "street1", column = #Column(name = "fld_street")) })
public Set<Address> addresses = new HashSet<Address>();
public User() {
}
public User(String name, Address... addresses){
this.name = name;
this.addresses.addAll(Arrays.asList(addresses));
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Address> getAddresses() {
return addresses;
}
public void setAddresses(Set<Address> addresses) {
this.addresses = addresses;
}
}
Address.java
import javax.persistence.Embeddable;
#Embeddable
public class Address {
private String street1;
public Address() {
}
public Address(String street1) {
this.street1 = street1;
}
public String getStreet1() {
return street1;
}
public void setStreet1(String street1) {
this.street1 = street1;
}
#Override
public String toString() {
return street1;
}
}
Simple logic to test this:
private static void showUsers() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.getTransaction().begin();
List<User> users = session.createQuery("from User").list();
for (User user : users) {
System.out.println(user.getName() + " -- > " + user.getAddresses());
}
session.getTransaction().commit();
}
private static void saveUsers() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.getTransaction().begin();
User user1 = new User("U1", new Address("A1"), new Address("A11"));
User user2 = new User("U2", new Address("A2"));
session.save(user1);
session.save(user2);
session.getTransaction().commit();
}
I have example web application Hibernate 4.3.5 + Derby database 10.10.1.1+ Glassfish4.0 with IDE NetBeans 8.0Beta.
I have the next exception:
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: CUSTOMERV is not mapped
at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:189)
at org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:109)
at org.hibernate.hql.internal.ast.tree.FromClause.addFromElement(FromClause.java:95)
at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromElement(HqlSqlWalker.java:331)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3633)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3522)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:706)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:562)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:299)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:247)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:278)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:206)
... 72 more
Form from index.xhtml
<h:panelGrid id="panel1" columns="2" border="1"
cellpadding="5" cellspacing="1">
<f:facet name="header">
<h:outputText value="Add Customer Information"/>
</f:facet>
<h:outputLabel value="First Name:"/>
<h:inputText value="#{customer.firstName}" id="fn"/>
<h:outputLabel value="Last Name:"/>
<h:inputText value="#{customer.lastName}" id="ln"/>
<h:outputLabel value="Email:"/>
<h:inputText value="#{customer.email}" id="eml"/>
<h:outputLabel value="Date of Birth:"/>
<h:inputText value="#{customer.sd}" id="s"/>
<f:facet name="footer">
<h:outputLabel value="#{customer.msg}" id="msg" styleClass="msg"/>
<h:commandButton value="Save" action="#{customer.saveCustomer}">
</h:commandButton>
</f:facet>
</h:panelGrid>
Customer.java
package com.javaknowledge.entity;
import com.javaknowledge.dao.CustomerDao;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.persistence.*;
#ManagedBean
#SessionScoped
public class Customer implements java.io.Serializable {
private Integer custId;
private String firstName;
private String lastName;
private String email;
private Date dob;
private String sd, msg, selectedname;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public Customer() {
}
public Customer(String firstName, String lastName, String email, Date dob) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.dob = dob;
}
public String getSd() {
return sd;
}
public void setSd(String sd) {
this.sd = sd;
}
public Integer getCustId() {
return this.custId;
}
public void setCustId(Integer custId) {
this.custId = custId;
}
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Column(name = "EMAIL")
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
#Column(name = "DOB")
public Date getDob() {
return this.dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getSelectedname() {
return selectedname;
}
public void setSelectedname(String selectedname) {
this.selectedname = selectedname;
}
public void saveCustomer() {
try {
Date d = sdf.parse(sd);
System.out.println(d);
this.dob = d;
} catch (ParseException e) {
e.printStackTrace();
}
CustomerDao dao = new CustomerDao();
dao.addCustomer(this);
this.msg = "Member Info Saved Successfull!";
clearAll();
}
public void updateCustomer() {
try {
Date d = sdf.parse(sd);
System.out.println(d);
this.dob = d;
} catch (ParseException e) {
e.printStackTrace();
}
CustomerDao dao = new CustomerDao();
dao.updateCustomer(this);
this.msg = "Member Info Update Successfull!";
clearAll();
}
public void deleteCustomer() {
CustomerDao dao = new CustomerDao();
dao.deleteCustomer(custId);
this.msg = "Member Info Delete Successfull!";
clearAll();
}
public List<Customer> getAllCustomers() {
List<Customer> users = new ArrayList<Customer>();
CustomerDao dao = new CustomerDao();
users = dao.getAllCustomers();
return users;
}
public void fullInfo() {
CustomerDao dao = new CustomerDao();
List<Customer> lc = dao.getCustomerById(selectedname);
System.out.println(lc.get(0).firstName);
this.custId = lc.get(0).custId;
this.firstName = lc.get(0).firstName;
this.lastName = lc.get(0).lastName;
this.email = lc.get(0).email;
this.dob = lc.get(0).dob;
this.sd = sdf.format(dob);
}
private void clearAll() {
this.firstName = "";
this.lastName = "";
this.sd = "";
this.email = "";
this.custId=0;
}
}
hibernate.cfg.xml
<?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.dialect">org.hibernate.dialect.DerbyDialect</property>
<property name="hibernate.connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
<property name="hibernate.connection.url">jdbc:derby://localhost:1527/derbyDB</property>
<property name="hibernate.connection.username">user1</property>
<property name="hibernate.connection.password">user1</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<property name="c3p0.min_size">1</property>
<property name="c3p0.max_size">5</property>
<property name="c3p0.timeout">300</property>
<property name="c3p0.max_statements">50</property>
<property name="c3p0.idle_test_period">300</property>
<mapping class="com.javaknowledge.entity.Customer" resource="com/javaknowledge/entity/Customer.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Customer.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.javaknowledge.entity.Customer" table="CUSTOMERV" schema="APP">
<id name="custId" type="java.lang.Integer">
<column name="cust_id" />
<generator class="increment" />
</id>
<property name="firstName" type="string">
<column name="first_name" length="45" not-null="true" />
</property>
<property name="lastName" type="string">
<column name="last_name" length="45" not-null="true" />
</property>
<property name="email" type="string">
<column name="email" length="45" not-null="true" />
</property>
<property name="dob" type="date">
<column name="dob" length="10" not-null="true" />
</property>
</class>
</hibernate-mapping>
Finally I found a mistake! Hope this is useful to someone. When doing a request to the database(in my case it Apache Derby), name of base need write the first letter upper case other in lower case.
This is wrong query:
session.createQuery("select first_name from CUSTOMERV").
This is valid query
session.createQuery("select first_name from Customerv").
And class entity must be same name as database, but I'm not sure.
in HQL query, Don't write the Table name, write your Entity class name in your query like
String s = "from Entity_class name";
query qry = session.createUqery(s);
In my case I just forgot to add nativeQuery = true
#Query( value = "some sql query ...", nativeQuery = true)
For Spring Boot with Spring Data JPA
If you are using the JPA annotations to create the entities and then make sure that the table name is mapped along with #Table annotation instead of #Entity.
Incorrectly mapped :
#Entity(name="DB_TABLE_NAME")
public class DbTableName implements Serializable {
....
....
}
Correctly mapped entity :
#Entity
#Table(name="DB_TABLE_NAME")
public class DbTableName implements Serializable {
....
....
}
hibernate.cfg.xml file should have the mapping for the tables like below. Check if it is missing in your file.
......
<hibernate-configuration>
......
......
<session-factory>
......
<mapping class="com.test.bean.dbBean.testTableHibernate"/>
......
</session-factory>
</hibernate-configuration>
.....
None of the other solution worked for me.
Even if I don't think its the best practice, I Had to add it into the code like this
configuration.addAnnotatedClass(com.myOrg.entities.Person.class);
here
public static SessionFactory getSessionFactory() {
Configuration configuration = new Configuration().configure();
configuration.addAnnotatedClass(com.myOrg.entities.Person.class);
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties());
SessionFactory sessionFactory = configuration.buildSessionFactory(builder.build());
return sessionFactory;
}
May be this will make it more clear, and of course makes sense too.
#Entity
#Table(name = "users")
/**
*
* #author Ram Srinvasan
* Use class name in NamedQuery
* Use table name in NamedNativeQuery
*/
#NamedQueries({ #NamedQuery(name = "findUserByName", query = "from User u where u.name= :name") })
#NamedNativeQueries({ #NamedNativeQuery(name = "findUserByNameNativeSQL", query = "select * from users u where u.name= :name", resultClass = User.class) })
public class User implements Principal {
...
}
There is one more chance to get this exception even we used class name i.e., if we have two classes with same name in different packages. we'll get this problem.
I think hibernate may get ambiguity and throws this exception, so the solution is to use complete qualified name(like com.test.Customerv)
I added this answer that will help in scenario as I mentioned. I got the same scenario got stuck for some time.
I too have faced similar issue when i started to work on Hibernate. All in all i can say is in the createQuery one needs to pass the name of the entity class not the table name to which the entity is mapped to.
In Hibernate,
session.createQuery("select first_name from Customerv").
The Customerv is your Entity Name, not your Table Name
It means your table is not mapped to the JPA.
Either Name of the table is wrong (Maybe case sensitive), or you need to put an entry in the XML file.
Happy Coding :)
Other persons that are using mapping classes for Hibernate, make sure that have addressed correctly to model package in sessionFactory bean declaration in the following part:
<property name="packagesToScan" value="com.mblog.model"></property>
In my case: spring boot 2 ,multiple datasource(default and custom). entityManager.createQuery go wrong: 'entity is not mapped'
while debug, i find out that the entityManager's unitName is wrong(should be custom,but the fact is default)
the right way:
#PersistenceContext(unitName = "customer1") // !important,
private EntityManager em;
the customer1 is from the second datasource config class:
#Bean(name = "customer1EntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,
#Qualifier("customer1DataSource") DataSource dataSource) {
return builder.dataSource(dataSource).packages("com.xxx.customer1Datasource.model")
.persistenceUnit("customer1")
// PersistenceUnit injects an EntityManagerFactory, and PersistenceContext
// injects an EntityManager.
// It's generally better to use PersistenceContext unless you really need to
// manage the EntityManager lifecycle manually.
// 【4】
.properties(jpaProperties.getHibernateProperties(new HibernateSettings())).build();
}
Then,the entityManager is right.
But, em.persist(entity) doesn't work,and the transaction doesn't work.
Another important point is:
#Transactional("customer1TransactionManager") // !important
public Trade findNewestByJdpModified() {
//test persist,working right!
Trade t = new Trade();
em.persist(t);
log.info("t.id" + t.getSysTradeId());
//test transactional, working right!
int a = 3/0;
}
customer1TransactionManager is from the second datasource config class:
#Bean(name = "customer1TransactionManager")
public PlatformTransactionManager transactionManager(
#Qualifier("customer1EntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
The whole second datasource config class is :
package com.lichendt.shops.sync;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "customer1EntityManagerFactory", transactionManagerRef = "customer1TransactionManager",
// 【1】这里写的是DAO层的路径 ,如果你的DAO放在 com.xx.DAO下面,则这里写成 com.xx.DAO
basePackages = { "com.lichendt.customer1Datasource.dao" })
public class Custom1DBConfig {
#Autowired
private JpaProperties jpaProperties;
#Bean(name = "customer1DatasourceProperties")
#Qualifier("customer1DatasourceProperties")
#ConfigurationProperties(prefix = "customer1.datasource")
public DataSourceProperties customer1DataSourceProperties() {
return new DataSourceProperties();
}
#Bean(name = "customer1DataSource")
#Qualifier("customer1DatasourceProperties")
#ConfigurationProperties(prefix = "customer1.datasource") //
// 【2】datasource配置的前缀,对应上面 【mysql的yaml配置】
public DataSource dataSource() {
// return DataSourceBuilder.create().build();
return customer1DataSourceProperties().initializeDataSourceBuilder().build();
}
#Bean(name = "customer1EntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,
#Qualifier("customer1DataSource") DataSource dataSource) {
return builder.dataSource(dataSource).packages("com.lichendt.customer1Datasource.model") // 【3】这里是实体类的包路径
.persistenceUnit("customer1")
// PersistenceUnit injects an EntityManagerFactory, and PersistenceContext
// injects an EntityManager.
// It's generally better to use PersistenceContext unless you really need to
// manage the EntityManager lifecycle manually.
// 【4】
.properties(jpaProperties.getHibernateProperties(new HibernateSettings())).build();
}
#Bean(name = "customer1TransactionManager")
public PlatformTransactionManager transactionManager(
#Qualifier("customer1EntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
If you by any chance using java for configuration, you may need to check the below bean declaration if you have package level changes. Eg: com.abc.spring package changed to com.bbc.spring
#Bean
public SessionFactory sessionFactory() {
LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(dataSource());
//builder.scanPackages("com.abc.spring"); //Comment this line as this package no longer valid.
builder.scanPackages("com.bbc.spring");
builder.addProperties(getHibernationProperties());
return builder.buildSessionFactory();
}
Should use Entity class name for em.createQuery method
or
Should use em.createNativeQuery method for native query without entity class
With Entity class:
em.createQuery("select first_name from CUSTOMERV")
Without Entity class or Native query:
em.createNativeQuery("select c.first_name from CUSTOMERV c")
Another solution that worked:
The data access object that actually throwed this exception is
public List<Foo> findAll() {
return sessionFactory.getCurrentSession().createQuery("from foo").list();
}
The mistake I did in the above snippet is that I have used the table name foo inside createQuery. Instead, I got to use Foo, the actual class name.
public List<Foo> findAll() {
return sessionFactory.getCurrentSession().createQuery("from Foo").list();
Thanks to this blog: https://www.arundhaj.com/blog/querysyntaxexception-not-mapped.html
Other persons that are using mapping classes for Hibernate, make sure that have addressed correctly to model package in sessionFactory bean declaration in the following part:
public List<Book> list() {
List<Book> list=SessionFactory.getCurrentSession().createQuery("from book").list();
return list;
}
The mistake I did in the above snippet is that I have used the table name foo inside createQuery. Instead, I got to use Foo, the actual class name.
public List<Book> list() {
List<Book> list=SessionFactory.getCurrentSession().createQuery("from Book").list();
return list;
}
add parameter nativeQuery = true
ex:
#Query(value="Update user set user_name =:user_name,password =:password where user_id =:user_id",nativeQuery = true)
In Apache Derby DB, refrain from using table names as "user" or so because they are reserved keywords on Apache Derby but will work fine on MySql.
In the Query, you must specify the name of the Entity class that you want to fetch the data from in the FROM clause of the Query.
List<User> users=session.createQuery("from User").list();
Here, User is the name of my Java Entity class(Consider the casing of the name as in Java it matters.)
in my case was that i forgot the "nativeQuery = true"
Problem partially was solved. Besides creating jdbc/resource(DB Derby) had to create JDBC Connection Pool for db resource in Glassfish admin console, and check it on pinging. Now all CRUD operation work just fine. I check, object Customer in database adding properly, update and delete too. But in Glassfish output log have same exception:
SEVERE: org.hibernate.hql.internal.ast.QuerySyntaxException: CUSTOMERV is not mapped [select concat(first_name, ' ', last_name) as name from CUSTOMERV]
at org.hibernate.hql.internal.ast.QuerySyntaxException.generateQueryException(QuerySyntaxException.java:96)
at org.hibernate.QueryException.wrapWithQueryString(QueryException.java:120)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:234)
.......
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: CUSTOMERV is not mapped
at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:189)
at org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:109)
The mistake in my case is that I used session.createQuery() instead of session.createSQLQuery()
I was reading some interview questions on Hibernate and came across Hibernate derived properties. I was trying a simple example using #Formula annotations but it is not working. Can anyone please tell me what am i missing. Code snippets below
The output and the SQL queries are display at the end.
Entity (Employee.java)
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Formula;
#Entity
#Table(name="EMPLOYEE")
public class Employee implements java.io.Serializable {
private static final long serialVersionUID = -7311873726885796936L;
#Id
#Column(name="ID")
private Integer id;
#Column(name="FIRST_NAME", length=31)
private String firstName;
#Column(name="LAST_NAME", length=31)
private String lastName;
#Column(name="MONTHLY_SALARY")
private float monthlySalary;
#Formula("MONTHLY_SALARY*12")
private float yearlySalary;
public Employee() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public float getMonthlySalary() {
return monthlySalary;
}
public void setMonthlySalary(float monthlySalary) {
this.monthlySalary = monthlySalary;
}
public float getYearlySalary() {
return yearlySalary;
}
}
hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle9iDialect</property>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.username">system</property>
<property name="hibernate.connection.password">system</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:#localhost:1521:XE</property>
<property name="hibernate.cache.use_query_cache">false</property>
<property name="hibernate.jdbc.use_streams_for_binary">true</property>
<property name="hibernate.jdbc.batch_size">0</property>
<property name="hibernate.max_fetch_depth">3</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<property name ="show_sql">true</property>
<mapping class="Employee"/>
<!-- <mapping class="dto.UserDetailsEmbeddedId"/>-->
</session-factory>
</hibernate-configuration>
Tester class
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateTest {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
SessionFactory factory = (new Configuration()).configure().buildSessionFactory();
Session session = factory.openSession();
Employee employee = new Employee();
employee.setFirstName("Tarun");
employee.setLastName("bhatt");
employee.setMonthlySalary(34000);
employee.setId(12);
session.beginTransaction();
session.save(employee);
session.getTransaction().commit();
System.out.println("salary1 = "+employee.getYearlySalary());
session.close();
System.out.println("salary = "+employee.getYearlySalary());
}
}
Output
salary1 = 0.0
salary = 0.0
Queries
Hibernate: create table EMPLOYEE (ID number(10,0) not null, FIRST_NAME varchar2(31 char), LAST_NAME varchar2(31 char), MONTHLY_SALARY float, primary key (ID))
Hibernate: insert into EMPLOYEE (FIRST_NAME, LAST_NAME, MONTHLY_SALARY, ID) values (?, ?, ?, ?)
#Formula annotation is intended to be used during data-retrivial (SELECT in few words) so a read of and Employee looks as
select ID,FIRST_NAME,LAST_NAME,MONTHLY_SALARY,MONTHLY_SALARY*12 as yearlySalary
#Formula doesn't works for insertion or update
While trying to run the following program :
public class Runner {
public static void main(String args[]) {
Configuration config = new Configuration().configure();
SessionFactory sessFact = config.buildSessionFactory();
Session sess = sessFact.openSession();
Transaction trans = sess.beginTransaction();
Person p = new Person();
p.setPersonName("Suhail");
Set<String> set = new HashSet<String>();
set.add("Address-1");
set.add("Address-2");
set.add("Address-3");
p.setAddressSet(set);
sess.save(p);
trans.commit();
}
}
I am getting :
SEVERE: IllegalArgumentException in class: pojo.Address, getter method
of property: addressID
Exception in thread "main" org.hibernate.PropertyAccessException:
IllegalArgumentException occurred calling getter of pojo.Address.addressID
I don't know the reason for this. I am trying to make one to many association between Person and Address class.
mapping xml:
<hibernate-mapping>
<class name="pojo.Person" table="person">
<id name="personID" column="p_id">
<generator class="increment" />
</id>
<property name="personName" column="p_name" />
<set name="addressSet" table="address" cascade="all">
<key column="p_id" />
<one-to-many class="pojo.Address" />
</set>
</class>
<class name="pojo.Address" table="address">
<id name="addressID" column="a_id">
<generator class="increment" />
</id>
<property name="personAddress" column="p_address" />
</class>
</hibernate-mapping>
POJO:
Person
public class Person {
private int personID;
private String personName;
private Set addressSet;
public int getPersonID() {
return personID;
}
public void setPersonID(int personID) {
this.personID = personID;
}
public String getPersonName() {
return personName;
}
public void setPersonName(String personName) {
this.personName = personName;
}
public Set getAddressSet() {
return addressSet;
}
public void setAddressSet(Set addressSet) {
this.addressSet = addressSet;
}
}
Address
public class Address {
private int addressID;
private String personAddress;
public int getAddressID() {
return addressID;
}
public void setAddressID(int addressID) {
this.addressID = addressID;
}
public String getPersonAddress() {
return personAddress;
}
public void setPersonAddress(String personAddress) {
this.personAddress = personAddress;
}
}
SQL that created table
CREATE TABLE person(p_id INTEGER,p_name TEXT,PRIMARY KEY(p_id));
CREATE TABLE address(a_id INTEGER,p_address TEXT);
In your example you add to adress set Strings. But in your configuration you specify Address class.So I think your problem in this lines:
Set<String> set = new HashSet<String>();
set.add("Address-1");
set.add("Address-2");
set.add("Address-3");
You need to change set to Set<Address> and add Address objects in set:
Set<Address> set = new HashSet<>();
Address address = new Address();
address.setPersonAddress("Address-1");
set.add(address);
You can do couple of things without Mapping xml file. Place #Embeddable on ur Pojo of
#Embeddable
#Entity
public class Address {
#Id
private int addressID;
private String personAddress;
public int getAddressID() {
return addressID;
}
public void setAddressID(int addressID) {
this.addressID = addressID;
}
public String getPersonAddress() {
return personAddress;
}
public void setPersonAddress(String personAddress) {
this.personAddress = personAddress;
}
}
Then on
public class Runner {
public static void main(String args[]) {
Configuration config = new Configuration().configure();
SessionFactory sessFact = config.buildSessionFactory();
Session sess = sessFact.openSession();
Transaction trans = sess.beginTransaction();
Person p = new Person();
p.setPersonName("Suhail");
#ElementCollection//To inform hibernate to save this in a seperate table
Set<String> set = new HashSet<String>();
set.add("Address-1");
set.add("Address-2");
set.add("Address-3");
p.setAddressSet(set);
sess.save(p);
trans.commit();
}
}
Better to use Annotations so that we get rid of writing .hbm.xml mapping File