Spring Boot 1.4 Hibernate 5 konfiguracja

0

Witam, mam problem z podpięciem hibernate 5 do spring boota 1.4. Wszystko robie bez pliku persistence.xml w Gradle. Próbowałem już na różne sposoby, niestety w internecie są stare rozwiązania, albo źle szukam :D W tym przypadku dostaję NullPointerException

build.gradle (tylko dependencies)

dependencies {
	compile('org.springframework.boot:spring-boot-starter-actuator')
	compile('org.springframework.boot:spring-boot-starter-aop')
	compile('org.springframework.boot:spring-boot-starter-web')
	compile('org.springframework.boot:spring-boot-starter-web-services')
	compile "org.jsoup:jsoup:1.9.2"

	compile group: 'postgresql', name: 'postgresql', version: '9.1-901-1.jdbc4'


	compile group: 'org.hsqldb', name: 'hsqldb', version: '2.3.1'
	compile group: 'org.hibernate', name: 'hibernate-core', version: '5.2.2.Final'
	
	
	
	testCompile('org.springframework.boot:spring-boot-starter-test')
}

application.properties

spring.datasource.url=jdbc:postgresql://localhost:5432/ernest
spring.datasource.username=postgres
spring.datasource.password=psql
spring.datasource.driver-class-name=org.postgresql.Driver;

spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

UserDao (tu mam NullPointerException w entityManager.persist(user);

import javax.persistence.EntityManager;
import javax.persistence.PersistenceUnit;

import org.springframework.stereotype.Repository;

@Repository
public class UserDao {

	@PersistenceUnit
	private EntityManager entityManager;
	
	public void saveUser(){
		User user = new User();
		user.setLogin("ernest");
		user.setPassword("pass");
		
		entityManager.persist(user);
	}
}

w klasie mainowej mam tylko adnotacje @SpringBootApplication

0

A klasa ze springowym kontekstem tzn klasa z @Configuration gdzie miałbyś zdefiniowaną konfiguracje dla jakiegoś beana, pewnie org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean i dla transaction managera i jeszcze ustawić annotation driven transaction?
Ja mam wrażenie że ludzie nie powinni zaczynać od Spring Boota bo potem niektórym się wydaje że to wszystko jakoś samo z siebie działa :D (co zresztą pewnie by się stało jakby napchać jeszcze jakis spring boot starter jpa znając życie...)

0
Shalom napisał(a):

to wszystko jakoś samo z siebie działa

no to chyba jest głównym celem Spring Boota, jak nie całego frameworka

i w Spring MVC właśnie nie ma takiego problemu z konfiguracją bo są tysiące gotowych rozwiązań jak to zrobić. Jeśli ktoś znałby rozwiązanie to proszę o odpowiedź, chociaż zabieram się do jej znalezienia :)

0

Wydaje mi się że musisz to zrobić tak jak napisałem, tzn konfiguracje przeprowadzić ręcznie. Tutaj nie ma nic do "znajdowania", musisz po prostu zdefiniować sobie 2 beany w konfiguracji. Mam tylko nadzieje że w CV nie wpisujesz sobie znajomości Springa, bo zabijesz kogoś ze śmiechu na interview ;)
Jest gotowa konfiguracja boota dla jpa ale tylko dla Spring Data a nie dla ręcznie pisanego DAO.

0
@Configuration
@EnableTransactionManagement
public class Konf {

	@Bean
	public JpaTransactionManager jpaTransMan(){
		JpaTransactionManager jtManager = new JpaTransactionManager(getEntityManagerFactoryBean().getObject());
		return jtManager;
	}
	@Bean
	public LocalEntityManagerFactoryBean getEntityManagerFactoryBean() {
		LocalEntityManagerFactoryBean lemfb = new LocalEntityManagerFactoryBean();
		lemfb.setPersistenceUnitName("localEntity");
		return lemfb;
	}
}
@Repository
@Transactional(readOnly = false)
public class UserDao {

	@PersistenceUnit
	private EntityManager entityManager;
	
	public void saveUser(){
		User user = new User();
		user.setLogin("ernest");
		user.setPassword("pass");
				
		entityManager.persist(user);
	}
}

dla takiej konfiguracji i przy próbowaniu @Autowired UserDao dostaję taki Exception i w sumie to cały czas miałem chyba taki Exception, ale do tematu wolałem wrzucić mniej skomplikowany kod. Czasami serio uważam, że niektóre konfiguracje były łatwiejsze w MVC niż Boocie

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'loggingController': Unsatisfied dependency expressed through field 'userDao': Error creating bean with name 'userDao' defined in file [/home/user/bin/pl/pvkk/profit/user/UserDao.class]: Post-processing failed of bean type [class pl.profit.user.UserDao] failed; nested exception is java.lang.IllegalStateException: Specified field type [interface javax.persistence.EntityManager] is incompatible with resource type [javax.persistence.EntityManagerFactory]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDao' defined in file [/home/user/bin/pl/profit/user/UserDao.class]: Post-processing failed of bean type [class pl.profit.user.UserDao] failed; nested exception is java.lang.IllegalStateException: Specified field type [interface javax.persistence.EntityManager] is incompatible with resource type [javax.persistence.EntityManagerFactory]
0

A widzisz teraz to zupełnie co innego. Pomyliłeś adnotacje. Chciałeś użyć @PersistenceContext a nie @PersistenceUnit

0

Proszę o przywrócenie do porządku Pana Moderatora i nie spamowaniu tematu głupimi i bezwartościowymi postami. Pozdrawiam.

0

Dochodzi 2 w nocy, a ja właśnie poradziłem sobie z problemem :D Wbrew "poradom" moderatora nie dodawałem żadnych beanów z konfiguracją, dodałem tylko plik hibernate.cfg.xml, gdzie umieściłem jedynie to samo co w application.properties.

A co do moderatora w tym temacie nie potrafił napisać nic mądrego, dawał rady bez większego wytłumaczenia : D : D : D : D postował swoje głupie emotki : D : D I

mam tylko nadzieje że w CV nie wpisujesz sobie znajomości Springa, bo zabijesz kogoś ze śmiechu na interview ;)

0

urągające...
przy takiej przykrej okazji, mam propozycję do moderatorów/adminów, żeby zrobić "poddział" Spring, ale zasadą (warunkiem koniecznym), żeby wklejać strukturę Springowego projektu...

@ernest1: jak można besztać faceta, który chciał Ci pomóc? Oczywiście nie wiedział dokładnie jak, bo poruszał się po omacku.
Naprawdę, wystarczyło napisać: "Dziękuję, jednak mój problem był w innym miejscu".

0

Dochodzi 2 w nocy, a ja właśnie poradziłem sobie z problemem Wbrew "poradom" moderatora nie dodawałem żadnych beanów z konfiguracją, dodałem tylko plik hibernate.cfg.xml, gdzie umieściłem jedynie to samo co w application.properties.

@ernest1 no i widać znów że nie rozumiesz co się dzieje w twoim projekcie. Nowe beany można definiować na wiele sposobów, założyłem że skoro juz uzywasz Spring Boot to chcesz mieć Java Configuration, ale to nie jest jedyna metoda. Równie dobrze można definiować beany w xmlowym springowym kontekście, a także na kilka innych sposobów, w tym ten którego użyłeś. Gdybyś poprawnie zastosował się do mojej rady to także by zadziałało, tak samo gdybyś zdefiniował te beany w xmlowym kontekście, bo wszystkie te metody są równoważne. Wiedziałbyś o tym gdybyś postanowił kiedyś naczyć się programować inaczej niż metodą kopiuj-wklej ze stackoverflow :) Więc zaręczam ci że dodałeś właśnie bean z konfiguracją - dodałeś go za pomocą xmla, tylko że nawet o tym nie wiesz, bo programujesz metodą kopiego pejsta...

To jak podpiąłeś hibernate jest metodą najgorszą z możliwych i działa tylko dlatego że twórcy springa przewidzieli, że ktoś bez cienia zrozumienia będzie chciał coś takiego wykonać. Wrzuciłeś plik konfiguracji gołego hibernate a używasz go jako dostawce JPA. Jeszcze nie tak dawno po prostu by to nie zadziałało, ale widać twórcy springa zlitowali się nad sierotkami kopiującymi niezrozumiałe kawałki kodu z tutoriali sprzed kilku lat i zwyczajnie naprawiają twój błąd automatycznie. Jeśli już chciałeś dodawać plik xml to należało dostać persistence.xml skoro używasz JPA. Niemniej jest to raczej niezbyt eleganckie rozwiązanie skoro juz i tak korzystasz z Boota. Chciałbym zobaczyć jak teraz wymieniasz dostawcę JPA z Hibernate na jakiegoś innego. W normalnym projekcie to jedna linijka do zmiany.

0

Tu masz przykład projektu na GitHub z wykorzystaniem Spring Boot i Hibernate: https://github.com/netgloo/spring-boot-samples/tree/master/spring-boot-mysql-hibernate

Zwróć uwagę na plik DatabaseConfig.java i bedziesz wszystko wiedział.

0

to mój plik hibernate.cfg.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>

        <!-- Connection settings -->
		<property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
		<property name="hibernate.connection.url">jdbc:hsqldb:data/tutorial</property>
        
        
        <property name="hibernate.connection.username">postgres</property>
        <property name="hibernate.connection.password">pass</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.HSQLDialect</property>

        <!-- Print executed SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Drop and re-create all database on startup -->
        <property name="hibernate.hbm2ddl.auto">create-drop</property>

        <!-- Annotated entity classes -->
        <mapping class="pl.profit.user.User"/>
        
    </session-factory>
</hibernate-configuration>
0

aaaaa w końcu to działa, a najlepsze były niedziałające tutoriale z internetu robione metodą ctrl+c, ctrl+v. sorry panie moderatorze ale byłem zdenerwowany

Plik konfiguracyjny

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

@Configuration
public class HibernateConfig {

	@Bean
	public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
	    LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
	    em.setDataSource(dataSource());
	    em.setPackagesToScan(new String[] { "pl.pvkk.profit" });
	    JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
	    em.setJpaVendorAdapter(vendorAdapter);
	    em.setJpaProperties(additionalProperties());
	    return em;
	}

	Properties additionalProperties() {
	    Properties properties = new Properties();
	    properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
	    properties.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
	    properties.setProperty("hibernate.show_sql", "true");
	    return properties;
	}
	
	@Bean
	public DataSource dataSource() {
	    DriverManagerDataSource dataSource = new DriverManagerDataSource();
	    dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
	    dataSource.setUrl("jdbc:hsqldb:data/tutorial");
	    dataSource.setUsername("postgres");
	    dataSource.setPassword("pass");
	    return dataSource;
	}
	
	@Bean
	public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
	    JpaTransactionManager transactionManager = new JpaTransactionManager();
	    transactionManager.setEntityManagerFactory(emf);
	    return transactionManager;
	}
}

gradle dependencies

 compile group: 'org.hsqldb', name: 'hsqldb', version: '2.3.2'
	
	compile group: 'org.hibernate', name: 'hibernate-core', version: '5.2.2.Final'
	compile group: 'org.hibernate', name: 'hibernate-entitymanager', version: '5.2.2.Final'
	compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '1.4.0.RELEASE'

a w naszy repozytorium tworzymy entity managera jak poniżej

	@Autowired
	private EntityManagerFactory emf;
	
	public String getUser(){
		EntityManager em = emf.createEntityManager();
		
		em.getTransaction().begin();
		User user = em.find(User.class, 1);
		em.getTransaction().commit();		
		return user.toString();
	}
0

Zalecałbym jednak wstrzykiwać @PersistenceContext i EntityManager a także używać @Transactional zamiast ręcznego otwierania i zamykania transakcji. To drugie będzie wymagać dodania @EnableTransactionManagement. Będzie wygodniej i ładniej.
No i lepiej użyć @Inject zamiast @Autowired żeby niepotrzebnie nie wiązać sie tak mocno z frameworkiem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1