mysql - 如何使用 IntelliJ 正确设置 Spring Boot 和 Hibernate?

标签 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。

目的

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

数据库

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

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

来源

我的 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 接口(interface)只是为了测试裸数据访问层,尚未引入 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
...

JPA 实体是使用 InteliJ 自动生成的,这就是问题开始的地方。让我们以下面的 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")

经过一些研究,我猜问题是现在有两种方法可以设置发票ID,一种是通过 setInvoiceID() setter ,另一种是通过 InvoiceEntity 与 OrderEntity 相关的对象本身,这可能会导致不一致的状态。正如这里的另一位用户所说,

You would do that when the responsibility of creating/udpating the related entity in question isn't in the current entity.

请参阅此处的相关帖子:Please explain about: insertable=false, updatable=false

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

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

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

非常感谢您的宝贵时间和提前提供的帮助,对这篇长文章表示歉意! :)

最佳答案

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

对我来说,以下方法有效:

在父实体中(在我的例子中是 TblUser):

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

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

在子实体中(在我的例子中是 TblTracks),例如

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

关于mysql - 如何使用 IntelliJ 正确设置 Spring Boot 和 Hibernate?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30140922/

相关文章:

java - 是否应该在进入 Java 之前克隆 Date 对象

java - 如何在 hibernate 中映射对实体的访问?

java - 生成 Hibernate 映射文件时未创建注释

java - Hibernate 不会自己创建 Join Table

php 使用隐藏的 post 将动态数据传递到另一个 php 文件

php - 如何更正php mysql查询

java - 带有 GWT RemoteServiceServlet 的 GWTP NullPointerException

spring - Spring Data Elasticsearch存储库:查询嵌套对象

php - 如何在 CakePHP 中检索整数列的整数值?

javascript - 如何获取特定月份 SQL 查询的总和?