私は、MySQLデータベースに格納されているユーザーを認証するためにSpringBoot Securityを使用するSpring Bootアプリケーションをセットアップしようとしています。私はこれを行う方法についていくつかのチュートリアルに従ってきましたが、mavenでアプリケーションを実行しようとすると、次のエラーが発生します:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.Java:1628) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.Java:555) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.Java:483) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.Java:306) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.Java:230) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.Java:302) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.Java:197) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.Java:1078) ~[spring-context-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.Java:857) ~[spring-context-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.Java:543) ~[spring-context-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.Java:122) ~[spring-boot-1.5.6.RELEASE.jar:1.5.6.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.Java:693) [spring-boot-1.5.6.RELEASE.jar:1.5.6.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.Java:360) [spring-boot-1.5.6.RELEASE.jar:1.5.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.Java:303) [spring-boot-1.5.6.RELEASE.jar:1.5.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.Java:1118) [spring-boot-1.5.6.RELEASE.jar:1.5.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.Java:1107) [spring-boot-1.5.6.RELEASE.jar:1.5.6.RELEASE]
at com.proba.Userboard.UserboardApplication.main(UserboardApplication.Java:11) [classes/:na]
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_121]
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:62) ~[na:1.8.0_121]
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43) ~[na:1.8.0_121]
at Java.lang.reflect.Method.invoke(Method.Java:498) ~[na:1.8.0_121]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.Java:49) [spring-boot-devtools-1.5.6.RELEASE.jar:1.5.6.RELEASE]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.Java:954) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.Java:882) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.Java:60) ~[spring-orm-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.Java:353) ~[spring-orm-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.Java:370) ~[spring-orm-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.Java:359) ~[spring-orm-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.Java:1687) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.Java:1624) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
... 21 common frames omitted
Caused by: org.hibernate.MappingException: Could not determine type for: Java.util.Set, at table: role, for columns: [org.hibernate.mapping.Column(users)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.Java:431) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.Java:398) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.mapping.Property.isValid(Property.Java:225) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.Java:595) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.mapping.RootClass.validate(RootClass.Java:265) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.Java:329) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.Java:443) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.Java:879) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
... 27 common frames omitted
私が間違っていない場合、これはデータベースに接続できないことを意味しているため、bean entityManagerFactoryの作成に問題があります。
だから、これは私のpom.xmlファイルです
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mjamsek</groupId>
<artifactId>Userboard</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Userboard</name>
<description>Userboard</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<Java.version>1.8</Java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-Java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
私application.properties:
spring.datasource.url=jdbc:mysql://localhost:3306/userboard?useSSL=false
spring.datasource.username=my_username
spring.datasource.password=my_pass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.ftl
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.session.store-type=jdbc
spring.session.jdbc.table-name=SESSIONS
spring.messages.basename=validation
次に、次の2つのエンティティを定義しました。
ser.Java
package com.proba.Userboard.entity;
import Java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
@Entity
@Table(name="user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="user_id")
private int id;
@Column(name="username")
private String username;
@Column(name="pass")
private String pass;
@Column(name="name")
private String name;
private String passConfirm;
private Set<Role> roles;
public User() {
}
public User(String usr, String pas, String nam) {
this.username = usr;
this.pass = pas;
this.name = nam;
}
@Override
public String toString() {
return String.format("{ id : %d, username : %s, pass : %s, name : %s }", this.id, this.username, this.pass, this.name);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToMany
@JoinTable(name="user_role", joinColumns = @JoinColumn(name="user_id"), inverseJoinColumns = @JoinColumn(name="role_id"))
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public String getPassConfirm() {
return passConfirm;
}
public void setPassConfirm(String passConfirm) {
this.passConfirm = passConfirm;
}
}
Role.Java
package com.proba.Userboard.entity;
import Java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
@Entity
@Table(name="role")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="role")
private int id;
@Column(name="role_name")
private String name;
private Set<User> users;
public Role() {
}
public Role(String n) {
this.name = n;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToMany(mappedBy = "roles")
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
@Override
public String toString() {
return String.format("{ id : %s, name: %s }", this.id, this.name);
}
}
次のDAOがあります。
RoleDAO.Java
package com.proba.Userboard.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.proba.Userboard.entity.Role;
@Repository
@Transactional
public interface RoleDAO extends JpaRepository<Role, Integer> {
}
serDAO.Java
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.proba.Userboard.entity.User;
@Repository
@Transactional
public interface UserDAO extends JpaRepository<User, Integer> {
public User findByUsername(String username);
}
私ユーザーサービス:
package com.proba.Userboard.service;
import Java.util.HashSet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.proba.Userboard.dao.RoleDAO;
import com.proba.Userboard.dao.UserDAO;
import com.proba.Userboard.entity.User;
public class UserServiceImpl implements UserService {
@Autowired
private UserDAO userDAO;
@Autowired
private RoleDAO roleDAO;
@Autowired
private BCryptPasswordEncoder bcrypt;
@Override
public void save(User user) {
user.setPass(bcrypt.encode(user.getPass()));
user.setRoles(new HashSet<>(roleDAO.findAll()));
userDAO.save(user);
}
@Override
public User findByUsername(String username) {
return userDAO.findByUsername(username);
}
}
私SpringBootセキュリティ構成:
package com.proba.Userboard.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConf extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bcyrpt() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resource/**", "/registration").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bcyrpt());
}
}
したがって、mvn clean spring-boot:runを実行すると、前述のエラーが発生し、何が間違っているのか理解できません。以前、私は同様のアプリを作成しましたが、うまくいきましたが、なぜこれがうまくいかないのかわかりません。
いいえ、問題はデータベースの接続ではありません。 Hibernateは、ID(属性自体またはメソッド)の注釈の場所に基づいて構成注釈をチェックするポリシーを決定します。
Userクラスでは、属性レベルの注釈を期待するようにhibernateに指示しています。
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="user_id")
private int id;
したがって、Hibernateの場合、マッピングのメソッドをチェックしないため、ロールなどの他の属性のマッピングはありません。そのため、メソッドからアノテーションを取得して属性に配置する必要があります。
@ManyToMany
@JoinTable(name="user_role", joinColumns = @JoinColumn(name="user_id"), inverseJoinColumns = @JoinColumn(name="role_id"))
private Set<Role> roles;
すべての注釈でこれを行う必要があります。
上記の例外と一緒にマッピング例外がある場合、問題はJdk 11とjavassistにある可能性があります。
これをpom.xmlに追加する必要があります
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.23.1-GA</version>
</dependency>