我正在使用Spring Security,Hibernate,JPA,mySQL的项目中工作...我正在尝试使该项目的注册,登录和注销工作正常进行,并且用户输入均未存储在数据库中,并且无法解决这个问题以挽救我的生命。我已经尝试了几乎所有我能想到的一切,并且得出的结论是,我必须丢失一些有关所有这些工作原理的基本信息。对于我来说,还不清楚我是否应该创建表,然后在运行项目之前将初始数据插入表中,或者表是否由以下代码创建和配置。我的数据库中是否需要表的初始创建?如果是这样...创建这些表以便将用户输入存储在数据库中的正确方法是什么? @JoinTable users-role让我特别困惑。
package com.stephanie.mycapec.models;
import java.util.Set;
import java.util.Date;
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 {
public User() {
}
public User(Long id, String email, String password, String fullname, boolean enabled){
this.id = id;
this.email=email;
this.password=password;
this.fullname=fullname;
this.enabled=enabled;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String email;
private String password;
private String fullname;
private boolean enabled;
@ManyToMany
@JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
private Set<Role> roles;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFullname() {
return fullname;
}
public void setFullname(String fullname) {
this.fullname = fullname;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
@Override
public String toString(){
return String.format("User[id=%d, email='%s', password='%s', name='%s'" );
}
}
我还需要为数据库中的users_roles初始化一个表吗?还是由@JoinTable创建的架构表?
这是运行程序时控制台的外观,似乎存储库存在一些问题,但是我也不知道如何解决此问题。
2020-04-22 22:30:23.260 INFO 25452 --- [ main] com.stephanie.mycapec.MyCapecApp : Starting MyCapecApp on DESKTOP-4G0GSBA with PID 25452 (C:\Users\Stephanie\My-Capec\build\classes\java\main started by Stephanie in C:\Users\Stephanie\My-Capec)
2020-04-22 22:30:23.263 INFO 25452 --- [ main] com.stephanie.mycapec.MyCapecApp : No active profile set, falling back to default profiles: default
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1 (file:/C:/Users/Stephanie/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.5.9/4222eafca660d01a44682c3fe4c629005728973/groovy-2.5.9.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.vmplugin.v7.Java7$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2020-04-22 22:30:23.887 INFO 25452 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2020-04-22 22:30:23.887 INFO 25452 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JDBC repositories in DEFAULT mode.
2020-04-22 22:30:23.919 INFO 25452 --- [ main] .RepositoryConfigurationExtensionSupport : Spring Data JDBC - Could not safely identify store assignment for repository candidate interface com.stephanie.mycapec.repositories.ApdbRepository. If you want this repository to be a JDBC repository, consider annotating your entities with one of these annotations: org.springframework.data.relational.core.mapping.Table.
2020-04-22 22:30:23.920 INFO 25452 --- [ main] .RepositoryConfigurationExtensionSupport : Spring Data JDBC - Could not safely identify store assignment for repository candidate interface com.stephanie.mycapec.repositories.RoleRepository. If you want this repository to be a JDBC repository, consider annotating your entities with one of these annotations: org.springframework.data.relational.core.mapping.Table.
2020-04-22 22:30:23.921 INFO 25452 --- [ main] .RepositoryConfigurationExtensionSupport : Spring Data JDBC - Could not safely identify store assignment for repository candidate interface com.stephanie.mycapec.repositories.UseCaseRepository. If you want this repository to be a JDBC repository, consider annotating your entities with one of these annotations: org.springframework.data.relational.core.mapping.Table.
2020-04-22 22:30:23.922 INFO 25452 --- [ main] .RepositoryConfigurationExtensionSupport : Spring Data JDBC - Could not safely identify store assignment for repository candidate interface com.stephanie.mycapec.repositories.UserRepository. If you want this repository to be a JDBC repository, consider annotating your entities with one of these annotations: org.springframework.data.relational.core.mapping.Table.
2020-04-22 22:30:23.922 INFO 25452 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 31ms. Found 0 JDBC repository interfaces.
2020-04-22 22:30:23.929 INFO 25452 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2020-04-22 22:30:23.929 INFO 25452 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2020-04-22 22:30:23.960 INFO 25452 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 28ms. Found 4 JPA repository interfaces.
2020-04-22 22:30:24.217 INFO 25452 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-04-22 22:30:24.388 INFO 25452 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2020-04-22 22:30:24.394 INFO 25452 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-04-22 22:30:24.394 INFO 25452 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.30]
2020-04-22 22:30:24.523 INFO 25452 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-04-22 22:30:24.523 INFO 25452 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1115 ms
2020-04-22 22:30:24.685 INFO 25452 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2020-04-22 22:30:24.742 INFO 25452 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.4.10.Final}
2020-04-22 22:30:24.832 INFO 25452 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2020-04-22 22:30:24.906 INFO 25452 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2020-04-22 22:30:25.208 INFO 25452 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2020-04-22 22:30:25.218 INFO 25452 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
Hibernate: alter table role_users add constraint FKipeyaf3dve9njdrl1t23ndidv foreign key (users_id) references user (id)
Hibernate: alter table role_users add constraint FKele6ufqrv6w1uoxqw6h1vkki0 foreign key (role_id) references role (id)
Hibernate: alter table users_roles add constraint FKt4v0rrweyk393bdgt107vdx0x foreign key (role_id) references role (id)
Hibernate: alter table users_roles add constraint FKgd3iendaoyh04b95ykqise6qh foreign key (user_id) references user (id)
2020-04-22 22:30:25.927 INFO 25452 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-04-22 22:30:25.933 INFO 25452 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2020-04-22 22:30:25.980 WARN 25452 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2020-04-22 22:30:26.376 INFO 25452 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/resources/**'], []
2020-04-22 22:30:26.376 INFO 25452 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/static/**'], []
2020-04-22 22:30:26.376 INFO 25452 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/css/**'], []
2020-04-22 22:30:26.376 INFO 25452 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/js/**'], []
2020-04-22 22:30:26.376 INFO 25452 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/images/**'], []
2020-04-22 22:30:26.399 INFO 25452 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@1238a074, org.springframework.security.web.context.SecurityContextPersistenceFilter@6e12f38c, org.springframework.security.web.header.HeaderWriterFilter@5a4e492c, org.springframework.security.web.authentication.logout.LogoutFilter@240291d9, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@640a6d4b, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@5a9baba8, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@1b79df53, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@35b58254, org.springframework.security.web.session.SessionManagementFilter@26a202ae, org.springframework.security.web.access.ExceptionTranslationFilter@534d0cfa, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@49c4118b]
2020-04-22 22:30:26.517 INFO 25452 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-04-22 22:30:26.887 INFO 25452 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2020-04-22 22:30:26.889 INFO 25452 --- [ main] com.stephanie.mycapec.MyCapecApp : Started MyCapecApp in 3.887 seconds (JVM running for 4.6)
Hibernate: select role0_.id as id1_1_, role0_.role as role2_1_ from role role0_ where role0_.role=?
Hibernate: select role0_.id as id1_1_, role0_.role as role2_1_ from role role0_ where role0_.role=?
2020-04-22 22:30:32.835 INFO 25452 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-04-22 22:30:32.835 INFO 25452 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-04-22 22:30:32.842 INFO 25452 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 7 ms
2020-04-22 22:30:33.050 WARN 25452 --- [nio-8080-exec-1] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [175] milliseconds.
2020-04-22 22:30:33.421 WARN 25452 --- [nio-8080-exec-2] n.n.u.t.expressions.ExpressionProcessor : Fragment expression "default" is being wrapped as a Thymeleaf 3 fragment expression (~{...}) for backwards compatibility purposes. This wrapping will be dropped in the next major version of the expression processor, so please rewrite as a Thymeleaf 3 fragment expression to future-proof your code. See https://github.com/thymeleaf/thymeleaf/issues/451 for more information.
Hibernate: select user0_.id as id1_4_, user0_.email as email2_4_, user0_.enabled as enabled3_4_, user0_.fullname as fullname4_4_, user0_.password as password5_4_ from user user0_ where user0_.email=?
这也是我的application.properties
spring.datasource.url = jdbc:mysql://localhost:3306/login?useSSL=true
spring.datasource.username = root
spring.datasource.password = uber
spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.jpa.database=H2
spring.jpa.properties.hibernate.jdbc.batch_size=5
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true
spring.jpa.properties.hibernate.jdbc.batch_versioned_data=true
如果有人可以帮助我找出如何将用户输入存储在数据库中,以使我的登录和身份验证在我的Spring项目中正常工作,我将万分感谢。
编辑根据要求,这是我的角色实体
package com.stephanie.mycapec.models;
import java.util.Set;
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)
private Long id;
private String role;
@ManyToMany(targetEntity= User.class)
//@ManyToMany(mappedBy = "role")
private Set<User> users;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}
我不确定这是否可行。让我从关于如何对程序和数据库建模的一些一般性想法开始。
首先,重要的是创建数据库并为表及其附带的所有模型建模。考虑要以哪种数据类型以及它们之间的关系存储在数据库中的内容。只有在完全建立数据库模型之后,才尝试根据数据库对Java对象建模。这也意味着您必须先创建所有表,然后再尝试存储数据。
所以您必须有两个看起来像这样的表
用户:
id bigint not null autoincrement
email varchar not null
password varchar not null
fullname varchar not null
enabled boolean not null default false
角色:
id bigint not null autoincrement
role varchar not null
这里的意思是,您不能存储用户与其所拥有角色之间的任何关系。在您的课程中,您已建模了许多关系,但是数据库无法存储这种关系。
我对这个问题的解决方案是第三个表,看起来像这样
UserRoles:
id bigint not null autonincrement
userid bigint not null
roleid bigint not null
当然,此表必须具有两个外键约束。考虑到这一点,您的课程可能看起来像这样:
用户:
@Entity
@Table(name="user")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private Long id;
@Column(name="fullname")
private String fullname;
@Column(name="password")
private String password;
@Column(name="enabled")
private Boolean enabled;
@Column(name="email")
private String email;
@JsonManagedReference
@OneToMany(mappedBy="userid", cascade=CascadeType.ALL)
@Fetch(value = FetchMode.SELECT)
private List<UserRoles> roles = null;
// Gettes & Setters etc.
}
角色:
@Entity
@Table(name="role")
public class UserRole implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private Long id;
@Column(name="name")
private String name;
@JsonBackReference
@OneToMany(mappedBy="roleid")
@Fetch(value = FetchMode.JOIN)
private List<UserRoles> users;
// Getters & Setters
}
UserRole:
@Entity
@Table(name="userrole")
public class UserRoles implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private Long id;
@JsonBackReference
@ManyToOne
@JoinColumn(name="user_id")
private User userid;
@JsonManagedReference
@ManyToOne
@JoinColumn(name="role_id")
private UserRole roleid;
// Getters & Setters
}
当然,我跳过了类中的某些部分,但是建模以这种方式工作。现在,您已经在数据库中存储了关系,并且已经在程序中对其进行了建模。根据需要检查并设置JSON设置和提取策略。
我想我现在看到了代码问题。您应该从application.properties
中删除它spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
并将@Transactional
批注添加到CustomUserDetailService:
@Override
@Transactional
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
User user = userRepository.findByEmail(email);
if(user != null) {
List<GrantedAuthority> authorities = getUserAuthority(user.getRoles());
return buildUserForAuthentication(user, authorities);
} else {
throw new UsernameNotFoundException("username not found");
}
}
如果您正在使用hsqldb或h2之类的嵌入式(内存)数据库进行测试,那么Spring将自动为您创建数据库表。对于其他数据库,例如mySql或PostgreSql,您将必须明确指示Hibernate(通过Spring)创建或更新架构对象。这是通过将该属性添加到application.properties中来完成的:spring.jpa.hibernate.ddl-auto = update
。
关于将用户与角色相关联,是的,您必须通过手动插入或在应用程序中创建用于管理用户和角色的管理仪表板来做到这一点。 (通常在企业应用程序中)
在这种情况下,Hibernate将创建三个表,分别称为user,role和users_roles。最后一个是由于ManyToMany
关联而将用户与角色关联。
您的代码在登录过程中已经在填充用户,然后您必须通过我提到的管理控制台或手动插入,以某种方式将适当的角色授予每个用户。
我希望这会有所帮助。