gpt4 book ai didi

mysql - 无法刷新 Vaadin JPAContainer 嵌套属性

转载 作者:行者123 更新时间:2023-11-29 23:22:06 25 4
gpt4 key购买 nike

于 2014 年 12 月 2 日修订 - persistence.xml 和 eclipselink/mysql 的 Wildfly 配置于 2014 年 12 月 2 日修订 - 更好的问题信息、建议的完整代码和屏幕截图。

我有两个一对多关系的 MYSQL 表。我使用绑定(bind)到关联 JPAContainer(productsContainer、pricesContainer)的两个表(tbl_products、tbl_prices)在 Vaadin 中显示它们。在 tbl_prices 中,我使用 ratesContainer.addNestedContainerProperty() 显示第一个表中的字段。

问题是,当我更改 tbl_products 中的 QTY 字段值时,更改会立即反射(reflect)到数据库中,但是 tbl_prices 中的嵌套属性永远不会知道更改,直到浏览器刷新。 (pricesContainer.getItem(itemId).getProperty("product.qty") 返回旧值)。帖子末尾的数量更新后屏幕截图清楚地显示了这一点。

tbl_prices.refreshRowCache() 和 ratesContainer.refresh() 没有帮助,尽管容器刷新应该刷新数据库中的值)

如果您能提供有关如何解决此问题的帮助,我将不胜感激。无法在 vaadin.com 论坛上获得答案。以下是实体的配置方式:

@Entity
@Table(name="products")
@NamedQuery(name="Product.findAll", query="SELECT p FROM Product p")
public class Product implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(unique=true, nullable=false)
private int id;

@Column(nullable=false, length=255)
private String name;

@Column(nullable=false)
private int qty;

//bi-directional many-to-one association to Price
@OneToMany(mappedBy="product")
private List<Price> prices;

... constructor, getters and setters
}

@Entity
@Table(name="prices")
@NamedQuery(name="Price.findAll", query="SELECT p FROM Price p")
public class Price implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(unique=true, nullable=false)
private int id;

@Column(nullable=false, length=255)
private String description;

@Column(nullable=false, precision=10, scale=2)
private BigDecimal price;

//bi-directional many-to-one association to Product
@ManyToOne
@JoinColumn(name="prodid", nullable=false)
private Product product;

@Transient
private BigDecimal value;
public BigDecimal getValue() {
return this.price.multiply(new BigDecimal(product.getQty()));
}

... constructor, getters and setters
}

public class UI_Tables_Test extends CustomComponent {
public static final String PERSISTENCE_UNIT = "vaadin_sandbox";
public JPAContainer<Product> productsContainer;
public JPAContainer<Price> pricesContainer;
private FieldGroup formFieldGroup;

public UI_Tables_Test() {
buildMainLayout();
setCompositionRoot(mainLayout);

// Containers
productsContainer = JPAContainerFactory.make(Product.class, PERSISTENCE_UNIT);
pricesContainer = JPAContainerFactory.make(Price.class, PERSISTENCE_UNIT);
pricesContainer.addNestedContainerProperty("product.*");

// Tables
tbl_products.setContainerDataSource(productsContainer);
tbl_products.setSelectable(true);
tbl_products.setImmediate(true);

tbl_prices.setContainerDataSource(pricesContainer);
tbl_prices.setSelectable(true);
tbl_prices.setImmediate(true);

// Columns
tbl_products.setVisibleColumns(new Object[] {"id","name", "qty"});
tbl_prices.setVisibleColumns(new Object[] {"id", "product.name", "product.qty", "price", "value"});

// Form
formFieldGroup = new FieldGroup(new BeanItem<Product>(new Product()));
formFieldGroup.setBuffered(false);
formFieldGroup.bind(tf_name, "name");
formFieldGroup.bind(tf_qty, "qty");

// ValueChangeListener to set form data source
tbl_products.addValueChangeListener(new Property.ValueChangeListener() {
private static final long serialVersionUID = 7133249924369468095L;

@Override
public void valueChange(ValueChangeEvent event) {
Object selectedrow = event.getProperty().getValue();
if (selectedrow != null) {
formFieldGroup.setItemDataSource(tbl_products.getItem(selectedrow));
}
}
});

// Property ValueChangeListener to refresh Prices table
productsContainer.getItem(2).getItemProperty("qty").addValueChangeListener(new Property.ValueChangeListener() {
@Override
public void valueChange(ValueChangeEvent event) {
refreshTable2();
}
});
}

public void refreshTable2() {
// trying various refresh methodologies
pricesContainer.refresh();
pricesContainer.getEntityProvider().refreshEntity(pricesContainer.getItem(3).getEntity());
tbl_prices.refreshRowCache();

// trying removing and adding nested container property again
pricesContainer.removeContainerProperty("product.*");
pricesContainer.addNestedContainerProperty("product.*");

// trying resetting table2 container data source
tbl_prices.setContainerDataSource(pricesContainer);
pricesContainer.addNestedContainerProperty("product.*");
tbl_prices.setVisibleColumns(new Object[] {"id", "product.name", "product.qty", "price", "value"});

// popup message to display the values read from the containers
String msg = "Product container Qty= " +
String.valueOf(productsContainer.getItem(2).getEntity().getQty()) + "\n" +
"Price container Qty= " +
String.valueOf(pricesContainer.getItem(3).getEntity().getProduct().getQty()) + "\n" +
pricesContainer.getContainerProperty(3, "product.qty");

Notification.show("Test", msg, Notification.Type.ERROR_MESSAGE);
}

... build layout
}

这里有两个屏幕截图(Dropbox 链接,因为信誉点不足以发布图像)

数量更新前: https://www.dropbox.com/s/ej459r0v80popsb/before_quantity_update.png?dl=0

数量更新后: https://www.dropbox.com/s/ryl358pyymguonl/after_quantity_update.png?dl=0

这是 persistence.xml 和相关的 Wildfly 配置

persistence.xml
---------------
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="vaadin_sandbox" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<non-jta-data-source>java:/jdbc/vaadin_sandbox</non-jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<shared-cache-mode>NONE</shared-cache-mode>
<properties>
<property name="eclipselink.deploy-on-startup" value="True" />
<property name="eclipselink.target-server" value="JBoss"/>
<property name="eclipselink.logging.level" value="FINE" />
</properties>
</persistence-unit>
</persistence>

wildfly config:
--------------
eclipselink.jar in /usr/local/wildfly-8.1.0.Final/modules/system/layers/base/org/eclipse/persistence/main
corresponding module.xml
<module xmlns="urn:jboss:module:1.1" name="org.eclipse.persistence">
<resources>
<resource-root path="jipijapa-eclipselink-1.0.1.Final.jar"/>
<resource-root path="eclipselink.jar"/>
</resources>
<dependencies>
...
</dependencies>
</module>

workaround for issueid=414974
$ bin/jboss-cli.sh —connect
[standalone@localhost:9990 /] /system-property=eclipselink.archive.factory:add(value=org.jipijapa.eclipselink.JBossArchiveFactoryImpl)

mysql-connector-java-5.1.30-bin.jar in /usr/local/wildfly-8.1.0.Final/modules/system/layers/base/com/mysql/main
corresponding module.xml
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="com.mysql">
<resources>
<resource-root path="mysql-connector-java-5.1.30-bin.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
<module name="javax.transaction.api"/>
</dependencies>
</module>

$ bin/jboss-cli.sh --connect
[standalone@localhost:9990 /] /subsystem=datasources/jdbc-driver=mysql:add(driver-name=mysql,driver-module-name=com.mysql,driver-class-name=com.mysql.jdbc.Driver)
[standalone@localhost:9990 /] /subsystem=datasources/data-source=vaadin_sandbox:add(driver-name=mysql, user-name=secret, password=secret, connection-url=jdbc:mysql://localhost:3306/vaadin_sandbox?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8, min-pool-size=5, max-pool-size=15, jndi-name=java:/jdbc/innodron, enabled=true, validate-on-match=true, valid-connection-checker-class-name=org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker, exception-sorter-class-name=org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter)

最佳答案

修订:在这个问题上花费几个小时后记录我的发现

常见:Wildfly 8.1.0.Final、MySQL 5.6.20、Vaadin 7.3.5、EclipseLink 2.5.2、javax.persistence 2.1.0、mysql-connector-java 5.1.34

情况1)persistence.xml transaction-type="RESOURCE_LOCAL",shared_cache_mode="NONE"

在这种情况下,清除 EntityManagerFactory 缓存似乎是解决问题的唯一方法。

public void refreshTable2() {
//Evict Entity Manager Cache for the specific item
em.getEntityManagerFactory().getCache().evict(Price.class, 3);
// if container is not refreshed, tbl_prices is not updated in the UI.
pricesContainer.refresh();

// popup message to display the values read from the containers
String msg = "Product container Qty= " +
String.valueOf(productsContainer.getItem(2).getEntity().getQty()) + "\n" +
"Price container Qty= " +
String.valueOf(pricesContainer.getItem(3).getEntity().getProduct().getQty()) + "\n" +
pricesContainer.getContainerProperty(3, "product.qty");

Notification.show("Test", msg, Notification.Type.ERROR_MESSAGE);
}

案例2)persistence.xml transaction-type="RESOURCE_LOCAL",shared_cache_mode="ALL"

在这种情况下,不需要逐出EntityManagerFactory缓存,但pricesContainer需要手动刷新嵌套属性来刷新其值。

public void refreshTable2() {
// if container is not refreshed, tbl_prices is not updated in the UI.
pricesContainer.refresh();
}

情况 3) persistence.xml transaction-type="JTA"、shared_cache_mode="ALL"或 "NONE"。(查看 this blog entry 了解如何使 Vaadin 与 JTA 事务配合使用)

对于这两种情况,都不需要逐出 EntityManagerFactory 缓存,但pricesContainer 需要手动刷新嵌套属性来刷新其值。上面的是shared_cache_mode可以设置为“NONE”,这似乎是Vaadin JPAContainer发挥良好作用所必需的(根据Vaadin论坛中的几个建议)

public void refreshTable2() {
// if container is not refreshed, tbl_prices is not updated in the UI.
pricesContainer.refresh();
}

欢迎就如何在无需手动干预的情况下刷新嵌套属性提供任何建议。在实际项目中,手动刷新将需要为源容器使用一个 Container.addItemSetChangeListener(),为容器中的每个项目使用一个 Container.getItem(i).addValueChangeListener() - 这会产生巨大的开销。

关于mysql - 无法刷新 Vaadin JPAContainer 嵌套属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27220091/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com