如何正确设置Spring Boot& Hibernate使用InteliJ?

时间:2015-05-09 14:13:28

标签: mysql spring hibernate intellij-idea spring-boot

正如标题所示,我正在为我的数据访问层使用Spring Boot和Hibernate构建一个Web应用程序,并且开发是在InteliJ IDEA 14.1.2上完成的。

我的知识

这是我第一次使用Spring Boot,Hibernate和InteliJ。我已经构建了一些小应用程序来测试Spring Boot和Hibernate,但是这些和我现在正在构建的应用程序之间的复杂性差异要大一些。

环境

关于我的环境,如果重要,我在运行Redis 3.0.1服务器的VirtualBox 4.3.26 VM上运行Windows 7 SP1 64位,MySQL服务器5.6.17,InteliJ 14.1.2和Ubuntu Server 14.04。 / p>

目的

此时使用上述技术的目的是将不同实体存储和检索到MySQL数据库(Redis仅用于会话外部化和应用程序实例之间的共享)。换句话说,我正在构建我的数据访问层。

数据库

我的完整数据库架构可以在这里找到:

https://dl.dropboxusercontent.com/u/49544122/so/DB.pdf

来源

My Spring Boot应用程序如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import se.domain.cvs.abstraction.dataaccess.AccountRepository;
import se.domain.cvs.domain.AccountEntity;

@SpringBootApplication
@EnableRedisHttpSession
public class Application implements CommandLineRunner {
    @Autowired
    AccountRepository repository;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... strings) throws Exception {     
        System.out.println("=======================================================");
        AccountEntity account = repository.findByEmail("r.franklin@companya.se");
        System.out.println("My name is " + account.getFirstName() + " " + account.getLastName());
        System.out.println("=======================================================");
    }
}

我正在使用CommandLineRunner接口来测试裸数据访问层而不引入REST端点。

我的配置如下YAML格式:

...
# MySQL Database Configuration
spring.datasource:
    url: jdbc:mysql://localhost:3306/cvs
    username: cvs
    password: cvs
    driverClassName: com.mysql.jdbc.Driver

spring.jpa:
    database: MYSQL
    show-sql: true
    hibernate.ddl-auto: validate
    hibernate.naming-strategy: org.hibernate.cfg.DefaultNamingStrategy
    properties.hibernate.dialect: org.hibernate.dialect.MySQL5Dialect
...

使用InteliJ自动生成JPA实体,这就是问题开始的地方。让我们以下面的OrderEntity为例(为了简洁起见,我省略了一些代码):

...
@Entity
@Table(name = "order", schema = "", catalog = "cvs")
public class OrderEntity {
    ...
    private int invoiceId;
    ...
    private InvoiceEntity invoiceByInvoiceId;
    ...

    @Basic
    @Column(name = "InvoiceID", nullable = false, insertable = false, updatable = false)
    public int getInvoiceId() {
        return invoiceId;
    }

    public void setInvoiceId(int invoiceId) {
        this.invoiceId = invoiceId;
    }

    ...

    @ManyToOne
    @JoinColumn(name = "InvoiceID", referencedColumnName = "InvoiceID", nullable = false)
    public InvoiceEntity getInvoiceByInvoiceId() {
        return invoiceByInvoiceId;
    }

    public void setInvoiceByInvoiceId(InvoiceEntity invoiceByInvoiceId) {
        this.invoiceByInvoiceId = invoiceByInvoiceId;
    }
    ...
}

尝试运行Spring Boot应用程序时,出现以下错误:

org.hibernate.MappingException: Repeated column in mapping for entity: OrderEntity column: invoiceId (should be mapped with insert="false" update="false")

在做了一些研究之后,我想问题是invoiceID现在有两种设置方式,一种是通过setInvoiceID() setter,一种是通过InvoiceEntity对象本身设置OrderEntity涉及,可能导致不一致的状态。正如另一位用户所说,

  

当创建/更新相关实体的责任不在当前实体中时,您会这样做。

请在此处查看相关信息:Please explain about: insertable=false, updatable=false

将相应字段(insertableupdateable)的建议值设置为false可修复错误。

我的问题是为什么这会产生错误的方式?我的更改修复了错误,但我想确保我的SQL中没有错误导致InteliJ以错误的方式生成错误。完整的SQL脚本可以在http://pastebin.com/aDguqR1N找到。

此外,在生成实体时,InteliJ需要一个Hibernate配置文件,我猜Spring Boot自己在其他地方生成(或使用基于Java的配置)。无论我把它留在那里还是删除它,它似乎都不会影响应用程序。我猜SB读取属性的顺序会覆盖它。我可以删除它吗?

非常感谢你的时间和提前帮助,对不起这篇长篇文章感到抱歉! :)

1 个答案:

答案 0 :(得分:0)

我的建议是让Spring / Hibernate为你生成db模式(包括外键和约束在内的所有内容都可以由Spring生成。

对我来说,下面的方法是有效的:

父实体中的

(在我的情况下是TblUser):

@OneToMany(targetEntity=TblTracks.class,fetch=FetchType.EAGER,cascade=CascadeType.ALL,mappedBy="tbluser")
    private List<TblTracks> tbltracks= new ArrayList<TblTracks>();

其中mappedBy指向子实体的Tbluser实体(私有TblUser tbluser)

并且在子实体(在我的情况下是TblTracks)中

@ManyToOne(fetch = FetchType.LAZY)
     @JoinColumn(name="idTblUser",nullable=false)
    private TblUser tbluser;