【问题标题】:MySQL index creation using JPA (Hibernate and Batoo)使用 JPA(Hibernate 和 Batoo)创建 MySQL 索引
【发布时间】:2012-12-12 17:17:02
【问题描述】:

我正在尝试使用 JPA 生成索引。我已经知道 JPA 规范本身并没有考虑生成索引的标准方法,但是(一些)提供程序支持此功能。我正在测试新出生的 Batoo (http://batoo.jp/) 和 Hibernate,我对意外的(对我的公司而言)行为感到好奇。我们有 2 个类,第一次定义时没有任何索引,第二次在其上定义了两个索引。当我们查看生成的表时,我们发现实际上没有创建索引。然后我们制作了这两个类的精确副本,索引立即到位,这些索引反映在数据库中。这里是重要的配置和类文件。
jpa-beans.xml(用于休眠)

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans profile="hibernate" xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://www.springframework.org/schema/data/jpa"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/jpa
    http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

    <beans:import resource="classpath:spring/jpa-common.xml"/>

    <beans:bean id="entityManagerFactory"
            class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <beans:property name="dataSource" ref="dataSource" />
        <beans:property name="jpaVendorAdapter">
            <beans:bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <beans:property name="database" value="MYSQL" />
                <beans:property name="showSql" value="true" />
            </beans:bean>
        </beans:property>
        <beans:property name="persistenceUnitName" value="jpa.sample" />
        <beans:property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>
        <beans:property name="jpaProperties">
            <beans:props>
                <beans:prop key="hibernate.enable_lazy_load_no_trans">true</beans:prop>
                <beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
            </beans:props>
        </beans:property>
    </beans:bean>

    <beans:bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
        <beans:property name="entityManagerFactory" ref="entityManagerFactory" />
        <beans:property name="jpaDialect">
            <beans:bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
        </beans:property>
    </beans:bean>

</beans:beans>

对于 Batoo,我们只需将 jpaVendorAdapter 更改为我们的自定义适配器和 jpaProperties 映射,以便使用 Batoo 提供的属性。

带注释的 Java 类:
Address(在 DB 上已经存在表时添加了 @Table 注释中的 uniqueConstraints)和 CopyOfAddress(@Table 注释中的 uniqueConstraints立即在那里)。省略了 setter 和 getter。

@Entity
@Table(uniqueConstraints={
    @UniqueConstraint(name="uniqueAddress", columnNames={
        "zipCode", "street", "number", "city", "country"
    })
})
public class Address extends BaseEntity
{
  private String zipCode;
  private String street;
  private String number;
  private String city;
  private String country;

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  Long id;

  @ManyToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
  private User user;
  ...
}

用户CopyOfUser

@Entity
public class User extends BaseEntity
{
  @Column(unique=true)
  private String username;

  private String fullName;

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  private Long id;
  ...
}


我们希望在 db 上创建的表是相同的,但这里使用 mysqldump 获得的转储(只是相关的 create table 语句):

CREATE TABLE `Address` (
  `zipCode` varchar(255) DEFAULT NULL,
  `street` varchar(255) DEFAULT NULL,
  `user_id` bigint(20) DEFAULT NULL,
  `number` varchar(255) DEFAULT NULL,
  `country` varchar(255) DEFAULT NULL,
  `city` varchar(255) DEFAULT NULL,
  `id` bigint(20) DEFAULT NULL,
  KEY `FK_A2CD7CE3` (`user_id`),
  CONSTRAINT `FK_A2CD7CE3` FOREIGN KEY (`user_id`) REFERENCES `User` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `CopyOfAddress` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `city` varchar(255) DEFAULT NULL,
  `country` varchar(255) DEFAULT NULL,
  `number` varchar(255) DEFAULT NULL,
  `street` varchar(255) DEFAULT NULL,
  `zipCode` varchar(255) DEFAULT NULL,
  `user_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `zipCode` (`zipCode`,`street`,`number`,`city`,`country`),
  KEY `FKA0BC6A08E9A4D67F` (`user_id`),
  CONSTRAINT `FKA0BC6A08E9A4D67F` FOREIGN KEY (`user_id`) REFERENCES `User` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `User` (
  `id` bigint(20) NOT NULL DEFAULT '0',
  `username` varchar(255) DEFAULT NULL,
  `fullName` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

DROP TABLE IF EXISTS `CopyOfUser`;

CREATE TABLE `CopyOfUser` (
  `id` bigint(20) NOT NULL DEFAULT '0',
  `username` varchar(255) DEFAULT NULL,
  `fullName` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

如您所见,在 User 和 Address 中都没有创建索引,而它们在精确的副本中。有谁知道为什么?而且,作为一个附带问题,有谁知道为什么我们在 CopyOfAddress 中为索引提供的名称不被考虑?

编辑
如果有帮助,我可以添加我正在使用 Hibernate 4.1.7.Final 和 Batoo 2.0.1.0-RTM。

【问题讨论】:

  • 我的猜测是,当表已经创建并且必须添加索引时,使用 JPA 提供程序(至少我们尝试过的两个)是不可能的,因为他们不知道如何处理使用现有数据,因此(也许)索引创建功能仅在创建时可用,而不是在更改表时可用......这可能吗?

标签: mysql hibernate jpa indexing batoo


【解决方案1】:

我使用一些日志深入研究了更多细节,我发现 Hibernate(不知道 Batoo)仅在创建表时创建索引,而仅在添加的情况下(并且唯一目的是)更改表新列(即使现有的 db 表不包含数据,它也不会删除现有的列)。这里有一些日志可以证明这一点:

从头开始创建一个具有唯一约束的新表

DEBUG [tool.hbm2ddl.SchemaUpdate] create table CopyOfCopyOfAddress (id bigint not null auto_increment, city varchar(255), country varchar(255), number varchar(255), street varchar(255), zipCode varchar(255), user_id bigint, primary key (id), unique (zipCode, street, number, city, country))
DEBUG [tool.hbm2ddl.SchemaUpdate] alter table CopyOfCopyOfAddress add index FK50EC293CE9A4D67F (user_id), add constraint FK50EC293CE9A4D67F foreign key (user_id) references User (id)


将新列添加到现有表中,其中唯一约束设置到 java 文件中而不是 db 中

DEBUG [tool.hbm2ddl.SchemaUpdate] alter table Address add column zipCode2 varchar(255)


在第二种情况下,我希望还会看到像 alter table Address add unique(zipCode, street, number, city, country); 这样的行(记住 Address.java),因此很明显 Hibernate 不会向现有表添加唯一约束(至少使用标准 JPA 注释)!
如果我没有被证明是错误的,我很快就会接受这个作为答案,因为我不知道还有什么要测试的,而且我没有找到任何文档。

【讨论】:

    猜你喜欢
    • 2013-01-26
    • 1970-01-01
    • 1970-01-01
    • 2019-10-22
    • 2014-07-17
    • 1970-01-01
    • 2018-10-30
    • 2017-08-11
    • 2013-08-11
    相关资源
    最近更新 更多