Hibernate5 ignores Lazy load - java

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)

Related

Spring Boot two databases JPA

I have two Postgres databases and a SpringBoot application. I connect to each database and perform separate transactions on each successfully. This has working fine as long as I have been using normal queries on my secondary database.
Primary: powwow
secondary: pims
As soon as I try execute a native query on the secondary (pims) database, it thinks it is looking at the primary database (powwow).
e.g. This "merchants" table is on the secondary database (pims):
PSQLException: ERROR: relation "merchants" does not exist
If I run the same native query but over a table on the primary (powwow) database, it works fine. So I think there's a problem with my config where I define the secondary (pims) datasource.
If I run a non native query over the secondary (pims) database using a repository in the com.xxxx.powwow.entities.pims package, it works fine.
Question
How do I execute a native query using a dao in the com.xxxx.powwow.dao.pims package?
PersistencePimsAutoConfiguration.java
#Configuration
#PropertySource({"classpath:application.properties"})
#EnableJpaRepositories(
basePackages = {"com.xxxx.powwow.dao.pims", "com.xxxx.powwow.repositories.pims"},
entityManagerFactoryRef = "pimsEntityManager",
transactionManagerRef = "pimsTransactionManager")
public class PersistencePimsAutoConfiguration {
private Logger logger = LogManager.getLogger(PersistencePimsAutoConfiguration.class);
#Value("${spring.datasource1.jdbc-url}")
private String url;
#Value("${spring.datasource1.username}")
private String username;
#Value("${spring.jpa.hibernate.ddl-auto}")
private String hbm2ddl;
#Value("${spring.jpa.database-platform}")
private String platform;
#Value("${spring.jpa.properties.hibernate.dialect}")
private String dialect;
#Value("${spring.profiles.active}")
private String profile;
#Bean
#ConfigurationProperties(prefix="spring.datasource1")
public DataSource pimsDataSource() {
return DataSourceBuilder.create().build();
}
//#Bean(name = "pimsEntityManager")
#Bean
public LocalContainerEntityManagerFactoryBean pimsEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(pimsDataSource());
em.setPackagesToScan(new String[] {"com.xxxx.powwow.entities.pims"});
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", hbm2ddl);
properties.put("hibernate.dialect", dialect);
em.setJpaPropertyMap(properties);
String host = null;
try {
host = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
logger.info("Setting spring.datasource1 (pims): hibernate.hbm2ddl.auto='"+hbm2ddl+"', platform='"+platform+"', url='"+url+"', username='"+username+"', host='"+host+"', profile='"+profile+"'.");
return em;
}
#Bean
public PlatformTransactionManager pimsTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(pimsEntityManager().getObject());
return transactionManager;
}
}
BookingHistoryReportDao.java (package com.xxxx.powwow.dao.pims)
#Component
#Transactional("pimsTransactionManager")
public class BookingHistoryReportDao {
private Logger logger = LogManager.getLogger(BookingHistoryReportDao.class);
#PersistenceContext
private EntityManager entityManager;
public void executeBookingHistoryReport(Date startDate, Date endDate, List<Integer> companyIds) {
final String sql = getSQLBookingHistoryReportDao();
try {
Query qry = entityManager.createNativeQuery(sql);
List<String> merchants = qry.getResultList();
logger.info("done");
} catch (Exception e) {
logger.error("Error executing query for BookingHistoryReport.", e);
logger.info(sql);
}
}
private String getSQLBookingHistoryReportDao() {
return "select company_name from Merchants limit 100";
}
}
I managed to get this working by using the PersistenceUnitName.
e.g.
set it in the config:
em.setPersistenceUnitName("pimsPersistenceUnit");
and reference in the DAO:
#PersistenceContext(unitName = "pimsPersistenceUnit")
private EntityManager entityManager;

Spring boot launch hibernate config not found

Hi there I am trying to create a student webapp with spring boot but i can't seem to get it to run as an error appears every time that hibernate sessionfactory can't be found and i should include a bean type of equal type in my configuration.
I thought I properly configured the webapp properly but i cant seem to get it to find my hibernate session factory which i configured in my DAO, any help on where i'm going wrong would be appreciated.
Here Spring boot launcher class
#SpringBootApplication(exclude = HibernateJpaAutoConfiguration.class)
#ComponentScan({"model", "controller", "dao", "service"})
public class StudentsApplication {
public static void main(String[] args) {
SpringApplication.run(StudentsApplication.class, args);
}
}
Here is my DAO class
#Repository
#Transactional
public class StudentDao {
#Autowired
SessionFactory sessionFactory;
public Student getStudent(final int id) {
#SuppressWarnings("unchecked")
TypedQuery<Student> q = sessionFactory.getCurrentSession().createQuery(
"from student where = id").setParameter("id", id);
return q.getSingleResult();
}
public List<Student> getAllStudents() {
#SuppressWarnings("unchecked")
TypedQuery<Student> q = sessionFactory.getCurrentSession().createQuery(
"from student");
return q.getResultList();
}
public void addStudent(final Student student) {
sessionFactory.getCurrentSession().save(student);
}
public void updateStudent(final Student student) {
sessionFactory.getCurrentSession().saveOrUpdate(student);
}
public void deleteStudent(final int id) {
sessionFactory.getCurrentSession().createQuery(
"delete from student where = id").setParameter("id", id)
.executeUpdate();
}
}
here is my configuration class
#Configuration
#PropertySource({"classpath:application.properties"})
public class DbConfig {
#Autowired
private Environment environment;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getProperty("jdbc.url"));
dataSource.setUsername(environment.getProperty("jdbc.username"));
dataSource.setPassword(environment.getProperty("jdbc.password"));
return dataSource;
}
#Bean
public LocalSessionFactoryBean getSessionFactory() {
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
factoryBean.setDataSource(dataSource());
Properties props = new Properties();
props.put("format_sql", "true");
props.put("hibernate.show_sql", "true");
factoryBean.setHibernateProperties(props);
factoryBean.setPackagesToScan("com.alpheus.students.entity");
// factoryBean.setAnnotatedClasses(Student.class);
return factoryBean;
}
#Bean
public HibernateTransactionManager getTransactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(getSessionFactory().getObject());
return transactionManager;
}
}
here is my properties file
# Connection url for the database
spring.datasource.url=jdbc:mysql://localhost:3308/week04
spring.datasource.username=user
spring.datasource.password=pass
server.port=9999
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
#view resolver
spring.mvc.view.prefix=/views/
spring.mvc.view.suffix=.jsp
here is my controller class
#Controller
public class StudentController {
#Autowired
private StudentService studentService;
#GetMapping("/home")
public String getAllStudents(Model studentsModel) {
List<Student> listStudents = studentService.getAllStudents();
studentsModel.addAttribute("listStudents", listStudents);
return "student-list";
}
#GetMapping("/student/{id}")
public String editStudent(#PathVariable int id, Model studentModel) {
studentModel.addAttribute("student", studentService.getStudent(id));
return "student-form";
}
#PostMapping("/student/new")
public String saveStudent(#ModelAttribute("student")Student student) {
studentService.addStudent(student);
return "redirect:/";
}
#GetMapping("/student")
public String showNewForm() {
return "student-form";
}
#PostMapping("/student/update/{id}")
public String updateStudent(#ModelAttribute("student") Student student) {
studentService.updateStudent(student);
return "redirect:/";
}
#GetMapping(value = "/student/delete/{id}")
public String deleteStudent(#PathVariable int id) {
studentService.deleteStudent(id);
return "redirect:/";
}
}

Annotations #ActiveProfile doesn't work in a Spring app

I'm not using spring-boot in this app.
I'm testing profiles to use different datasource in integration tests.
I have entity User as follow:
#Table(name = "user_inf")
#Entity
#NamedQuery(name="User.findById", query="select u from User u where u.id=:id")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
#Column(name = "userName", length = 25)
private String userName;
#Column(name = "userEmail", unique = true, length = 320)
private String userEmail;
}
for that entity I have the service and dao(Service only invokes dao method)
UserDao :
#Repository
#Transactional
public class UserDaoImpl implements UserDao {
#PersistenceContext
private EntityManager entityManager;
#Override
public User findById(Long id) {
TypedQuery<User> query = entityManager.createNamedQuery("User.findById", User.class);
query.setParameter("id", id);
return query.getSingleResult();
}
}
User service :
#Service
public class UserServiceImpl implements UserService{
#Autowired
private UserDao userDao;
#Override
public User getUser(Long id) {
return userDao.findById(id);
}
}
#Configuration
#PropertySource(value = {"classpath:database/jdbc.properties"})
#EnableTransactionManagement
#ComponentScan({"com.example.test.repository", "com.example.test.service"})
public class SpringConfig {
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_HIBERNATE_MAX_FETCH_DEPTH = "hibernate.max_fetch_depth";
private static final String PROPERTY_NAME_HIBERNATE_JDBC_FETCH_SIZE = "hibernate.jdbc.fetch_size";
private static final String PROPERTY_NAME_HIBERNATE_JDBC_BATCH_SIZE = "hibernate.jdbc.batch_size";
private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
private static final String ENTITY_MANAGER_PACKAGES_TO_SCAN = "com.example.test.entity";
#Autowired
private Environment env;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
return dataSource;
}
#Bean
#Profile("test")
public DataSource dataSourceForTest() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.test.url"));
dataSource.setUsername(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
return dataSource;
}
#Bean
public PlatformTransactionManager jpaTransactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactoryBean.getObject());
return transactionManager;
}
private HibernateJpaVendorAdapter vendorAdaptor() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(true);
return vendorAdapter;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(DataSource mainDataSource) {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdaptor());
entityManagerFactoryBean.setDataSource(mainDataSource);
entityManagerFactoryBean.setPackagesToScan(ENTITY_MANAGER_PACKAGES_TO_SCAN);
entityManagerFactoryBean.setJpaProperties(jpaHibernateProperties());
return entityManagerFactoryBean;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
private Properties jpaHibernateProperties() {
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_MAX_FETCH_DEPTH, env.getProperty(PROPERTY_NAME_HIBERNATE_MAX_FETCH_DEPTH));
properties.put(PROPERTY_NAME_HIBERNATE_JDBC_FETCH_SIZE, env.getProperty(PROPERTY_NAME_HIBERNATE_JDBC_FETCH_SIZE));
properties.put(PROPERTY_NAME_HIBERNATE_JDBC_BATCH_SIZE, env.getProperty(PROPERTY_NAME_HIBERNATE_JDBC_BATCH_SIZE));
properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
properties.put("hibernate.hbm2ddl.auto", "none");
return properties;
}
}
Property file which is used for datasource and hibernate (jdbc.properties) contains following :
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testdatabase
jdbc.username=Bruce
jdbc.password=givanchy
jdbc.test.url=jdbc:mysql://localhost:3306/testdatabase1
hibernate.max_fetch_depth = 3
hibernate.jdbc.fetch_size = 50
hibernate.jdbc.batch_size = 10
hibernate.show_sql = true
hibernate.dialect = org.hibernate.dialect.MySQL8Dialect
Entry point for application :
public class EntryClass {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = applicationContext.getBean("userServiceImpl", UserServiceImpl.class);
User user =userService.getUser(1L);
System.out.println("userName is "+user.getUserName());
}
}
It works as it should.
But in test source
I have only one test for service to understand how profiles work
#SpringJUnitConfig(SpringConfig.class)
#ActiveProfiles("test")
class UserServiceImplTest {
#Autowired
private UserService userService;
#Test
void getUser() {
User user = userService.getUser(5L);
Assertions.assertEquals("Vector", user.getUserName());
}
}
And I get "No qualifying bean" exception because there are two beans of datasource type, but I set which profile it should use?Can you explain why It doesn't work?
When you launch it normally, the datasource bean with 'test' profile is not created. (becasue there is no test profile set.)
When you run it as a test, then both datasource beans are created. The default is created because there is no any condition on it, and the other is becasue its annotated with the test profile.
Simply add #Profile("!test") to the default bean. This way it will be created only if the test profile is NOT active.

Hibernate sessionFactory bean throwing java.lang.NullPointerException

I am migrating jdbc to hibernate and i have palced below hibernate configuration in my application.
public class HibernateConfiguration {
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.cm.models" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl(jdbcurl);
dataSource.setUsername(userName);
dataSource.setPassword(password);
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.put("hibernate.show_sql", true);
properties.put("hibernate.format_sql", true);
return properties;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
my application interacting fine with database at application startup creating hibernate session successfully through session factory giving output also.
**#Autowired
private SessionFactory sessionFactory;**
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
but after application startup when i hitting DAO by controller then session factory bean getting Null reference and throwing NullPointerException due to which unable to create or open hibernate session , i tried to find out solution but that's not working please let me know why above SessionFactory bean having nullPointer due to which issue created.
Just to test my DAO logic I am using this controller and This controller hitting to DAO where sessionFacory bean is null.
#RestController
#RequestMapping("/Emp")
public class myController {
#RequestMapping(value = "/findByChannelManager", method = RequestMethod.GET)
public void findemp() {
HotelDaoImpl hotelDaoImpl=new HotelDaoImpl();
List <HotelEntity> list = new ArrayList<>();
list = hotelDaoImpl.findByChannelManager (EnumCM.AR);
for (HotelEntity pro : list) {
System.out.println(pro);
}
}
}
#Repository
#Transactional
public class HotelDaoImpl extends AbstractDao implements IHotelDao {
#SuppressWarnings({ "unchecked", "unused" })
#Override
public List<HotelEntity> findByChannelManager(EnumCM cm) {
List<HotelEntity> list = null;
try {
Session s = getSession();
Criteria criteria=s.createCriteria(Hotel.class);
criteria.add(Restrictions.eq("channelManager", "cm.name()"));
list = criteria.list();
}catch(Exception e) {
LOGGER.debug("error " +e.getMessage());
e.printStackTrace();
}
return list;
}
public abstract class AbstractDao {
#Autowired
private SessionFactory sessionFactory;
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
}
You cant access dao from your controller. You can access dao from service so add service class. Try this code
#RestController
#RequestMapping("/Emp")
public class myController {
#Autowired
HotelService service;
#RequestMapping(value = "/findByChannelManager", method = RequestMethod.GET)
public void findemp() {
List <HotelEntity> list = new ArrayList<>();
list = service.findByChannelManager (EnumCM.AR);
for (HotelEntity pro : list) {
System.out.println(pro);
}
}
}
#Service
#Transactional
public class HotelService {
#Autowired
private HotelDao dao;
public List<HotelEntity> findByChannelManager(EnumCM cm) {
return dao.findByChannelManager(EnumCM cm);
}
}
#Repository
public class HotelDaoImpl extends AbstractDao implements IHotelDao {
#SuppressWarnings({ "unchecked", "unused" })
#Override
public List<HotelEntity> findByChannelManager(EnumCM cm) {
List<HotelEntity> list = null;
try {
Session s = getSession();
Criteria criteria=s.createCriteria(Hotel.class);
criteria.add(Restrictions.eq("channelManager", "cm.name()"));
list = criteria.list();
}catch(Exception e) {
LOGGER.debug("error " +e.getMessage());
e.printStackTrace();
}
return list;
}
public abstract class AbstractDao {
#Autowired
private SessionFactory sessionFactory;
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
}

HibernateException: createQuery is not valid without active transaction

The programmatic configuration seems in place but for some reason the application throws exception:
org.springframework.orm.jpa.JpaSystemException: createQuery is not valid without active transaction; nested exception is org.hibernate.HibernateException: createQuery is not valid without active transaction
Code:
#Repository
public class FilmDAOImpl implements FilmDAO {
#Autowired
private HibernateUtil hibernateUtil;
#Autowired
private SessionFactory sessionFactory;
#Override
public List<Film> findFilms(int actorId, int categoryId, int languageId, int releaseYear) {
Query searchQuery = sessionFactory.getCurrentSession().createQuery("from Film " +
"join Actor " +
"join Category " +
"where Category.categoryId=:categoryId " +
"and Film.language.id=:languageId " +
"and Film.releaseYear=:releaseYear " +
"and Actor.actorId=:actorId");
searchQuery.setParameter("categoryId", categoryId);
searchQuery.setParameter("languageId", languageId);
searchQuery.setParameter("releaseYear", releaseYear);
searchQuery.setParameter("actorId", actorId);
return (List<Film>)searchQuery.list();
}
}
Configuration:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories (basePackages = { "com.hibernate.query.performance.persistence" }, transactionManagerRef = "jpaTransactionManager")
#EnableJpaAuditing
#PropertySource({ "classpath:persistence-postgresql.properties" })
#ComponentScan(basePackages = { "com.hibernate.query.performance" })
public class ApplicationConfig {
#Autowired
private Environment env;
public ApplicationConfig() {
super();
}
#Bean
public LocalSessionFactoryBean sessionFactory() {
final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(applicationDataSource());
sessionFactory.setPackagesToScan(new String[] { "com.hibernate.query.performance.persistence.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(applicationDataSource());
emf.setPackagesToScan(new String[] { "com.hibernate.query.performance.persistence.model" });
final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
emf.setJpaVendorAdapter(vendorAdapter);
emf.setJpaProperties(hibernateProperties());
return emf;
}
#Primary
#Bean
public DriverManagerDataSource applicationDataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
return dataSource;
}
#Bean
#Primary
public PlatformTransactionManager hibernateTransactionManager() {
final HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
transactionManager.setDataSource(applicationDataSource());
return transactionManager;
}
#Bean
public PlatformTransactionManager jpaTransactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
private final Properties hibernateProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
hibernateProperties.setProperty("hibernate.format_sql", env.getProperty("hibernate.format_sql"));
hibernateProperties.setProperty("hibernate.generate_statistics", env.getProperty("hibernate.generate_statistics"));
hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("hibernate.cache.use_second_level_cache"));
hibernateProperties.setProperty("hibernate.cache.region.factory_class", env.getProperty("hibernate.cache.region.factory_class"));
hibernateProperties.setProperty("hibernate.cache.use_query_cache", env.getProperty("hibernate.cache.use_query_cache"));
hibernateProperties.setProperty("hibernate.current_session_context_class", "managed");
hibernateProperties.setProperty("hibernate.current_session_context_class", "org.hibernate.context.internal.ThreadLocalSessionContext");
return hibernateProperties;
}
}
UPDATE
#Service
#Transactional
public class FilmServiceImpl implements FilmService {
#Autowired
private FilmDAO filmDAO;
#Override
public int createFilm(Film film) {
return filmDAO.createFilm(film);
}
#Override
public Film updateFilm(Film film) {
return filmDAO.updateFilm(film);
}
#Override
public void deleteFilm(int id) {
filmDAO.deleteFilm(id);
}
#Override
public List<Film> getAllFilms() {
return filmDAO.getAllFilms();
}
#Override
public Film getFilm(int id) {
return filmDAO.getFilm(id);
}
#Override
public List<Film> findFilms(int actorId, int categoryId, int languageId, int releaseYear) {
return filmDAO.findFilms(actorId, categoryId, languageId, releaseYear);
}
}
Try using openSession() as below, Since getCurrentSession() just attaches to the current session:
Query searchQuery = sessionFactory.openSession().createQuery(...
Also, you need to surround code with proper try..catch..finally block and in finally close the session using session.close()

Categories