【发布时间】: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