我正在尝试使用 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 类:
地址(@Table 注释中的 uniqueConstraints 是在 DB 上已经存在表时添加的)和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;
如您所见,在用户和地址中都没有创建索引,而它们在精确的副本中。有谁知道为什么?而且,作为一个附带问题,有谁知道为什么不考虑我们在 CopyOfAddress 中为索引提供的名称?
编辑
如果可能有帮助,我可以添加我正在使用 Hibernate 4.1.7.Final 和 Batoo 2.0.1.0-RTM。