My web application was working until I decided to put in comments. I messed it up a lot so I changed spring.jpa.hibernate.ddl-auto
from upate
to create-drop
But now, when I spring.jpa.hibernate.ddl-auto = create-drop
the application starts and when I change it to spring.jpa.hibernate.ddl-auto = update
I get this error:
2017-11-27 15:27:02.481 ERROR 3552 --- [ restartedMain] o.s.boot.SpringApplication : Application startup failed
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.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1078) ~[spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) ~[spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) ~[spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at blog.BlogApplication.main(BlogApplication.java:14) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_111]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_111]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_111]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_111]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-1.5.8.RELEASE.jar:1.5.8.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.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353) ~[spring-orm-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:370) ~[spring-orm-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:359) ~[spring-orm-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
... 21 common frames omitted
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Unable to execute schema management to JDBC target [alter table comments add constraint FK99rehd3fcds7jsy5dpa39fitm foreign key (comments) references users (id)]
at org.hibernate.tool.schema.internal.TargetDatabaseImpl.accept(TargetDatabaseImpl.java:59) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applySqlString(SchemaMigratorImpl.java:431) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applySqlStrings(SchemaMigratorImpl.java:420) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applyForeignKeys(SchemaMigratorImpl.java:386) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigrationToTargets(SchemaMigratorImpl.java:214) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigration(SchemaMigratorImpl.java:60) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:134) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:101) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:472) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) ~[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
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: BLOB/TEXT column 'comments' used in key specification without a key length
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_111]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_111]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_111]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_111]
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) ~[mysql-connector-java-5.1.44.jar:5.1.44]
at com.mysql.jdbc.Util.getInstance(Util.java:408) ~[mysql-connector-java-5.1.44.jar:5.1.44]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:943) ~[mysql-connector-java-5.1.44.jar:5.1.44]
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973) ~[mysql-connector-java-5.1.44.jar:5.1.44]
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909) ~[mysql-connector-java-5.1.44.jar:5.1.44]
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527) ~[mysql-connector-java-5.1.44.jar:5.1.44]
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680) ~[mysql-connector-java-5.1.44.jar:5.1.44]
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2483) ~[mysql-connector-java-5.1.44.jar:5.1.44]
at com.mysql.jdbc.StatementImpl.executeUpdateInternal(StatementImpl.java:1552) ~[mysql-connector-java-5.1.44.jar:5.1.44]
at com.mysql.jdbc.StatementImpl.executeLargeUpdate(StatementImpl.java:2607) ~[mysql-connector-java-5.1.44.jar:5.1.44]
at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1480) ~[mysql-connector-java-5.1.44.jar:5.1.44]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_111]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_111]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_111]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_111]
at org.apache.tomcat.jdbc.pool.StatementFacade$StatementProxy.invoke(StatementFacade.java:114) ~[tomcat-jdbc-8.5.23.jar:na]
at com.sun.proxy.$Proxy88.executeUpdate(Unknown Source) ~[na:na]
at org.hibernate.tool.schema.internal.TargetDatabaseImpl.accept(TargetDatabaseImpl.java:56) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
... 37 common frames omitted
Probably some of my relations are messed up, but I have an ArticleBindingModel
public class ArticleBindingModel
{
private String comments;
@NotNull
private String title;
@NotNull
private String content;
//--------------------------GETTERS/SETTERS---------------------------
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getContent()
{
return content;
}
public void setContent(String content)
{
this.content = content;
}
public String getComments()
{
return comments;
}
public void setComments(String comments)
{
this.comments = comments;
}
}
Article Entity
@Entity
@Table(name = "articles")
public class Article
{
private Integer id;
private String title;
private String content;
private User author;
private User commenter;
private Set<Comment> comments;
//-----------------------------CONSTRUCTORS--------------------------
public Article(String title, String content, User author)
{
this.title = title;
this.content = content;
this.author = author;
this.comments = new HashSet<>();
}
public Article(){}
//-------------------------GETTERS/SETTERS----------------------------
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
@Column(nullable = false)
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
@Column(columnDefinition = "text", nullable = false)
public String getContent()
{
return content;
}
public void setContent(String content)
{
this.content = content;
}
@ManyToOne()
@JoinColumn(nullable = false, name = "authorId")
public User getAuthor()
{
return author;
}
public void setAuthor(User author)
{
this.author = author;
}
@OneToMany(mappedBy = "article")
public Set<Comment> getComments()
{
return comments;
}
public void setComments(Set<Comment> comments)
{
this.comments = comments;
}
}
Comment Entity
@Entity
@Table(name = "comments")
public class Comment
{
private Integer id;
private User commenter;
private String comments;
private Article article;
//-----------------------------CONSTRUCTORS----------------------
public Comment(User commenter, String comments, Article article)
{
this.commenter = commenter;
this.comments = comments;
this.article = article;
}
public Comment(){}
//----------------------METHODS-----------------------------------
//--------------------GETTERS/SETTERS-----------------------------
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
@Column(nullable = false, columnDefinition = "LONGBLOB")
public String getComments()
{
return comments;
}
public void setComments(String comments)
{
this.comments = comments;
}
@ManyToOne()
@JoinColumn(nullable = false, name = "commenterId")
public User getCommenter()
{
return commenter;
}
public void setCommenter(User commenter)
{
this.commenter = commenter;
}
@ManyToOne()
@JoinColumn(nullable = false, name = "articleId")
public Article getArticle()
{
return article;
}
public void setArticle(Article article)
{
this.article = article;
}
}
User Entity
@Entity
@Table(name = "users")
public class User
{
private Integer id;
private String username;
private Set<Article> articles;
private Set<Comment> comments;
//-----------------------------------CONSTRUCTORS-----------------------------------
public User (String username)
{
this.username = username;
this.articles = new HashSet<>();
this.comments = new HashSet<>();
}
public User() {
}
//------------------------------------METHODS------------------------------------------
//----------------------------------GETTERS/SETTERS--------------------------------------
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
@Column(name = "username", length = 80, nullable = false, unique = true)
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
@OneToMany(mappedBy = "author")
public Set<Article> getArticles()
{
return articles;
}
public void setArticles(Set<Article> articles)
{
this.articles = articles;
}
@OneToMany(mappedBy = "comments")
public Set<Comment> getComments()
{
return comments;
}
public void setComments(Set<Comment> comments)
{
this.comments = comments;
}
}
And then I have a repository for the appropriate Entities. I have heavily edited the code so I won't be a "heresallmycode" guy. But, I'm pretty sure that my annotation relations are the problem. I wanted there to be comments that have a MANY TO ONE relationship with an article, a user that would appear above the comments when they are posted and a reverse ONE TO MANY relationship of the article with the comments. When the tables are created using the create
paramater, my articles table was not emptied(I had it on update
before), I had to manually drop it. Now, when the table is created it's empty. I thought that was worth mentioning. I can post the create
logs If that would be neccessary.
EDIT
I forgot my ArticleController
@Controller
public class ArticleController
{
@Autowired
private ArticleRepository articleRepository;
@Autowired
private UserRepository userRepository;
@Autowired
private CommentRepository commentRepository;
//---------------------------------METHODS-----------------------
//ARTICLE DETAILS--------------------------------------------------
@GetMapping("/article/{id}")
public String details(Model model, @PathVariable Integer id)
{
if (!this.articleRepository.exists(id))
{
return "redirect:/";
}
UserDetails principal = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();//This was inside the IF
if (!(SecurityContextHolder.getContext().getAuthentication() instanceof AnonymousAuthenticationToken))
{
User entityUser = this.userRepository.findByEmail(principal.getUsername());
model.addAttribute("user", entityUser);
}
//Getting the article
Article article = this.articleRepository.findOne(id);
//Comments
Set<Comment> comments = this.commentRepository.findCommentsByArticleId(id);//findAllByArticlesId
//Set<User> commenters = this.userRepository.findAllByComments(comments);
//Models
model.addAttribute("article", article);
//model.addAttribute("commenters", commenters);
model.addAttribute("comments", comments);
model.addAttribute("view", "article/details");
return "base-layout";
}
@PostMapping("/article/{id}")
@PreAuthorize("isAuthenticated()")
public String detailsProcess(@PathVariable Integer id, ArticleBindingModel articleBindingModel)
{
if (!this.articleRepository.exists(id))
{
return "redirect:/";
}
//Getting the article
Article article = this.articleRepository.findOne(id);
//Getting the commenter
UserDetails principal = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
User commenter = this.userRepository.findByEmail(principal.getUsername());
//Setting the values for the comment section
return "redirect:/article/{id}";
}
}