Java 在EJB3中使用StringBuffer或StringBuilder
在EJB3应用程序(在WebSphereApplicationServerV7.0.0.21上)中,我有一个返回字符串的方法。在方法中,我使用StringBuffer生成动态字符串(也使用StringBuilder进行了尝试,结果相同)。偶尔出现的问题是字符串的内容都被打乱了。我为这个问题挣扎了很长一段时间 编辑:Java 在EJB3中使用StringBuffer或StringBuilder,java,ejb,stringbuilder,stringbuffer,Java,Ejb,Stringbuilder,Stringbuffer,在EJB3应用程序(在WebSphereApplicationServerV7.0.0.21上)中,我有一个返回字符串的方法。在方法中,我使用StringBuffer生成动态字符串(也使用StringBuilder进行了尝试,结果相同)。偶尔出现的问题是字符串的内容都被打乱了。我为这个问题挣扎了很长一段时间 编辑: 添加了dao.properties、spring.xml、dao.java、DaoBeanLocal.java、DaoBean.java和DaoSpringJdbc.java的代码
- 添加了dao.properties、spring.xml、dao.java、DaoBeanLocal.java、DaoBean.java和DaoSpringJdbc.java的代码
- 我正在使用JavaEE5、JRE1.6和SpringJDBC3.0.6
# jndi lookup string
jndi.datasource = jdbc/DS
# integers
select.integers = \
SELECT \
num1 \
FROM \
DBINTEGERS \
WHERE \
param1 = :param1 \
AND param2 = :param2 \
ORDER BY num1 \
WITH UR
# custom object
select.custom.object = \
SELECT \
number1, number2, number3, number4 \
FROM \
DB_OBJECTS \
WHERE \
param1 = :param1 \
ORDER BY number1 \
WITH UR
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:dao.properties</value>
</list>
</property>
<property name="order" value="1" />
<property name="ignoreUnresolvablePlaceholders" value="false" />
<property name="localOverride" value="true" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.WebSphereDataSourceAdapter">
<property name="targetDataSource">
<bean class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${jndi.datasource}" />
<property name="resourceRef" value="true" />
</bean>
</property>
</bean>
<bean id="abstractDao" abstract="true">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dao" class="org.example.beans.dao.DaoSpringJdbc" parent="abstractDao">
<property name="selectIntegers" value="${select.integers}" />
<property name="selectCustomObject" value="${select.custom.object}" />
</bean>
</beans>
DaoBean.java
package org.example.beans.dao;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJBException;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
@Stateless
public class DaoBean implements DaoBeanLocal {
private Dao dao;
@PostConstruct
protected void init() {
try {
this.dao = (Dao) getBeanFactory().getBean("dao", Dao.class);
} catch (Exception e) {
// log.error(e.getMessage(), e);
throw new EJBException(e.getMessage(), e);
}
}
@PreDestroy
protected void destroy() {
if (this.dao != null) {
this.dao = null;
}
}
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public List<Integer> selectINTEGERS(String param1, String param2) throws SQLException {
return dao.selectINTEGERS(param1, param2);
}
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public List<CustomObject> selectCustomObject(Integer param1) throws SQLException {
return dao.selectCustomObject(param1);
}
}
CustomException.java
package org.example.beans.exceptions;
import javax.ejb.ApplicationException;
@ApplicationException(rollback = true)
public class CustomException extends Exception {
private static final long serialVersionUID = 1L;
public CustomException() {
super();
}
public CustomException(Throwable t) {
super(t);
}
public CustomException(String detailMessage) {
super(detailMessage);
}
public CustomException(String detailMessage, Throwable t) {
super(detailMessage, t);
}
}
Data.java
package org.example.beans.data;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.example.beans.models.CustomObject;
import org.example.beans.dao.DaoBeanLocal;
import org.example.beans.exceptions.CustomException;
public class Data {
public void getContent(StringBuffer doc, DaoBeanLocal dao, Integer param1) throws CustomException {
List<CustomObject> list = dao.selectCustomObject(param1);
for (CustomObject obj : list) {
doc.append("------------------");
doc.append("String1: ").append(obj.getNumber1()).append("\n");
doc.append("String2: ").append(obj.getNumber2()).append("\n");
doc.append("String3: ").append(obj.getNumber3()).append("\n");
doc.append("String4: ").append(obj.getNumber4()).append("\n");
}
}
}
package org.example.beans.data;
导入java.util.array;
导入java.util.HashMap;
导入java.util.List;
导入java.util.Map;
导入org.example.beans.models.CustomObject;
导入org.example.beans.dao.DaoBeanLocal;
导入org.example.beans.exceptions.CustomException;
公共类数据{
public void getContent(StringBuffer doc、daobeannlocal dao、Integer param1)引发CustomException{
List List=dao,选择CustomObject(参数1);
用于(CustomObject对象:列表){
追加文件(“--------------------------”;
doc.append(“String1:”).append(obj.getNumber1()).append(“\n”);
doc.append(“String2:”).append(obj.getNumber2()).append(“\n”);
doc.append(“String3:”).append(obj.getNumber3()).append(“\n”);
doc.append(“String4:”).append(obj.getNumber4()).append(“\n”);
}
}
}
DocumentBean.java
package org.example.beans;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import org.example.beans.exceptions.CustomException;
import org.example.beans.data.Data;
import org.example.beans.dao.DaoBeanLocal;
@Stateless
public class DocumentBean implements DocumentRemote {
@PostConstruct
protected void init() {
}
@PreDestroy
protected void destroy() {
}
// DAO local ejb
@EJB
private DaoBeanLocal dao;
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public String generateDocument(String param1, String param2) throws CustomException {
StringBuffer doc = new StringBuffer(10000);
try {
// some utility class
Data data1 = new Data();
Data data2 = new Data();
Data data3 = new Data();
Data data4 = new Data();
// some data from database
List<Integer> list = dao.selectIntegers(param1, param2);
for (Integer param1 : list) {
// a lot of usage of StringBuffer inside methods
data1.getContent(doc, dao, param1);
data2.getContent(doc, dao, param1);
data3.getContent(doc, dao, param1);
data4.getContent(doc, dao, param1);
}
} catch (CustomException e) {
log.error(e.getMessage(), e);
throw e;
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new CustomException(e.getMessage(), e);
}
String result = doc.toString();
return result;
}
}
package org.example.beans;
导入java.util.List;
导入javax.annotation.PostConstruct;
导入javax.annotation.PreDestroy;
导入javax.ejb.ejb;
导入javax.ejb.EJBException;
导入javax.ejb.Stateless;
导入javax.ejb.TransactionAttribute;
导入javax.ejb.TransactionAttributeType;
导入org.example.beans.exceptions.CustomException;
导入org.example.beans.data.data;
导入org.example.beans.dao.DaoBeanLocal;
@无国籍
公共类DocumentBean实现DocumentRemote{
@施工后
受保护的void init(){
}
@发情前期
受保护的无效销毁(){
}
//DAO本地ejb
@EJB
私人道具本地道具;
@凌驾
@TransactionAttribute(TransactionAttributeType.REQUIRES\u NEW)
公共字符串generateDocument(字符串参数1,字符串参数2)引发CustomException{
StringBuffer文档=新StringBuffer(10000);
试一试{
//一些实用程序类
Data data1=新数据();
Data data2=新数据();
Data data3=新数据();
Data data4=新数据();
//数据库中的一些数据
List List=dao.selectIntegers(参数1,参数2);
for(整数参数1:列表){
//StringBuffer在方法内部的大量使用
data1.getContent(doc、dao、param1);
data2.getContent(doc、dao、param1);
data3.getContent(doc、dao、param1);
data4.getContent(doc、dao、param1);
}
}捕获(自定义异常){
log.error(e.getMessage(),e);
投掷e;
}捕获(例外e){
log.error(e.getMessage(),e);
抛出新的CustomException(e.getMessage(),e);
}
字符串结果=doc.toString();
返回结果;
}
}
我想这就是同步线程的问题所在。我认为EJB上下文处理同步,每个远程调用在单独的线程中进行
有人知道如何解决这个问题吗?正如您所说,每个EJB都是独立的线程,因此StringBuffer不会以任何方式共享。将dao添加到列表中,可能存在问题。@谢谢您的输入。没想到dao可能是问题的根源。我已经更新了我的问题…您确定输出不是这样的吗:例如:String1:5 String2:6 String1:1 String2:2 String3:7 String4:8 String3:3 String4:4?这是完全合法的,因为写入日志是不同步的。@Gas GUI应用程序(Java AWT)使用EJB客户端,返回的字符串显示在文本区域中。写入日志不是问题,也没有使用。你觉得DAO代码怎么样?为什么您认为DAO可能会导致问题?@Gas输出看起来有一点来自用户a响应,而有一点来自用户B响应-似乎有两个不同的线程混合在一起。我不能重复这个错误。
package org.example.beans.models;
public class CustomObject {
private int number1;
private int number2;
private int number3;
private int number4;
public int getNumber1() {
return this.number1;
}
public void setNumber1(int number1) {
this.number1 = number1;
}
public int getNumber1() {
return this.number1;
}
public void setNumber2(int number2) {
this.number2 = number2;
}
public int getNumber2() {
return this.number2;
}
public void setNumber3(int number3) {
this.number3 = number3;
}
public int getNumber3() {
return this.number3;
}
public void setNumber4(int number4) {
this.number4 = number4;
}
public int getNumber4() {
return this.number4;
}
}
package org.example.beans.exceptions;
import javax.ejb.ApplicationException;
@ApplicationException(rollback = true)
public class CustomException extends Exception {
private static final long serialVersionUID = 1L;
public CustomException() {
super();
}
public CustomException(Throwable t) {
super(t);
}
public CustomException(String detailMessage) {
super(detailMessage);
}
public CustomException(String detailMessage, Throwable t) {
super(detailMessage, t);
}
}
package org.example.beans.data;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.example.beans.models.CustomObject;
import org.example.beans.dao.DaoBeanLocal;
import org.example.beans.exceptions.CustomException;
public class Data {
public void getContent(StringBuffer doc, DaoBeanLocal dao, Integer param1) throws CustomException {
List<CustomObject> list = dao.selectCustomObject(param1);
for (CustomObject obj : list) {
doc.append("------------------");
doc.append("String1: ").append(obj.getNumber1()).append("\n");
doc.append("String2: ").append(obj.getNumber2()).append("\n");
doc.append("String3: ").append(obj.getNumber3()).append("\n");
doc.append("String4: ").append(obj.getNumber4()).append("\n");
}
}
}
package org.example.beans;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import org.example.beans.exceptions.CustomException;
import org.example.beans.data.Data;
import org.example.beans.dao.DaoBeanLocal;
@Stateless
public class DocumentBean implements DocumentRemote {
@PostConstruct
protected void init() {
}
@PreDestroy
protected void destroy() {
}
// DAO local ejb
@EJB
private DaoBeanLocal dao;
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public String generateDocument(String param1, String param2) throws CustomException {
StringBuffer doc = new StringBuffer(10000);
try {
// some utility class
Data data1 = new Data();
Data data2 = new Data();
Data data3 = new Data();
Data data4 = new Data();
// some data from database
List<Integer> list = dao.selectIntegers(param1, param2);
for (Integer param1 : list) {
// a lot of usage of StringBuffer inside methods
data1.getContent(doc, dao, param1);
data2.getContent(doc, dao, param1);
data3.getContent(doc, dao, param1);
data4.getContent(doc, dao, param1);
}
} catch (CustomException e) {
log.error(e.getMessage(), e);
throw e;
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new CustomException(e.getMessage(), e);
}
String result = doc.toString();
return result;
}
}