JPA合并不更新表

时间:2016-02-22 11:10:07

标签: oracle jpa

我面对这个问题一个星期,我希望有人会为我找到解决方案。

当我进行合并时,数据库中的行不会更新。 在日志中,我看到发送给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发送的参数。我仍然不知道要解决这个问题。

1 个答案:

答案 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中的更新正在运行。