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

时间:2014-03-21 14:23:54

标签: 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无法强制转换为com.xxxxxxxxx.jpa.model.cafe.MlMenuItem

如果我生成豆“懒惰”并且从不访问加入它的项目(aka.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;
}

1 个答案:

答案 0 :(得分:2)

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