简体   繁体   中英

SpringData CrudRepository only reads (it doesn't save, update or delete)

I have following issue. I would like to use Spring Data CrudRepository with Hibernate 5 in my application. As DB I use MySQL version 5.7.21. I think I configured it wrongly, because when I run my application I am able to read from DB only. When i use any other CrudRepository method eg. save() there is no reaction. In Hibernate logs i see only read Select statement (there should be insert statement but it seems that hibernate doesn't create it).

Example log when I use save(animal) method LOG:

Hibernate: /* load com.entity.Animal */ select animal0_.animal_id as animal_i1_0_0_, animal0_.name as name2_0_0_, animal0_.type as type3_0_0_ from animal animal0_ where animal0_.animal_id=?

It is only issue with SpringData CrudRepository, because when i configure application to use only Hibernate i can read and write to DB using this method:

public void save(Animal animal) {
          sessionFactory.getCurrentSession().save(animal);
       }

My question is: What I did wrong with configuration? I would like to be able to save my Entity to DB.

I will be very thankful for any suggestion or links.

My Configuration: pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>train</groupId>
    <artifactId>train</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>train Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.4.0.Final</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>5.1.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>6.0.6</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.7</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.4.2.Final</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>train</finalName>
    </build>
</project>


AppConfig.java

package com.configuration;


import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import com.entity.Animal;

@Configuration
@EnableWebMvc
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com")
@ComponentScan("com")
public class AppConfig{

    // Configuration Beans
    @Bean
    public LocalSessionFactoryBean getSessionFactory() {
        Properties hibernateProperties = new Properties();
        hibernateProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
        hibernateProperties.put("hibernate.show_sql", "true");
        hibernateProperties.put("hibernate.generate_statistics", false);
         hibernateProperties.put("hibernate.hbm2ddl.auto", "update");
         hibernateProperties.put("hibernate.use_sql_comments", true);

        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setHibernateProperties(hibernateProperties);
        sessionFactory.setAnnotatedClasses(Animal.class);
        return sessionFactory;
    }

    @Bean(name="transactionManager")
     public PlatformTransactionManager txManager(){
     JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(
             entityManagerFactory(dataSource()).getObject());
     return jpaTransactionManager;
     }

    @Bean
    public DataSource dataSource() {

        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/projekt?useSSL=false");
        dataSource.setUsername("Programowanie@localhost");
        dataSource.setPassword("password");

        return dataSource;
    }


    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setPrepareConnection(true);
        vendorAdapter.setGenerateDdl(true);
        vendorAdapter.setDatabase(Database.MYSQL);
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter(vendorAdapter);
        factory.setPackagesToScan("com");
        factory.setDataSource(dataSource);
        Properties hibernateProperties = new Properties();
        hibernateProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
        hibernateProperties.put("hibernate.show_sql", "true");
        hibernateProperties.put("hibernate.generate_statistics", false);
         hibernateProperties.put("hibernate.hbm2ddl.auto", "update");
         hibernateProperties.put("hibernate.use_sql_comments", true);
         factory.setJpaProperties(hibernateProperties);
        return factory;
    }

}

Entity: Animal.java

package com.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="animal")
public class Animal {


    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="animal_id", insertable=true)
    private Long animalId;

    @Column(name="name", insertable=true)
    private String name;

    @Column(name="type", insertable=true)
    private String type;

    public Long getAnimalId() {
        return animalId;
    }

    public void setAnimalId(Long animalId) {
        this.animalId = animalId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

AnimalController.java

package com;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.entity.Animal;

@RestController
@RequestMapping("/test")
public class AnimalController {
    @Autowired private AnimalService animalService;
    public AnimalController() {

    }
    public AnimalController(AnimalService animalService) {
        this.animalService = animalService;
    }
    @GetMapping("/hello")
    public String sayHello() {
        return "Hello World!";
    }

    @GetMapping("/animal/{id}")
    public Animal getGreeting(@PathVariable("id") Long id) {
        return animalService.getAnimal(id);
    }


    @PostMapping("/animal")
    public void saveGreeting(@RequestBody Animal animal) {
        animalService.saveAnimal(animal);
    }

}

AnimalService.java

package com;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.entity.Animal;

@Service
public class AnimalService {

    @Autowired
    private AnimalRepository animalRepository;

    public Animal saveAnimal(Animal animal) {
        return animalRepository.save(animal);
    }

    public Animal getAnimal(Long id) {
        return animalRepository.findById(id).get();
    }
}

AnimalRepository.java

package com;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.entity.Animal;

@Repository
@Transactional
public interface AnimalRepository extends CrudRepository<Animal, Long> {

}

The @Transactional annotation on the repository interface does not help much. It needs to get somewhere where these methods are actually called, in your case that would be AnimalService . You can put them either on each method or the class itself. Annotating your controller may also work; dependening on the setup, I have seen it conflict with @Controller in the old times, but did not check your code here.

There is, however, one case where this annotation does something useful on the interfacse: With @Transactional(readOnly = true) you change the default for that option for each method in the interface, and can set it to false only the methods that really change something. This, however, is an optimization that should come later.

You also use @Repository on the repository interface. This has no additional effect. It triggers exceptions translation, but Spring Data reposiories already do that anyway.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM