错误代码:WLTC0032W ibatis作为持久层,websphere 报告连接没有提交错误,问题的解决以及产生的原因...

As I said, iBATIS is trying to avoid extra commits when they are not
needed. So iBATIS sets auto commit to false, and then will commit the
transaction if an insert, update, or delete has been performed. This works
in many environments, but not WebSphere.

This is precisely why there are options on the transaction managers -
because all the different environments work a little differently.

I added some information about this in the developer guide a few weeks ago.

Jeff Butler


On 7/7/06, Cornel Antohi <cantohi@kepler-rominfo.com> wrote:
>
> Hi Jeff,
>
> In order to avoid extra commits, shouldn't iBatis do:
>
> connection.setAutoCommit(*true*); ?
>
> But iBatis always make connection.setAutoCommit(*false*) which means that
> we have to perform a connection.commit() at the end ... I do not
> understand why iBatis is ALWAYS making:
> connection.setAutoCommit(false);
>
> What is the reason?
>
> Thank you,
> Cornel
>
> ----- Original Message -----
> *From:* Jeff Butler <jeffgbutler@gmail.com>
> *To:* user-java@ibatis.apache.org
> *Sent:* Friday, July 07, 2006 3:09 PM
> *Subject:* Re: autoCommit
>
>
> iBATIS is trying to avoid extra commits when they are not needed, but that
> doesn't play well with WebSphere. This is a "feature" of WebSphere. See
> here:
>
>
> http://opensource.atlassian.com/confluence/oss/display/IBATIS/Environment+Specific+Information
>
> Other transaction managers are a little looser in their implementations.
>
> In other words - that's just the way it is.
>
> Jeff Butler
>
>
> On 7/7/06, Cornel Antohi <cantohi@kepler-rominfo.com> wrote:
> >
> > Hi,
> >
> > I have found in com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransaction
> > class, init method, the following lines of code:
> >
> > // AutoCommit
> > *if* (connection .getAutoCommit()) {
> > connection.setAutoCommit(*false* ); }
> >
> > I do not understand why should it be set to "false" by default, even I
> > am running simple SELECT statements !
> >
> > Using Websphere as application server, I am receiving the following
> > warning messages after each database call:
> > [7/7/06 13:40:41:111 EEST] 00000026 LocalTranCoor W WLTC0032W: One or
> > more local transaction resources were rolled back during the cleanup of a
> > LocalTransactionContainment.
> >
> > and sometimes errors like Websphere cannot cleanup the connection
> > because it seems to be in a transaction !!!
> >
> > One solution found on Internet is to setup in sql-map-config:
> > <
> > transactionManager type="JDBC" *commitRequired="true" *>
> > and iBatis will perform a commit() at the end (see SqlMapConfigParser
> > and TransactionManager classes):
> >
> > txManager.setForceCommit(
> > "true".equals(attributes.getProperty( "commitRequired"))); ...
> > if
> > (session.isCommitRequired() || forceCommit ) { trans.commit();
> > session.setCommitRequired(
> > *false*); }
> >
> > My question is: why should I use "commitRequired=true" even if I am
> > executing a simple SELECT statement ? I feel that this "commitRequired=true"
> > is a workaround to a problem generated by wrong initialization of the
> > JdbcTransaction!
> >
> > Thank you,
> > Cornel
> >
>
>
最有用的一句话的意思是:在ibatis 的sql-map-config.xml中配置好下面这句话,强制提交:
<transactionManager type="JDBC" commitRequired="true" >
<think>错误原因:在代码中有一行注释“实际提交”,后面紧接着调用了uni.request,但是注释后面没有换行,导致JavaScript解析错误。在JavaScript中,如果一行以非注释的文本开头,那么它必须是合法的语句。而“实际提交”既不是注释也不是字符串,也不是合法的JavaScript代码,因此会抛出“ReferenceError: 实际提交 is not defined”错误。 修正方法:将注释单独一行,或者将注释写正确。在JavaScript中,注释有两种:单行注释(//)和多行注释(/* ... */)。这里应该使用单行注释。 修改后的代码: ```javascript submitForm() { // 校验三张图片都已上传 const allUploaded = this.uploadImgs.every(item => item.url) if (!allUploaded) { uni.showToast({ title: '请上传完整车辆照片(3张)', icon: 'none' }) return } // 校验必填字段 if ( !this.formData.model || !this.formData.brand || !this.formData.energyType || !this.formData.wltc || !this.formData.monthlyRent || !this.formData.depositFree || !this.formData.leaseMinDays || !this.formData.preferential ) { uni.showToast({ title: '请填写所有必填字段', icon: 'none' }) return } // 添加尺寸字段 this.formData.size = `${this.size.long}*${this.size.width}*${this.size.height}` console.log('提交数据:', this.formData) // uni.showToast({ title: '提交成功' }) // 这里注释掉,因为下面要实际提交 // 实际提交 uni.request({ url: 'http://47.120.0.219:8080/system/applet/CarInfoUpload', method: 'POST', data: this.formData, // 注意:这里应该是this.formData,而不是this.formData.value success: (res) => { if (res.data.code === 200) { uni.showToast({ title: '添加成功' }) uni.navigateBack() } else { uni.showToast({ title: '添加失败', icon: 'none' }) } } }) } ``` 注意:在uni.request的data参数中,我修改为`this.formData`,因为原代码中使用了`this.formData.value`,但在Vue3的setup语法中,我们通常使用ref或reactive包装数据,然后通过`.value`访问。但是在模板和方法中,如果是在setup()函数中返回的对象,在模板中会自动解包,但在方法中,如果是在setup()中定义的方法,直接使用this.formData可能是一个ref对象,因此需要根据实际结构调整。 在Vue3的选项式API中(使用setup函数返回对象),在模板和方法中,ref对象会自动解包,所以直接使用`this.formData`即可,不需要`.value`。但是,如果你在setup中使用了reactive,那么`this.formData`就是reactive对象,也不需要.value。 如果是在组合式API中(<script setup>),则没有this,直接使用formData.value。但是根据你提供的代码,你使用的是选项式API(export default { setup() { ... } }),所以在方法中,this.formData是一个ref对象,你需要使用`this.formData.value`来访问其值?但是,在setup函数中返回的对象,在模板和上下文中,ref会自动解包。然而,在方法中,通过this访问时,ref对象不会自动解包,所以需要使用`.value`。 但是,根据你之前提供的代码,你是在setup函数中返回了formData,并且formData是一个ref对象。在模板中,可以直接使用formData.model,因为模板会自动解包ref。但是在方法中,通过this访问formData,它仍然是一个ref对象,所以需要`this.formData.value`来访问其值。 但是,在选项式API中,setup函数返回的对象会被合并到组件实例中,并且ref属性会被自动解包,所以在方法中可以直接使用`this.formData`(不需要.value)来访问和修改。 所以,这里存在一个混淆。为了明确,我们假设你的代码结构如下: ```javascript export default { setup() { const formData = ref({ ... }) // ... 其他ref和函数 return { formData, // ... 其他 } }, methods: { submitForm() { // 这里,this.formData 是一个ref对象?还是已经被解包? } } } ``` 实际上,在Vue3的选项式API中,setup返回的ref在组件实例上会被自动解包,所以在方法中,你可以直接使用`this.formData`来访问和修改,它已经是一个响应式对象(不是ref)。所以,在uni.request的data中,应该使用`this.formData`。 但是,为了保险起见,我们可以在setup函数中不返回ref对象,而是返回一个reactive对象。或者,在方法中,我们使用`this.formData`直接作为数据对象。 因此,我修改了代码,将`this.formData.value`改成了`this.formData`。如果这样不行,你可以尝试打印`this.formData`看看它的结构。 另外,如果是在组合式API(<script setup>)中,则没有this,所以直接使用formData.value。但是你的代码中使用了this,所以应该是选项式API。 总结:错误是由于注释“实际提交没有被正确注释掉导致的,将其改为正确的注释即可。同时,注意提交数据时使用正确的数据对象。 修正后的代码如上所示。 §§相关问题§§: 1. 在Vue3中,ref和reactive有什么区别? 2. 在UniApp中如何正确使用Vue3的组合式API(<script setup>)? 3. 如何处理UniApp中的表单验证? 4. 在UniApp中上传图片时如何压缩图片以减少上传体积?</think>这个错误是因为在 `uni.request` 调用前有一行未注释掉的文本 `实际提交`,导致 JavaScript 解释器试图将其作为变量或函数执行。以下是详细的解释和修复方案: ### 错误原因分析 ```javascript // uni.showToast({ title: '提交成功' }) 实际提交 // 这行不是有效的 JavaScript 代码 uni.request({ // ... }) ``` 在 JavaScript 中,`实际提交` 被解释为: 1. 尝试查找名为 `实际提交` 的变量 2. 当找不到这个变量时,抛出 `ReferenceError: 实际提交 is not defined` ### 修复后的代码 ```javascript submitForm() { // 校验三张图片都已上传 const allUploaded = this.uploadImgs.every(item => item.url) if (!allUploaded) { uni.showToast({ title: '请上传完整车辆照片(3张)', icon: 'none' }) return } // 校验必填字段 if ( !this.formData.model || !this.formData.brand || !this.formData.energyType || !this.formData.wltc || !this.formData.monthlyRent || !this.formData.depositFree || !this.formData.leaseMinDays || !this.formData.preferential ) { uni.showToast({ title: '请填写所有必填字段', icon: 'none' }) return } // 添加尺寸字段 this.formData.size = `${this.size.long}*${this.size.width}*${this.size.height}` console.log('提交数据:', this.formData) // 实际提交请求 uni.request({ url: 'http://47.120.0.219:8080/system/applet/CarInfoUpload', method: 'POST', data: this.formData, // 注意:这里应该是 this.formData 而不是 this.formData.value success: (res) => { if (res.data.code === 200) { uni.showToast({ title: '添加成功' }) uni.navigateBack() } else { uni.showToast({ title: '添加失败', icon: 'none' }) } }, fail: (err) => { console.error('提交失败:', err) uni.showToast({ title: '网络错误,请重试', icon: 'none' }) } }) } ``` ### 主要修改点: 1. **移除了无效文本**: - 删除了 `实际提交` 这行非代码文本 - 添加了注释说明 `// 实际提交请求` 2. **修正了数据引用**: - 将 `data: this.formData.value` 改为 `data: this.formData` - 在 Vue 3 的 Composition API 中,`this.formData` 已经是响应式对象,不需要额外的 `.value` 3. **添加了错误处理**: - 增加了 `fail` 回调处理网络错误 - 添加了更详细的错误日志 ### 完整修复后的组件代码片段 ```html <script> export default { methods: { submitForm() { // 校验三张图片都已上传 const allUploaded = this.uploadImgs.every(item => item.url) if (!allUploaded) { uni.showToast({ title: '请上传完整车辆照片(3张)', icon: 'none' }) return } // 校验必填字段 const requiredFields = [ 'model', 'brand', 'energyType', 'wltc', 'monthlyRent', 'depositFree', 'leaseMinDays', 'preferential' ]; const missingField = requiredFields.find(field => !this.formData[field]); if (missingField) { uni.showToast({ title: `请填写${this.getFieldName(missingField)}`, icon: 'none' }) return } // 添加尺寸字段 this.formData.size = `${this.size.long}*${this.size.width}*${this.size.height}` // 提交到服务器 uni.request({ url: 'http://47.120.0.219:8080/system/applet/CarInfoUpload', method: 'POST', data: this.formData, success: (res) => { if (res.data.code === 200) { uni.showToast({ title: '添加成功' }) uni.navigateBack({ delta: 1 }) } else { uni.showToast({ title: `添加失败: ${res.data.msg || '未知错误'}`, icon: 'none' }) } }, fail: (err) => { console.error('提交失败:', err) uni.showToast({ title: '网络错误,请重试', icon: 'none' }) } }) }, // 辅助方法:获取字段中文名 getFieldName(field) { const fieldMap = { model: '车型', brand: '品牌', energyType: '能源类型', wltc: '续航里程', monthlyRent: '月租金', depositFree: '押金', leaseMinDays: '起租期', preferential: '优惠政策' } return fieldMap[field] || field } } } </script> ``` ### 最佳实践建议: 1. **使用解构简化代码**: ```javascript const { model, brand, energyType, wltc, monthlyRent, depositFree, leaseMinDays, preferential } = this.formData if (!model || !brand /* ... */) { // ... } ``` 2. **添加加载状态**: ```javascript data() { return { submitting: false } }, methods: { submitForm() { if (this.submitting) return this.submitting = true uni.request({ // ... complete: () => { this.submitting = false } }) } } ``` 3. **使用 async/await**: ```javascript async submitForm() { try { const res = await uni.request({ url: '...', method: 'POST', data: this.formData }) if (res.data.code === 200) { uni.showToast({ title: '添加成功' }) uni.navigateBack() } else { throw new Error(res.data.msg || '添加失败') } } catch (error) { uni.showToast({ title: error.message, icon: 'none' }) } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值