2

I got trouble with hibernate and don't know how to fix it.

All may class files;

Bean:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@NamedQuery(name="Book.getBookList", query="from Book")
public class Book {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    private String author;

    public Book(String name, String author) {
        super();
        this.name = name;
        this.author = author;
    }
}

Controller:

@Controller
public class BookController {

    @Autowired
    private BookRepository bookRepo;
    private DAO dao = new DAO();

    @GetMapping("/")
    public String showpage(Model model, @RequestParam(defaultValue="0") int page) {
        model.addAttribute("data", bookRepo.findAll(PageRequest.of(page,4)));
        model.addAttribute("currentPage",page);
        return "index";
    }

    @PostMapping("/save")
    public String save(Book book) {
        System.out.println(book);
        bookRepo.save(book);
        dao.saveBook(book);
        return "redirect:/";
    }

    @GetMapping("/delete")
    public String delete(Long id) {
        bookRepo.deleteById(id);
        dao.deleteBook(id);
        return "redirect:/";
    }

    @GetMapping("/findOne")
    @ResponseBody
    public Optional<Book> findone(Long id) {
        return bookRepo.findById(id);
    }
}

Dao:

public class DAO {

    SessionFactory sessionFactory = new Configuration()
            .configure("ca/sheridancollege/config/hibernate.cfg.xml")
            .buildSessionFactory();

    public DAO() {
        super();
    }

    public void saveBook(Book book) {
        Session session = sessionFactory.openSession();
        session.beginTransaction();

        session.saveOrUpdate(book);

        session.getTransaction().commit();
        session.close();
    }

    public List<Book> getBookList() {
        Session session = sessionFactory.openSession();
        session.beginTransaction();

        Query query = session.createNamedQuery("Book.getBookList"); 
        List<Book> bookList = query.getResultList();

        session.getTransaction().commit();
        session.close();

        return bookList;
    }

    public void deleteBook(Long id) {
        Session session = sessionFactory.openSession();
        session.beginTransaction();

        Book toDelete = session.get(Book.class, id);
        session.delete(toDelete);

        session.getTransaction().commit();
        session.close();
    }
}

Whenever I am calling /save, getting below error.

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Tue Dec 04 16:34:24 EST 2018
There was an unexpected error (type=Internal Server Error, status=500).
Error accessing field [private java.lang.Long ca.sheridancollege.beans.Book.id] by reflection for persistent property [ca.sheridancollege.beans.Book#id] : Book(id=11, name=, author=)
org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private java.lang.Long ca.sheridancollege.beans.Book.id] by reflection for persistent property [ca.sheridancollege.beans.Book#id] : Book(id=11, name=, author=)
    at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:75)
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:224)
    at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4931)
    at org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:4631)
    at org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:226)
    at org.hibernate.event.internal.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:540)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:83)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
    at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:678)
    at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:670)
    at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:665)
    at ca.sheridancollege.dao.DAO.saveBook(DAO.java:28)
    at ca.sheridancollege.controllers.BookController.save(BookController.java:36)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:791)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.Long field ca.sheridancollege.beans.Book.id to ca.sheridancollege.beans.Book
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36)
    at java.lang.reflect.Field.get(Field.java:393)
    at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:71)
    ... 66 more

What I am doing wrong? Thanks in advance.

pleft
  • 7,567
  • 2
  • 21
  • 45
Rongfu Li
  • 45
  • 1
  • 2
  • 7
  • i see you are using lombok, did you install it on your ide? – Ryuzaki L Dec 04 '18 at 22:42
  • Already installed lombok and works well with other projects. – Rongfu Li Dec 04 '18 at 22:47
  • can you update the class where you are creating `Book` and adding values to it – Ryuzaki L Dec 04 '18 at 22:52
  • The error is caused during saving value to database. This line session.saveOrUpdate(book). I create a Book object with valid id and other fields still doesn't works. – Rongfu Li Dec 04 '18 at 22:57
  • May be try this by chainging modifer to public, i'm not sure you can try – Ryuzaki L Dec 04 '18 at 23:08
  • 2
    What version Hibernate are you using? There was a related bug in some previous versions https://stackoverflow.com/questions/37780811/hibernate-error-accessing-field-private-java-lang-integer-by-reflection-for. Also why are you using both `bookRepo` and the `DAO`? Are they saving to two different databases? – dyslexit Dec 04 '18 at 23:10
  • I'm using 5.3.7.Final. At the beginning I didn't connect with database, so I just manually created some book objets and put them in a JpaRepository. Will that conflict with hibernate saving? – Rongfu Li Dec 04 '18 at 23:20
  • It shouldn't, although the id is probably getting generated by the `bookRepo` instead of in the `DAO`'s `saveOrUpdate()`. But try removing the `bookRepo` call to see if it makes a difference. – dyslexit Dec 04 '18 at 23:30
  • Care to share also your `hibernate.cfg.xml`? It's rather strange that you use both a `BookRepository` and a 'DAO' to do the same job (save to database). It would be better if you choose one way, either the repo or the DAO. – pleft Dec 05 '18 at 07:54
  • Maybe Hibernate and Lombok are conflicting.. Which sequence of Lombok byte code manipulation in your Maven or Gradle? – Teddy Dec 05 '18 at 08:03

3 Answers3

2

This sample below code work fine! I used spring-boot version 1.5.10 for this sample.

AppConfig

@Configuration
@ComponentScan(basePackages = "com.test")
public class AppConfig {

    @Autowired
    private EntityManagerFactory entityManagerFactory;

    @Bean
    public SessionFactory getSessionFactory() {
        if (entityManagerFactory.unwrap(SessionFactory.class) == null) {
            throw new NullPointerException("factory is not a hibernate factory");
        }
        return entityManagerFactory.unwrap(SessionFactory.class);
    }

application.properties

spring.datasource.url=jdbc:mysql://test/testAPI?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=false

BookController

@RestController
@RequestMapping("/test")
public class BookController {

    @Autowired
    private DAO bookRepo;

    @PostMapping("/save")
    public String save(@RequestBody Book book) {
        System.out.println(book);
        bookRepo.saveBook(book);
        return "redirect:/";
    }
}

Book

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@NamedQuery(name="Book.getBookList", query="from Book")
public class Book {

    @Id
    @GeneratedValue
    private Long id;
    private String name;
    private String author;

    public Book(String name, String author) {
        super();
        this.name = name;
        this.author = author;
    }
}

DAO

@Repository
public class DAO {

    @Autowired
    private SessionFactory sessionFactory;


    public void saveBook(Book book) {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        session.saveOrUpdate(book);
        session.getTransaction().commit();
        session.close();
    }
}

SecurityConfig

@EnableWebSecurity
@Configuration
class SecurityConfig extends WebSecurityConfigurerAdapter {
    public SecurityConfig() {

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors().and()
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/").permitAll()
                .and()
                .exceptionHandling()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
        return source;
    }
}

then call localhost:8080/test/save body:

 {
    "name":"test",
    "author":"test1"
}

response :

redirect:/
MostafaMashayekhi
  • 27,359
  • 3
  • 21
  • 39
0

Your Book Bean has private fields, but no getters and setters.

Add:

public Long getId()
{
    return id;
}

public void setId(Long id)
{
    this.id = id;
}
brt
  • 154
  • 1
  • 2
  • 12
  • Even if it's autogenerated, Spring still needs a way to access a private field. You'll at least need the getter. – brt Dec 04 '18 at 22:17
  • I try that but doesn't help. The error is caused by session.saveOrUpdate(book). Even I create a Book object with valid id still doesn't works – Rongfu Li Dec 04 '18 at 22:22
  • The error is caused by hibernate not getting access to the `id` field. You need a getter. `right click > source > generate getters and setters` – brt Dec 04 '18 at 22:33
0

You have denoted that the ID column is auto-incremental but the auto-increment index stored at the Database side only. So you have to set ID column auto-incremental enabled in table configuration(if using workbench) from DB side.

Hibernate annotation sets the same thing at db side if you could have created table definition by API side. (you can do that by setting property value entry spring.jpa.hibernate.ddl-auto=create) The values create, create-drop, validate, and update basically influence how the schema tool management will manipulate the database schema at startup. For more info about same refer How does spring.jpa.hibernate.ddl-auto property exactly work in Spring?

Happy Coding!!

Akshay Sardhara
  • 129
  • 2
  • 7