I'm getting a "Could not resolve root entity 'PlayerStats'" UnknownEntityException while try to load a entity with spezific uuid. Inside the Test-Section it works fine but in when I compile it and try to run I received the error.
PlayerStats
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.NamedQueries;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
#Getter
#Setter
#NoArgsConstructor
#Table
#Entity
public class PlayerStats implements Serializable {
public PlayerStats(String UUID, int deaths, int placed, int destroyed, String settings) {
this.UUID = UUID;
setDeaths(deaths);
setPlaced(placedBlocks);
setDestroyed(destroyed);
setSettings(settings);
stringToBool();
}
#Id
#Column
private String UUID;
#Column
private int deaths;
#Column
private int placed;
#Column
private int destroyed;
#Column
private String settings;
...
}
Test
//This works
#Test
public void abc(){
SessionFactory sessionFactory;
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.setProperty("connection.driver_class", "com.mysql.cl.jdbc.Driver");
properties.setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/alldatanew");
properties.setProperty("hibernate.connection.username", "root");
properties.setProperty("hibernate.connection.password", "");
properties.setProperty("hibernate.hbm2ddl.auto", "update");
properties.setProperty("current_session_context_class", "thread");
try {
sessionFactory = new Configuration()
.addProperties(properties)
.addAnnotatedClass(PlayerStats.class)
.buildSessionFactory();
} catch (final Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
Session session = sessionFactory.openSession();
SelectionQuery<PlayerStats> query = session.createSelectionQuery("FROM PlayerStats as P WHERE P.UUID = :uuid", PlayerStats.class);
query.setParameter("uuid", "test3");
PlayerStats playerStats = query.getSingleResult();
System.out.println(playerStats.getUUID());
}
PlayerStatsStore
//This do not work
public PlayerStats findByUUID(String uuid) {
try (Session session = openSession()) {
SelectionQuery<PlayerStats> query = session.createSelectionQuery("FROM PlayerStats as P WHERE P.UUID = :uuid", PlayerStats.class);
query.setParameter("uuid", uuid);
PlayerStats playerStats = query.getSingleResult();
return playerStats;
} catch (final NoResultException exc) {
return null;
}
}
The exception
Exception
Exception
So my question is why it works inside of the test and not after compiling?
What am I doing wrong?
Regards, and thank you very much
I tried to solve my problem with the #NamedQuery annotation. This also doesn't work. So maybe my problem is at the SessionFactory init.
SessionFactory creation:
public SessionFactory createSessionFactory(Class<?>... clazz) {
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.setProperty("connection.driver_class", "com.mysql.cl.jdbc.Driver");
properties.setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/alldatanew");
properties.setProperty("hibernate.connection.username", "root");
properties.setProperty("hibernate.connection.password", "");
properties.setProperty("hibernate.hbm2ddl.auto", "update");
properties.setProperty("current_session_context_class", "thread");
properties.setProperty("hibernate.show_sql", "true");
try {
Configuration configuration = new Configuration();
configuration.addProperties(properties);
for (Class<?> c : clazz) {
configuration.addAnnotatedClass(c.getClass());
}
return configuration.buildSessionFactory();
} catch (final Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
EDIT: as written in the comments, make sure that addAnnotatedClass actually adds PlayerStats to the context. The error indicates that it has not been added.
Looking closer I think I spotted the bug in your original code. Change:
for (Class<?> c : clazz) {
configuration.addAnnotatedClass(c.getClass());
}
To:
for (Class<?> c : clazz) {
configuration.addAnnotatedClass(c);
}
You are already passing the classes, so the old code is registering the class of the class.
Related
SOLVED
The error I made was in the ConnectionUtils class, basically I was configuring hibernate without adding classes.
For anyone habing this problem I will leave new ConnectionUtils class.
PROGRAM INFO
Hi, I'm new to Hibernate framework and I'm developing a simple program that manages an Hostel.
I've made and populated a mySQL database called 'hostel_db' and I want to build a java desktop application
that enables me to interact with the database.
QUERY PROBLEM
I have done some research on how to setup and connect to a database with Hibernate, now I am trying to make a simple query on it to show elements in a table, but I get "QuerySyntaxException: Class is not mapped" as output.
Apparently the connection is done successfully but for some reason I can't figure out where I'm failing.
This is what the program (part of it) looks like:
PS: the connection details (username, password, etc. are done with a ConnectionUtils class).
mySQL DATABASE
CREATE TABLE hostel (
hid VARCHAR(10) PRIMARY KEY,
rooms INT NOT NULL,
profit INT DEFAULT 0,
cost INT DEFAULT 0
);
hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!--Use Hibernate's own connection pool configuration-->
<property name="connection.url">jdbc:mysql://localhost:3306/hostel_db</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!--hibernate dialect-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!--Print sql statement-->
<property name="hibernate.show_sql">false</property>
<!--Format sql-->
<property name="hibernate.format_sql">true</property>
<!-- Load map file -->
<mapping resource="com/hostelmanagment/tables/config/Employee.hbm.xml"/>
<mapping resource="com/hostelmanagment/tables/config/Student.hbm.xml"/>
<mapping resource="com/hostelmanagment/tables/config/Hostel.hbm.xml"/>
</session-factory>
</hibernate-configuration>
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="com.hostelmanagment.tables">
</persistence-unit>
</persistence>
Hostel
import javax.persistence.*;
import java.io.Serializable;
#Entity
#Table (name = "hostel")
public class Hostel implements Serializable {
// DATABASE ATTRIBUTES
#Id
#Column (name = "hid")
private String hid;
#Column (name = "rooms")
private int rooms;
#Column (name = "profit")
private int profit;
#Column (name = "cost")
private int cost;
// OTHER VARIABLES
// CONSTRUCTOR
public Hostel() {}
public Hostel(String hid, int rooms, int profit, int cost) {
this.hid = hid;
this.rooms = rooms;
this.profit = profit;
this.cost = cost;
}
// GETTERS
public int getRooms() {
return rooms;
}
public int getProfit() {
return profit;
}
public int getCost() {
return cost;
}
//
#Override
public String toString() {
return hid + " - Rooms: " + rooms + " - Profit: " + profit + " - Cost: " + cost;
}
}
hostel.hbm.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- name:full path to class:-->
<!-- table: table name: (can be omitted. Use the class name as the table name.)-->
<class name="com.hostelmanagment.tables.Hostel" table="hostel">
<!--Primary key-->
<id name="hid" column="hid">
<!--Primary key generation strategy-->
<generator class="native"></generator>
</id>
<property name="rooms" column="rooms" type="java.lang.Integer"/>
<property name="profit" column="profit" type="java.lang.Integer"/>
<property name="cost" column="cost" type="java.lang.Integer"/>
</class>
</hibernate-mapping>
Main
package com.hostelmanagment;
import com.hostelmanagment.gui.*;
import com.hostelmanagment.tables.Hostel;
import com.hostelmanagment.utils.*;
import javax.persistence.*;
import javax.persistence.Query;
import org.hibernate.*;
import java.util.List;
public class Main {
public static void main(String[] args) {
// Connect to database
EntityManager em = ConnectionUtils.connectToDatabase(ConnectionData.getUsr(), ConnectionData.getPsw()).
createEntityManager();
Session session = ConnectionUtils.connectToDatabaseSession(ConnectionData.getUsr(), ConnectionData.getPsw()).
openSession();
// Test show data from databases
Transaction transaction = session.beginTransaction();
Query query = session.createQuery("from Hostel");
List<?> list = query.getResultList();
Hostel hostel = (Hostel) list.get(0);
System.out.println("\nHostel: \n" + hostel);
// Run GUI
//new HostelMainFrame(em);
}
}
ConnectionUtils
public class ConnectionUtils {
private static Map<String, String> databaseProperties = new HashMap<>();
private static Configuration databaseConfiguration = new Configuration();
private static final String dialect = "org.hibernate.dialect.MySQL5Dialect";
private static final String url = "jdbc:mysql://localhost:3306/hostel_db";
private static final String driver = "com.mysql.jdbc.Driver";
public static EntityManagerFactory connectToDatabase(String username, String password) {
// Try to set up the configuration for hibernate.cfg
try {
databaseConfiguration.configure().
setProperty("hibernate.connection.username", username).
setProperty("hibernate.connection.password", password);
} catch (HibernateException e) {
if (verifyHibernateConfigXml())
throw new RuntimeException("Wrong format for hibernate.cfg.xml");
}
// Build configurations
StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder().
applySettings(databaseConfiguration.getProperties());
SessionFactory factory = databaseConfiguration.buildSessionFactory(ssrb.build());
// Setup persistence
persistenceSetup(username, password);
// Return EntityManagerFactory
return Persistence.createEntityManagerFactory("com.hostelmanagment.tables", databaseProperties);
}
public static SessionFactory connectToDatabaseSession(String username, String password) {
// Try to set up the configuration for hibernate.cfg
try {
databaseConfiguration.configure().
setProperty("hibernate.connection.username", username).
setProperty("hibernate.connection.password", password);
} catch (HibernateException e) {
if (verifyHibernateConfigXml())
throw new RuntimeException("Wrong format for hibernate.cfg.xml");
}
// Build configurations
StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder().
applySettings(databaseConfiguration.getProperties());
// Setup persistence
persistenceSetup(username, password);
return databaseConfiguration.buildSessionFactory(ssrb.build());
}
private static boolean verifyHibernateConfigXml() {
try {
InputStream is = ConnectionUtils.class.getClassLoader().getResourceAsStream("hibernate.cfg.xml");
return true;
} catch (NullPointerException npe) {
throw new RuntimeException("hibernate.cfg.xml don't exists");
}
}
private static void persistenceSetup(String username, String password) {
databaseProperties.put("hibernate.connection.driver_class", driver);
databaseProperties.put("hibernate.connection.url", url);
databaseProperties.put("hibernate.connection.autocommit", "false");
databaseProperties.put("hibernate.connection.username", username);
databaseProperties.put("hibernate.connection.password", password);
databaseProperties.put("hibernate.dialect", dialect);
databaseProperties.put("hibernate.connection.CharSet", "utf8");
databaseProperties.put("hibernate.connection.characterEncoding", "utf8");
databaseProperties.put("hibernate.connection.useUnicode", "true");
databaseProperties.put("hibernate.show_sql", "true");
databaseProperties.put("hibernate.hbm2ddl.auto", "update");
}
}
FOLDER STRUCTURE
STACK TRACE
NEW CONNECTION UTILS
public class ConnectionUtils {
private static Map<String, String> databaseProperties = new HashMap<>();
private static Configuration databaseConfiguration = new Configuration();
private static final String dialect = "org.hibernate.dialect.MySQL5Dialect";
private static final String url = "jdbc:mysql://localhost:3306/".concat(ConnectionData.getDbName());
private static final String driver = "com.mysql.cj.jdbc.Driver";
private static EntityManagerFactory emf;
private static SessionFactory sessionFactory;
public ConnectionUtils(){}
public void setUpProperties() {
propertiesSetup(ConnectionData.getUsr(), ConnectionData.getPsw());
StandardServiceRegistryBuilder standardServiceRegistryBuilder = new StandardServiceRegistryBuilder().
applySettings(databaseConfiguration.getProperties());
//standardServiceRegistryBuilder.configure();
emf = Persistence.createEntityManagerFactory(ConnectionData.getTablesPackage(), databaseProperties);
sessionFactory = databaseConfiguration.buildSessionFactory(standardServiceRegistryBuilder.build());
}
public EntityManagerFactory getEntityManagerFactory() {
return emf;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
private static void propertiesSetup(String username, String password) {
// Try to set up the configuration for hibernate.cfg
try {
databaseConfiguration.configure().
setProperty("hibernate.connection.username", username).
setProperty("hibernate.connection.password", password);
} catch (HibernateException e) {
if (verifyHibernateConfigXml())
throw new RuntimeException("Wrong format for hibernate.cfg.xml");
}
// Setup persistence
persistenceSetup(username, password);
}
private static boolean verifyHibernateConfigXml() {
try {
InputStream is = ConnectionUtils.class.getClassLoader().getResourceAsStream("hibernate.cfg.xml");
return true;
} catch (NullPointerException npe) {
throw new RuntimeException("hibernate.cfg.xml don't exists");
}
}
private static void persistenceSetup(String username, String password) {
try {
for (Class cls : getEntityClassesFromPackage(ConnectionData.getTablesPackage())) {
databaseConfiguration.addAnnotatedClass(cls);
}
} catch (Exception ex) { ex.printStackTrace(); }
databaseProperties.put("hibernate.connection.driver_class", driver);
databaseProperties.put("hibernate.connection.url", url);
databaseProperties.put("hibernate.connection.autocommit", "false");
databaseProperties.put("hibernate.connection.username", username);
databaseProperties.put("hibernate.connection.password", password);
databaseProperties.put("hibernate.dialect", dialect);
databaseProperties.put("hibernate.connection.CharSet", "utf8");
databaseProperties.put("hibernate.connection.characterEncoding", "utf8");
databaseProperties.put("hibernate.connection.useUnicode", "true");
databaseProperties.put("hibernate.show_sql", "true");
databaseProperties.put("hibernate.hbm2ddl.auto", "update");
}
private static List<Class<?>> getEntityClassesFromPackage(String packageName) throws ClassNotFoundException, URISyntaxException {
List<String> classNames = getClassNamesFromPackage(packageName);
List<Class<?>> classes = new ArrayList<Class<?>>();
for (String className : classNames) {
Class<?> cls = Class.forName(packageName + "." + className);
Annotation[] annotations = cls.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(cls.getCanonicalName() + ": " + annotation.toString());
if (annotation instanceof javax.persistence.Entity) {
classes.add(cls);
}
}
}
return classes;
}
private static ArrayList<String> getClassNamesFromPackage(String packageName) throws URISyntaxException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
ArrayList<String> names = new ArrayList<String>();
packageName = packageName.replace(".", "/");
URL packageURL = classLoader.getResource(packageName);
URI uri = new URI(packageURL.toString());
File folder = new File(uri.getPath());
File[] files = folder.listFiles();
for (File file: files) {
String name = file.getName();
name = name.substring(0, name.lastIndexOf('.')); // remove ".class"
names.add(name);
}
return names;
}
}
I am trying to use hibernate5:
my configurate class:
#Configuration
#EnableTransactionManagement
public class HibernateConfiguration {
#Value("${db.driver}")
private String DB_DRIVER;
#Value("${db.password}")
private String DB_PASSWORD;
#Value("${db.url}")
private String DB_URL;
#Value("${db.username}")
private String DB_USERNAME;
#Value("${hibernate.dialect}")
private String HIBERNATE_DIALECT;
#Value("${hibernate.show_sql}")
private String HIBERNATE_SHOW_SQL;
#Value("${entitymanager.packagesToScan}")
private String ENTITYMANAGER_PACKAGES_TO_SCAN;
#Value("${hibernate.enable_lazy_load_no_trans}")
private String ENABLE_LAZY_LOAD;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(ENTITYMANAGER_PACKAGES_TO_SCAN);
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public PlatformTransactionManager hibernateTransactionManager() {
HibernateTransactionManager transactionManager
= new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(DB_DRIVER);
dataSource.setUrl(DB_URL);
dataSource.setUsername(DB_USERNAME);
dataSource.setPassword(DB_PASSWORD);
return dataSource;
}
private final Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", HIBERNATE_DIALECT);
hibernateProperties.put("hibernate.show_sql", HIBERNATE_SHOW_SQL);
hibernateProperties.put("hibernate.enable_lazy_load_no_trans", ENABLE_LAZY_LOAD);
return hibernateProperties;
}
}
and my DAO:
#Service("userDAO_mysql")
#Transactional
public class UserDAOImpl implements UserDAO {
#Override
public User getAllUsers(){
Session session = sessionFactory.getCurrentSession();
return session.getSession().get(User.class,0);
}
}
My user has FetchType set to LazyLoad to any #OneToMany relation. However, all relations are loaded just by using:
User u = userDAO.getAllUsers();
I have failed to make it otherwise.
Are there any tricks for this to work as it should? Or i am missing something?
Thanks for help!
// edit , just for claryfication, i have been using this up to this date, and decided to use more relevant way:
public class HibernateUtil {
private static StandardServiceRegistry registry;
private static SessionFactory sessionFactory;
public static SessionFactory getSessionFactory() {
if (sessionFactory == null) {
try {
// Create registry
registry = new StandardServiceRegistryBuilder()
.configure()
.build();
// Create MetadataSources
MetadataSources sources = new MetadataSources(registry);
// Create Metadata
Metadata metadata = sources.getMetadataBuilder().build();
// Create SessionFactory
sessionFactory = metadata.getSessionFactoryBuilder().build();
} catch (Exception e) {
e.printStackTrace();
if (registry != null) {
StandardServiceRegistryBuilder.destroy(registry);
}
}
}
return sessionFactory;
}
public static void shutdown() {
if (registry != null) {
StandardServiceRegistryBuilder.destroy(registry);
}
}
}
public User getUserById(int id) {
User u = null;
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
Integer employeeID = null;
try {
tx = session.beginTransaction();
Criteria cr = session.createCriteria(User.class).add(Restrictions.eq("id",id));
u = (User) cr.uniqueResult();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return u;
}
This way lazy loading was not ignored, the lazy load:
#OneToMany(mappedBy="user",cascade=CascadeType.ALL,fetch=FetchType.LAZY,
orphanRemoval=true)
public Set<Topic> getTopics() {
return topics;
}
public void setTopics(Set<Topic> topics) {
this.topics = topics;
}
lets assume that parent is the first entity which has #onetomany relation to children and the lazyload is set true on #onetomany
you can still call the parent.getChildren() method in the service class,it will fetch them,but if you try this in your controller class,you will get the lazy load exception.
this scenario is useful when u only need the parent,so u just retrieve the parent object.
if you need the children,u call the method you just mentioned and it will retrieve all children of that parent for you(in your controller class)
i am a beginner to spring boot and I am performing a CRUD operation on database using spring boot .the program complies with no error but during running my application i encounter an error: NullPointerException.
this is my program:-
CrudOperationApplication.java
package com;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class CrudOperationApplication {
public static void main(String[] args) {
SpringApplication.run(CrudOperationApplication.class, args);
}
}
DatabaseCon.java
package com;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#ComponentScan({ "com" })
#Configuration
#EnableTransactionManagement
#PropertySource(value = { "classpath:application.properties" })
public class DatabaseCon {
#Autowired
private Environment environment;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
Employee.java
package com;
import javax.persistence.*;
#Entity
#Table(name="Employee")
public class Employee {
#Id
int id;
#Column(name="name")
String name;
#Column(name="salary")
int salary;
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 int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
#Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + "]";
}
}
EmployeeDao.java
package com;
public interface EmployeeDao {
String insertValue(Employee e);
String updateValue(Employee e);
String deleteValue(Employee e);
String getValue();
String getSpecificValue( int id);
}
EmployeeController.java
package com;
import java.util.*;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class EmployeeController implements EmployeeDao{
HibernateTemplate ht;
Employee e=new Employee();
void setHt(HibernateTemplate ht)
{
this.ht=ht;
}
// for insertion into database
#RequestMapping(value="/",method=RequestMethod.POST)
public String insertValue(Employee e)
{
e.setId(1);
e.setName("james");
e.setSalary(7000);
ht.persist(e);
return "value saved to database";
}
//for updation
#RequestMapping(value="/",method=RequestMethod.PUT)
public String updateValue(Employee e)
{
ht.update(e);
return "value updated to database";
}
//for deletion
#RequestMapping(value="/",method=RequestMethod.DELETE)
public String deleteValue(Employee e)
{
ht.delete(e);
return "value deleted from database";
}
// get stored values from d.b
#RequestMapping(value="/",method=RequestMethod.GET)
public String getValue()
{
List<Employee> al=new ArrayList<Employee>();
al=ht.loadAll(Employee.class);
return ""+al;
}
// to get particular value from d.b
#SuppressWarnings("unchecked")
#RequestMapping(value="/{id}",method=RequestMethod.GET)
public String getSpecificValue(#PathVariable int id)
{
List<Employee> al=new ArrayList<Employee>();
al=(List<Employee>) ht.load(Employee.class,id);
return ""+al;
}
}
Application.properties
jdbc.driverClassName = org.postgresql.Driver
jdbc.url = jdbc:postgresql://localhost:5432/testc
jdbc.db=testc
jdbc.port=5432
jdbc.ip= 127.0.0.1
jdbc.username = postgres
jdbc.password = root
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
hibernate.show_sql = true
hibernate.format_sql = true
You are using Spring Boot then use Spring Boot. Currently you are trying really hard to NOT use Spring Boot.
First instead of you manually configuration a DataSource let Spring Boot do it for you. Remove the #Bean for DataSource and add spring.datasource properties in your application.properties (or simply rename the existing ones).
spring.datasource.url=jdbc:postgresql://localhost:5432/testc
spring.datasource.username=postgres
spring.datasource.password=root
Next instead of using plain Hibernate I strongly suggest to start using JPA instead. So remove the definition for the LocalSessionFactoryBean and HibernateTransactionManager. Simply add the following properties to your configuration.
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
Now basically have an empty configuration class simply remove it. Spring Boot will already component-scan for you, create JPA, enable transactions.
In your controller/dao hybrid (which is a bad thing imho!) instead of the HibernateTemplate use the EntityManager instead. However I would suggest separating the dao and controller functionality.
#Repository
#Transactional
public class EmployeeDaoJpa implements EmployeeDao {
#PersistenceContext
private EntityManager em;
// Method implementations using the EntityManager
}
Now in your controller use that dao.
#RestController
public class EmployeeController {
private final EmployeeDao dao;
#Autowired
public EmployeeController(EmployeeDao dao) {
this.dao=dao;
}
// for insertion into database
#RequestMapping(value="/",method=RequestMethod.POST)
public String insertValue(Employee e) {
e.setId(1);
e.setName("james");
e.setSalary(7000);
dao.insertvalue(e);
return "value saved to database";
}
//for updation
#RequestMapping(value="/",method=RequestMethod.PUT)
public String updateValue(Employee e) {
dao.updateValue(e);
return "value updated to database";
}
//for deletion
#RequestMapping(value="/",method=RequestMethod.DELETE)
public String deleteValue(Employee e) {
ht.delete(e);
return "value deleted from database";
}
// get stored values from d.b
#RequestMapping(value="/",method=RequestMethod.GET)
public String getValue() {
return ""+dao.findAll();
}
// to get particular value from d.b
#SuppressWarnings("unchecked")
#RequestMapping(value="/{id}",method=RequestMethod.GET)
public String getSpecificValue(#PathVariable int id) {
return ""+dao.findOne(id);
}
}
Another tip don't use com as your package first it is to lowlevel and when Spring or your container starts scanning the com package it will scan everything in the com package. Like everything in jar files starting with com. So invent a better package naming.
In the end you now only have your controller, repository class and interface and finally your application class. No more configuration class that is all nicely in your application.properties.
I have been reading the book 'Java Persistence with Hibernate' and downloaded the source code. I am able to run the 'helloworld-native' files with XML mapping, but cannot run the annotated version of those files. Could anyone tell me if they had difficulty with that section or could they point it out step by step please?
The section I cannot pass is 2.2.1 Using Hibernate Annotations
When running 'ant schemaexport' I receive the following error message:
org.hibernate.HibernateException: The dialect was not set. Set the property hibernate dialect.
Which I shouldn't have to do in the XML file as the book does not say to do so. I do it anyway and get the following message....
UserSuppliedConnectionProvider:23 - No connection properties specified - the user must supply the JDBC connection
In HibernateUtil I have tried both...
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
sessionFactory = new Configuration().configure().buildSessionFactory();
Hibernate.cfg
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- ... Many property settings ... -->
<!-- List of annotated classes-->
<mapping class="hello.Message"/>
</session-factory>
</hibernate-configuration>
HibernateUtil.java
package persistence;
import org.hibernate.*;
import org.hibernate.cfg.*;
import org.hibernate.cfg.AnnotationConfiguration;
/**
* Startup Hibernate and provide access to the singleton SessionFactory
*/
public class HibernateUtil {
private static SessionFactory sessionFactory;
static {
try {
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
// Alternatively, we could look up in JNDI here
return sessionFactory;
}
public static void shutdown() {
// Close caches and connection pools
getSessionFactory().close();
}
}
Message.java
package hello;
import javax.persistence.*;
#Entity
#Table(name = "MESSAGES")
public class Message {
#Id #GeneratedValue
#Column(name = "MESSAGE_ID")
private Long id;
#Column(name = "MESSAGE_TEXT")
private String text;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "NEXT_MESSAGE_ID")
private Message nextMessage;
private Message() {}
public Message(String text) {
this.text = text;
}
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Message getNextMessage() {
return nextMessage;
}
public void setNextMessage(Message nextMessage) {
this.nextMessage = nextMessage;
}
}
HelloWorld.java
package hello;
import org.hibernate.*;
import persistence.*;
import java.util.*;
public class HelloWorld {
public static void main(String[] args) {
// ############################################################################
// First unit of work
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
Message message = new Message("Hello World");
session.save(message);
tx.commit();
session.close();
// ############################################################################
// Second unit of work
Session secondSession = HibernateUtil.getSessionFactory().openSession();
Transaction secondTransaction = secondSession.beginTransaction();
List messages =
secondSession.createQuery("from Message m order by m.text asc").list();
System.out.println( messages.size() + " message(s) found:" );
for ( Iterator iter = messages.iterator(); iter.hasNext(); ) {
Message loadedMsg = (Message) iter.next();
System.out.println( loadedMsg.getText() );
}
secondTransaction.commit();
secondSession.close();
// ############################################################################
// Third unit of work
Session thirdSession = HibernateUtil.getSessionFactory().openSession();
Transaction thirdTransaction = thirdSession.beginTransaction();
// message.getId() holds the identifier value of the first message
Message loadedMessage = (Message) thirdSession.get( Message.class, message.getId());
loadedMessage.setText( "Greetings Earthling" );
loadedMessage.setNextMessage(
new Message( "Take me to your leader (please)" )
);
thirdTransaction.commit();
thirdSession.close();
// ############################################################################
// Final unit of work (just repeat the query)
// TODO: You can move this query into the thirdSession before the commit, makes more sense!
Session fourthSession = HibernateUtil.getSessionFactory().openSession();
Transaction fourthTransaction = fourthSession.beginTransaction();
messages =
fourthSession.createQuery("from Message m order by m.text asc").list();
System.out.println( messages.size() + " message(s) found:" );
for ( Iterator iter = messages.iterator(); iter.hasNext(); ) {
Message loadedMsg = (Message) iter.next();
System.out.println( loadedMsg.getText() );
}
fourthTransaction.commit();
fourthSession.close();
// Shutting down the application
HibernateUtil.shutdown();
}
}
I am using configuration as in the code listed below.
auto create/drop function seams not to work as it should (it does not create/maintain tables in the database (dataSource.setConnectionProperties(hibernateProperties());))
(It works when table is already created in the DB? I think that properties are not taken into consideration here?),
Config
package com.parisibw.persistance;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.parisibw.forms.Contact;
#Configuration
#EnableTransactionManagement
public class HibernateConfig {
#Bean
public SessionFactory sessionFactory() {
return new LocalSessionFactoryBuilder(datasource()).addAnnotatedClasses(Account.class, Contact.class).buildSessionFactory();
}
#Bean
public PlatformTransactionManager transactionManager() {
return new HibernateTransactionManager(sessionFactory());
}
#Bean
public Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.hbm2ddl.auto", "create");
//properties.put("hibernate.connection.driver_class", "org.h2.Driver");
//properties.put("hibernate.connection.url", "jdbc:h2:db/test;CIPHER=AES");
//properties.put("hibernate.connection.username", "root");
//properties.put("hibernate.connection.password", "root root");
//properties.put("hibernate.connection.pool_size", "1");
//properties.put("hibernate.format_sql", "true");
//properties.put("hibernate.use_sql_comments", "true");
//properties.put("hibernate.c3p0.min_size", "5");
//properties.put("hibernate.c3p0.max_size", "20");
//properties.put("hibernate.c3p0.timeout", "300");
//properties.put("hibernate.c3p0.max_statements", "50");
//properties.put("hibernate.c3p0.idle_test_period", "3000");
//properties.put("hibernate.cache.use_second_level_cache", "true");
//properties.put("hibernate.cache.region.factory_class",
//"org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory");
//properties.put("hibernate.cache.use_query_cache", "true");
//properties.put("hibernate.cache.use_minimal_puts", "true");
//properties.put("hibernate.max_fetch_depth", "10");
return properties;
}
#Bean
public DataSource datasource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://dbpath");
dataSource.setUsername("username");
dataSource.setPassword("password");
dataSource.setConnectionProperties(hibernateProperties());
return dataSource;
}
}
Account
#Entity #Table(name="T_ACCOUNT")
public class Account {
#Id
private long id;
#Column
private double cashBalance;
#Column
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public double getCashBalance() {
return cashBalance;
}
public void setCashBalance(double cashBalance) {
this.cashBalance = cashBalance;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "id: " + id + ", balance: " + cashBalance + ", name: " + name;
}
test class
#RequestMapping(value = "/test", method = RequestMethod.GET)
public String homeTest(Model model) {
Account account = new Account();
try{
sessionFactory = new HibernateConfig().sessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
//account.setId(2);
account.setName("Marcin");
account.setCashBalance(1200);
session.save(account);
session.getTransaction().commit();
session.close();
}catch (Exception e) {
logger.info(e.toString());
}
model.addAttribute("serverTime" );
return "test";
}
You're passing your hibernate properties as connection properties for your datasource. Instead, they should be passed to the sessionfactory.
#Bean
public SessionFactory sessionFactory() {
return new LocalSessionFactoryBuilder(datasource())
.addAnnotatedClasses(Account.class, Contact.class)
.addProperties(hibernateProperties())
.buildSessionFactory();
}
See http://docs.jboss.org/hibernate/core/3.6/javadocs/org/hibernate/cfg/Configuration.html?is-external=true (parent class for LocalSessionFactoryBuilder)
The first problem I see here is that you're explicitly creating a new HibernateConfig instead of allowing spring to autowire it. So in your test class add the following property:
#Autowire
private SessionFactory sessionFactory;
Looking deeper, it looks like you might want to read up a little on Spring and IOC because you're kinda doing it in a strange way that looks like you might be a little confused. Everything you're trying to do is actually kinda already built into Spring so you're kinda reinventing the wheel. In short, you're creating new instances of things instead of getting them from spring's context so it has now way to hook things together for you.
Take a look at how this is being done here (yes it has other problems, but you should be able to get the general idea): Proper way to autowire a Hibernate Session in a Spring Transaction JUnit test