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.