3

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}";
    }
}
Subnom
  • 57
  • 2
  • 11
  • this might help you https://stackoverflow.com/questions/1827063/mysql-error-key-specification-without-a-key-length – Mohamed Nabli Nov 27 '17 at 14:08
  • It was a good read and something to keep in mind at all times, however, I use IDs that are limited to 11 as my primary keys. I do not limit my text/blobs nor convert anything into text/blobs. – Subnom Nov 27 '17 at 14:21

1 Answers1

1

You have defined the relation to User in Comment as:

@ManyToOne()
@JoinColumn(nullable = false, name = "commenterId")
public User getCommenter()
{
    return commenter;
}

but you are referring to comments string column on the Comment side of the relationship. You should change the mappedBy to:

@OneToMany(mappedBy = "commenter")
public Set<Comment> getComments()
{
    return comments;
}
Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63
  • That would've probably fixed one problem AFTER I'm able to start my application. The problem is, it won't let me start my application as that "ERROR: creating bean with name 'entityManagerFactory' appears". I really appreciate your answer though. – Subnom Nov 27 '17 at 14:33
  • The error is regarding the comments column.. which is due to a key reference.. which is invalid.. and the above code fixed that.. i would give it a try – Maciej Kowalski Nov 27 '17 at 14:35
  • Oh, sorry, forgot to tell you that I tried it immediately and changed the 'mappedBy' variable and still got the error – Subnom Nov 27 '17 at 14:37
  • Also, when I check mySQL database, in the table 'comments' I have 2 columns: "comment" & "comments" which both are set to be a LONGBLOB EDIT: Nevermind, I dropped the old table and every other table and created a new one and now there's one column – Subnom Nov 27 '17 at 14:47