I'm having issues mapping JPA entities that are joined by a junction table. The entities were created through STS 3.4.0 using an OpenJPA 2.3.0 implementation (Spring 4.0.2, Spring data jpa 1.5.0). It does appear to be doing the database hits and returning the data, but has an issue serializing the data into the JPA entities. Entities are generated "Eager" using field access.

Repository:

interface MenuItemRepository extends JpaRepository<MlMenuItem, Short>

Calling repository.findAll(); (actually happens with any add/get) I get the following error:

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

It works fine if I generate the beans "lazy" and never access the items joined to it (aka. foodItems). If it helps, I'm very new to JPA, so may be something obvious, but non-joined tables work fine, so not sure on this one.

The following are the JPA entities and configuration:

First Entity:

@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;
}
}

Second Entity:

@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;
}
}

Junction table entity:

@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;
}
}

Java Config for OpenJPA/Spring Data:

@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;
}
有帮助吗?

解决方案

I fixed the issue by dumping openJPA and switching to Hibernate. Not sure if it was an issue with the implementation of OpenJPA, but Hibernate seems to work much better.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top