我面对这个问题一个星期,我希望有人会为我找到解决方案。
当我进行合并时,数据库中的行不会更新。 在日志中,我看到发送给Oracle的更新
[EL Finest]: transaction: 2016-02-22 11:14:19.069--UnitOfWork(2109200496)--Thread(Thread[qtp1457417579-16,5,main])--Merge clone with references com.leray.test.User@610b894a
[EL Finer]: transaction: 2016-02-22 11:14:19.069--UnitOfWork(2109200496)--Thread(Thread[qtp1457417579-16,5,main])--begin unit of work flush
[EL Finest]: query: 2016-02-22 11:14:19.07--UnitOfWork(2109200496)--Thread(Thread[qtp1457417579-16,5,main])--Execute query UpdateObjectQuery(com.leray.test.User@610b894a)
[EL Finest]: connection: 2016-02-22 11:14:19.071--ServerSession(1907961337)--Connection(307503319)--Thread(Thread[qtp1457417579-16,5,main])--Connection acquired from connection pool [default].
[EL Finer]: transaction: 2016-02-22 11:14:19.071--ClientSession(925275938)--Connection(307503319)--Thread(Thread[qtp1457417579-16,5,main])--begin transaction
[EL Fine]: sql: 2016-02-22 11:14:19.071--ClientSession(925275938)--Connection(307503319)--Thread(Thread[qtp1457417579-16,5,main])--UPDATE USER SET LIB = ? WHERE (CODE = ?)
bind => [ModifiedLib, COD1]
[EL Finer]: transaction: 2016-02-22 11:14:19.099--UnitOfWork(2109200496)--Thread(Thread[qtp1457417579-16,5,main])--end unit of work flush
[EL Finer]: transaction: 2016-02-22 11:14:19.099--UnitOfWork(2109200496)--Thread(Thread[qtp1457417579-16,5,main])--resume unit of work
[EL Finer]: transaction: 2016-02-22 11:14:19.099--UnitOfWork(2109200496)--Thread(Thread[qtp1457417579-16,5,main])--begin unit of work commit
[EL Finer]: transaction: 2016-02-22 11:14:19.1--ClientSession(925275938)--Connection(307503319)--Thread(Thread[qtp1457417579-16,5,main])--commit transaction
[EL Finest]: connection: 2016-02-22 11:14:19.142--ServerSession(1907961337)--Connection(307503319)--Thread(Thread[qtp1457417579-16,5,main])--Connection released to connection pool [default].
[EL Finer]: transaction: 2016-02-22 11:14:19.143--UnitOfWork(2109200496)--Thread(Thread[qtp1457417579-16,5,main])--end unit of work commit
[EL Finer]: transaction: 2016-02-22 11:14:19.143--UnitOfWork(2109200496)--Thread(Thread[qtp1457417579-16,5,main])--resume unit of work
SQL Developper中的相同语句可以与同一个用户一起使用。
我只针对一个表有这个问题。我没有看到这个表有什么特别的东西,触发器存在,但我认为它不能解释我的问题。
我的代码是用Java 1.8编译的,我使用的是JPA和Oracle版本。
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc7</artifactId>
<version>12.1.0.2</version>
</dependency>
使用Eclipse生成的对象非常简单。
package com.leray.test;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
/**
* The persistent class for the User database table.
*
*/
@Entity
@NamedQuery(name="User.findAll", query="SELECT e FROM User e")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private String code;
private String ecran;
private String lib;
private String mdp;
public User() {
}
public String getCode() {
return this.code;
}
public void setCode(String code) {
this.code = code;
}
public String getEcran() {
return this.ecran;
}
public void setEcran(String ecran) {
this.ecran = ecran;
}
public String getLib() {
return this.lib;
}
public void setLib(String lib) {
this.lib = lib;
}
public String getMdp() {
return this.mdp;
}
public void setMdp(String mdp) {
this.mdp = mdp;
}
}
My Persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="test">
<class>com.leray.test.User</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@server:1521:siddb"/>
<property name="javax.persistence.jdbc.user" value="****"/>
<property name="javax.persistence.jdbc.password" value="****"/>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
<property name="eclipselink.logging.level" value="ALL"/>
<property name="eclipselink.logging.exceptions" value="true"/>
<property name="eclipselink.logging.session" value="true"/>
<property name="eclipselink.logging.thread" value="true"/>
<property name="eclipselink.logging.timestamp" value="true"/>
<property name="eclipselink.logging.connection" value="true"/>
<property name="eclipselink.weaving" value="false"/>
</properties>
</persistence-unit>
</persistence>
我调用合并的代码
public final void miseAJour(Evuti evuti) {
em.getTransaction().begin();
em.merge(evuti);
em.flush();
em.getTransaction().commit();
}
更新2016-02-23:我已经与DBA核对过,我在Oracle端看到了更新声明,但他无法确认eclipselink发送的参数。我仍然不知道要解决这个问题。
答案 0 :(得分:0)
我找到了根本原因和解决方案。 问题来自使用CHAR而不是VARCHAR。
如果您想尝试,请提供快速示例。
CREATE TABLE SHORT_TEST
( "CODE" CHAR(10 BYTE),
"LIB" CHAR(30 BYTE)
)
TABLESPACE "DATADBS" ;
INSERT INTO SHORT_TEST VALUES ('LIB1','COD1');
-- 1 line inserted
UPDATE SHORT_TEST SET LIB = 'LIB2' WHERE (CODE = 'COD1');
-- You get 1 line updated
-- Now, try this update which is used by eclipselink
UPDATE SHORT_TEST SET LIB = :1 WHERE (CODE = :2);
-- 0 line updated
在char列上使用查询参数时,必须遵守列大小。在此示例中,如果您使用六个空格填充COD1,则查询将起作用。
不幸的是,我必须使用旧的Oracle数据库,而我无权更改结构。
默认情况下,eclipselink会对字段执行修剪。 这就是甲骨文COD1&#39;与COD1&#39;
不匹配Eclipselink提供了禁用自动修剪的可能性。 https://wiki.eclipse.org/EclipseLink/FAQ/JPA#How_to_avoid_trimming_the_trailing_spaces_on_a_CHAR_field.3F
因此,在我的项目中,我使用此代码创建了一个新类。
package com.leray.test;
import org.eclipse.persistence.dynamic.DynamicHelper.SessionCustomizer;
import org.eclipse.persistence.sessions.Session;
public class JpaSessionCustomizer extends SessionCustomizer {
public void customize(Session session) {
session.getLogin().setShouldTrimStrings(false);
}
}
我已将此属性添加到persistence.xml
<property name="eclipselink.session.customizer" value="com.leray.test.JpaSessionCustomizer"/>
现在Eclipselink返回带有结束空格的数据,并且Oracle中的更新正在运行。