java - Spring JPA 与带有联结表的 OpenJPA 实体的映射(多对多)

标签 java spring spring-data openjpa spring-data-jpa

我在映射由联结表连接的 JPA 实体时遇到问题。这些实体是使用 OpenJPA 2.3.0 实现(Spring 4.0.2、Spring data jpa 1.5.0)通过 STS 3.4.0 创建的。它似乎确实执行数据库命中并返回数据,但在将数据序列化到 JPA 实体中时存在问题。使用现场访问“Eager”生成实体。

存储库:

interface MenuItemRepository extends JpaRepository<MlMenuItem, Short>

调用repository.findAll(); (实际上发生在任何添加/获取中)我收到以下错误:

org.springframework.orm.jpa.JpaSystemException: org.apache.openjpa.util.ShortId cannot be cast to com.xxxxxxxxx.jpa.model.cafe.MlMenuItem

如果我“惰性”生成 beans 并且从不访问连接到它的项目(又名 foodItems),它就可以正常工作。如果有帮助的话,我对 JPA 很陌生,所以可能是显而易见的事情,但非连接表工作正常,所以不确定这个。

以下是 JPA 实体和配置:

第一个实体:

@Entity
@Table
(name="ML_MENU_ITEM")
@NamedQuery
(name="MlMenuItem.findAll", query="SELECT m FROM MlMenuItem m")
public class MlMenuItem implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="MENU_ITEM_NBR", unique=true, nullable=false)
private short menuItemNbr;
@Column(name="COMPLETED_IND", nullable=false, length=1)
private String completedInd;
@Column(name="MARKET_PRICE_IND", nullable=false, length=1)
private String marketPriceInd;
@Column(name="MENU_ITEM_DES", nullable=false, length=100)
private String menuItemDes;
@Column(name="MENU_ITEM_NAME", nullable=false, length=40)
private String menuItemName;
@OneToMany(mappedBy="mlMenuItem", fetch=FetchType.EAGER)
private List<MlMenuFoodItem> mlMenuFoodItems;
@ManyToOne
@JoinColumn(name="MENU_TYPE_CD")
private MlMenuType mlMenuType;
@ManyToOne
@JoinColumn(name="MENU_ITEM_CLS_CD", nullable=false)
private MlMnuItmClsTyp mlMnuItmClsTyp;
@OneToMany(mappedBy="mlMenuItem", fetch=FetchType.EAGER)
private List<MlMenuItemPrice> mlMenuItemPrices;
@OneToMany(mappedBy="mlMenuItem", fetch=FetchType.EAGER)
private List<MlOrdMnuItm> mlOrdMnuItms;
public MlMenuItem() {
}
public short getMenuItemNbr() {
return this.menuItemNbr;
}
public void setMenuItemNbr(short menuItemNbr) {
this.menuItemNbr = menuItemNbr;
}
public String getCompletedInd() {
return this.completedInd;
}
public void setCompletedInd(String completedInd) {
this.completedInd = completedInd;
}
public String getMarketPriceInd() {
return this.marketPriceInd;
}
public void setMarketPriceInd(String marketPriceInd) {
this.marketPriceInd = marketPriceInd;
}
public String getMenuItemDes() {
return this.menuItemDes;
}
public void setMenuItemDes(String menuItemDes) {
this.menuItemDes = menuItemDes;
}
public String getMenuItemName() {
return this.menuItemName;
}
public void setMenuItemName(String menuItemName) {
this.menuItemName = menuItemName;
}
public List<MlMenuFoodItem> getMlMenuFoodItems() {
return this.mlMenuFoodItems;
}
public void setMlMenuFoodItems(List<MlMenuFoodItem> mlMenuFoodItems) {
this.mlMenuFoodItems = mlMenuFoodItems;
}
public MlMenuFoodItem addMlMenuFoodItem(MlMenuFoodItem mlMenuFoodItem) {
getMlMenuFoodItems().add(mlMenuFoodItem);
mlMenuFoodItem.setMlMenuItem(
this);
return mlMenuFoodItem;
}
public MlMenuFoodItem removeMlMenuFoodItem(MlMenuFoodItem mlMenuFoodItem) {
getMlMenuFoodItems().remove(mlMenuFoodItem);
mlMenuFoodItem.setMlMenuItem(
null);
return mlMenuFoodItem;
}
public MlMenuType getMlMenuType() {
return this.mlMenuType;
}
public void setMlMenuType(MlMenuType mlMenuType) {
this.mlMenuType = mlMenuType;
}
public MlMnuItmClsTyp getMlMnuItmClsTyp() {
return this.mlMnuItmClsTyp;
}
public void setMlMnuItmClsTyp(MlMnuItmClsTyp mlMnuItmClsTyp) {
this.mlMnuItmClsTyp = mlMnuItmClsTyp;
}
public List<MlMenuItemPrice> getMlMenuItemPrices() {
return this.mlMenuItemPrices;
}
public void setMlMenuItemPrices(List<MlMenuItemPrice> mlMenuItemPrices) {
this.mlMenuItemPrices = mlMenuItemPrices;
}
public MlMenuItemPrice addMlMenuItemPrice(MlMenuItemPrice mlMenuItemPrice) {
getMlMenuItemPrices().add(mlMenuItemPrice);
mlMenuItemPrice.setMlMenuItem(
this);
return mlMenuItemPrice;
}
public MlMenuItemPrice removeMlMenuItemPrice(MlMenuItemPrice mlMenuItemPrice) {
getMlMenuItemPrices().remove(mlMenuItemPrice);
mlMenuItemPrice.setMlMenuItem(
null);
return mlMenuItemPrice;
}
public List<MlOrdMnuItm> getMlOrdMnuItms() {
return this.mlOrdMnuItms;
}
public void setMlOrdMnuItms(List<MlOrdMnuItm> mlOrdMnuItms) {
this.mlOrdMnuItms = mlOrdMnuItms;
}
public MlOrdMnuItm addMlOrdMnuItm(MlOrdMnuItm mlOrdMnuItm) {
getMlOrdMnuItms().add(mlOrdMnuItm);
mlOrdMnuItm.setMlMenuItem(
this);
return mlOrdMnuItm;
}
public MlOrdMnuItm removeMlOrdMnuItm(MlOrdMnuItm mlOrdMnuItm) {
getMlOrdMnuItms().remove(mlOrdMnuItm);
mlOrdMnuItm.setMlMenuItem(
null);
return mlOrdMnuItm;
}
}

第二个实体:

@Entity
@Table
(name="ML_FOOD_ITEM")
@NamedQuery
(name="MlFoodItem.findAll", query="SELECT m FROM MlFoodItem m")
public class MlFoodItem implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="FOOD_ITEM_NBR", unique=true, nullable=false)
private short foodItemNbr;
@Column(name="COMPLETED_IND", nullable=false, length=1)
private String completedInd;
@Column(name="FOOD_ITEM_NAME", nullable=false, length=30)
private String foodItemName;
@Column(name="PURCHASED_IND", nullable=false, length=1)
private String purchasedInd;
@ManyToOne
@JoinColumn(name="UNIT_MEASURE_CD", nullable=false)
private MlUnitOfMeasure mlUnitOfMeasure;
@OneToMany(mappedBy="mlFoodItem1", fetch=FetchType.EAGER)
private List<MlFoodItemIngr> mlFoodItemIngrs1;
@OneToMany(mappedBy="mlFoodItem2", fetch=FetchType.EAGER)
private List<MlFoodItemIngr> mlFoodItemIngrs2;
@OneToMany(mappedBy="mlFoodItem", fetch=FetchType.EAGER)
private List<MlMenuFoodItem> mlMenuFoodItems;
public MlFoodItem() {
}
public short getFoodItemNbr() {
return this.foodItemNbr;
}
public void setFoodItemNbr(short foodItemNbr) {
this.foodItemNbr = foodItemNbr;
}
public String getCompletedInd() {
return this.completedInd;
}
public void setCompletedInd(String completedInd) {
this.completedInd = completedInd;
}
public String getFoodItemName() {
return this.foodItemName;
}
public void setFoodItemName(String foodItemName) {
this.foodItemName = foodItemName;
}
public String getPurchasedInd() {
return this.purchasedInd;
}
public void setPurchasedInd(String purchasedInd) {
this.purchasedInd = purchasedInd;
}
public MlUnitOfMeasure getMlUnitOfMeasure() {
return this.mlUnitOfMeasure;
}
public void setMlUnitOfMeasure(MlUnitOfMeasure mlUnitOfMeasure) {
this.mlUnitOfMeasure = mlUnitOfMeasure;
}
public List<MlFoodItemIngr> getMlFoodItemIngrs1() {
return this.mlFoodItemIngrs1;
}
public void setMlFoodItemIngrs1(List<MlFoodItemIngr> mlFoodItemIngrs1) {
this.mlFoodItemIngrs1 = mlFoodItemIngrs1;
}
public MlFoodItemIngr addMlFoodItemIngrs1(MlFoodItemIngr mlFoodItemIngrs1) {
getMlFoodItemIngrs1().add(mlFoodItemIngrs1);
mlFoodItemIngrs1.setMlFoodItem1(
this);
return mlFoodItemIngrs1;
}
public MlFoodItemIngr removeMlFoodItemIngrs1(MlFoodItemIngr mlFoodItemIngrs1) {
getMlFoodItemIngrs1().remove(mlFoodItemIngrs1);
mlFoodItemIngrs1.setMlFoodItem1(
null);
return mlFoodItemIngrs1;
}
public List<MlFoodItemIngr> getMlFoodItemIngrs2() {
return this.mlFoodItemIngrs2;
}
public void setMlFoodItemIngrs2(List<MlFoodItemIngr> mlFoodItemIngrs2) {
this.mlFoodItemIngrs2 = mlFoodItemIngrs2;
}
public MlFoodItemIngr addMlFoodItemIngrs2(MlFoodItemIngr mlFoodItemIngrs2) {
getMlFoodItemIngrs2().add(mlFoodItemIngrs2);
mlFoodItemIngrs2.setMlFoodItem2(
this);
return mlFoodItemIngrs2;
}
public MlFoodItemIngr removeMlFoodItemIngrs2(MlFoodItemIngr mlFoodItemIngrs2) {
getMlFoodItemIngrs2().remove(mlFoodItemIngrs2);
mlFoodItemIngrs2.setMlFoodItem2(
null);
return mlFoodItemIngrs2;
}
public List<MlMenuFoodItem> getMlMenuFoodItems() {
return this.mlMenuFoodItems;
}
public void setMlMenuFoodItems(List<MlMenuFoodItem> mlMenuFoodItems) {
this.mlMenuFoodItems = mlMenuFoodItems;
}
public MlMenuFoodItem addMlMenuFoodItem(MlMenuFoodItem mlMenuFoodItem) {
getMlMenuFoodItems().add(mlMenuFoodItem);
mlMenuFoodItem.setMlFoodItem(
this);
return mlMenuFoodItem;
}
public MlMenuFoodItem removeMlMenuFoodItem(MlMenuFoodItem mlMenuFoodItem) {
getMlMenuFoodItems().remove(mlMenuFoodItem);
mlMenuFoodItem.setMlFoodItem(
null);
return mlMenuFoodItem;
}
}

连接表实体:

@Entity
@Table
(name="ML_MENU_FOOD_ITEM")
@NamedQuery
(name="MlMenuFoodItem.findAll", query="SELECT m FROM MlMenuFoodItem m")
public class MlMenuFoodItem implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private MlMenuFoodItemPK id;
@Column(name="MENU_QUANTITY_NBR", nullable=false, length=4)
private String menuQuantityNbr;
@ManyToOne
@JoinColumn(name="FOOD_ITEM_NBR", nullable=false, insertable=false, updatable=false)
private MlFoodItem mlFoodItem;
@ManyToOne
@JoinColumn(name="MENU_ITEM_NBR", nullable=false, insertable=false, updatable=false)
private MlMenuItem mlMenuItem;
public MlMenuFoodItem() {
}
public MlMenuFoodItemPK getId() {
return this.id;
}
public void setId(MlMenuFoodItemPK id) {
this.id = id;
}
public String getMenuQuantityNbr() {
return this.menuQuantityNbr;
}
public void setMenuQuantityNbr(String menuQuantityNbr) {
this.menuQuantityNbr = menuQuantityNbr;
}
public MlFoodItem getMlFoodItem() {
return this.mlFoodItem;
}
public void setMlFoodItem(MlFoodItem mlFoodItem) {
this.mlFoodItem = mlFoodItem;
}
public MlMenuItem getMlMenuItem() {
return this.mlMenuItem;
}
public void setMlMenuItem(MlMenuItem mlMenuItem) {
this.mlMenuItem = mlMenuItem;
}
}

OpenJPA/Spring 数据的 Java 配置:

@Configuration
@EnableJpaRepositories
public
class JpaConfiguration {
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = 
new DriverManagerDataSource();
dataSource.setUrl(
"jdbc:db2://XXXXXXXX:99999/DATABASENAME");
dataSource.setUsername(
"XXXXXXX");
dataSource.setPassword(
"XXXXXXX");
dataSource.setDriverClassName(
"com.ibm.db2.jcc.DB2Driver");
return dataSource;
}
@Bean
public Map<String, Object> jpaProperties() {
Map<String, Object> props = 
new HashMap<String, Object>();
props.put(
"openjpa.RuntimeUnenhancedClasses", "supported");
props.put(
"openjpa.Log", "Runtime=TRACE, SQL=TRACE, MetaData=TRACE, Enhance=TRACE, DefaultLevel=TRACE");
props.put(
"openjpa.ConnectionFactoryProperties", "PrettyPrint=true, PrettyPrintLineLength=72");
props.put(
"openjpa.jdbc.Schema", "XXXXX");
props.put(
"openjpa.DynamicEnhancementAgent", "false");
props.put(
"openjpa.jdbc.DBDictionary", "db2");
return props;
}
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
OpenJpaVendorAdapter openJpaVendorAdapter = 
new OpenJpaVendorAdapter();
openJpaVendorAdapter.setShowSql(
true);
openJpaVendorAdapter.setGenerateDdl(
true);
openJpaVendorAdapter.setDatabase(Database.
DB2);
return openJpaVendorAdapter;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(
entityManagerFactory().getObject());
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lef = 
new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(
this.dataSource());
lef.setJpaPropertyMap(
this.jpaProperties());
lef.setJpaVendorAdapter(
this.jpaVendorAdapter());
lef.setPackagesToScan(
this.getClass().getPackage().getName());
return lef;
}

最佳答案

我通过转储 openJPA 并切换到 Hibernate 解决了该问题。不确定这是否是 OpenJPA 实现的问题,但 Hibernate 似乎工作得更好。

关于java - Spring JPA 与带有联结表的 OpenJPA 实体的映射(多对多),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22561468/

相关文章:

java - 两个 while 循环中的 break 语句

java - 正确使用反向引用和捕获组的 Java 正则表达式是什么

java - Spring Boot 不从属性文件读取

java - spring3.0注解

java - 使用 Spring Data JpaRepositories 按 ElementCollections 中的值查询实体

java - 如何从Android studio/java中的drawable文件夹中获取图像的内部url?

java - SWT - 获取等宽字体的操作系统无关方式

java - 在自定义注解中实现@RequestBody的功能

java - 在 Spring Data Query 中过滤子对象

java - 关于Spring JpaRepository方法线程安全