Je me heurte à un problème d'heure d'été inattendu dans le code que je pensais être purement UTC. J'utilise Java 1.6, le mappeur SQL iBatis (2.3.3) et Oracle XE (une version eval d'Oracle 10.2) avec le pilote thin Oracle.Quelle est la bonne façon de gérer les dates UTC en utilisant Java, iBatis et Oracle?
La base de données contient une table qui représente un programme de diffusion télévisée. Chaque "actif" (programme) a une heure de début et une heure de fin. Voici la tranche pertinente:
create table Asset
(
asset_id integer not null, -- The unique id of the Asset.
[...]
start_time timestamp, -- The start time.
end_time timestamp, -- The end time.
[...]
constraint asset_primary_key primary key (asset_id),
constraint asset_time check (end_time >= start_time)
);
L'oracle asset_time
contrainte de tir pour des programmes qui chevauchent le réglage de l'heure de l'heure d'été centrale américaine ce dimanche matin à venir, 11/1/2009.
J'ai cet objet de transfert de données (les dates sont java.util.Dates):
public class Asset
{
protected Long asset_id;
[...]
protected Date start_time;
protected Date end_time;
public Date getStart_time() { return start_time; }
public Date getEnd_time() { return end_time; }
public void setStart_time(Date start_time) { this.start_time = start_time; }
public void setEnd_time(Date end_time) { this.end_time = end_time; }
[...]
}
Et dans la carte iBatis SQL J'ai cette déclaration qui insère un actif DTO dans la table Oracle Asset:
<insert id="Asset.insert" parameterClass="com.acme.Asset">
insert into Asset
(asset_id, [...] start_time, end_time)
values
(#asset_id#, [...] #start_time#, #end_time#)
</insert>
du côté Java j'ai vérifié que je donne iBatis l'entrée de la date UTC correcte via cette affirmation pré-insertion, qui n'est pas jeté:
System.err.println("Inserting asset " + program_id);
System.err.println(" "+asset.getStart_time_str()+"--"+asset.getEnd_time_str());
if (!asset.getEnd_time().after(asset.getStart_time())) {
System.err.println("Invalid datetime range in asset.");
throw new AssertionError("Invalid datetime range in asset.");
}
Juste avant l'échec de contrainte Oracle les impressions de code ci-dessus:
Inserting asset EP011453960004
2009-11-01T06:30:00Z--2009-11-01T07:00:00Z
Je suis dans le fuseau horaire centrale américaine, GMT -5: 00, donc ce programme commence à 01h30 et se termine à 02h00. L'heure d'été change à 2h00 du matin et revient à 1h00 du matin.
iBatis signale l'échec de contrainte Oracle (modifiée):
2009-10-30 22:58:42,238 [...] Executing Statement:
insert into Asset (asset_id, [...] start_time, end_time)
values (?, [...] ?, ?)
2009-10-30 22:58:42,238 [...] Parameters:
[EP011453960004, [...] 2009-11-01 01:30:00.0, 2009-11-01 01:00:00.0]
2009-10-30 22:58:42,238 [..] Types:
[java.lang.Long, [...] java.sql.Timestamp, java.sql.Timestamp]
2009-10-30 22:58:42,285 [...] - Failed with a SQLException:
--- The error occurred in com/acme/data/dao/Asset-Write.xml.
--- The error occurred while applying a parameter map.
--- Check the Asset.insert-InlineParameterMap.
--- Check the statement (update failed).
--- Cause: java.sql.SQLException: ORA-02290: check constraint (ACME.ASSET_TIME)
violated
Vous remarquerez que sur le côté Oracle, il est de voir le start_time/end_time avec le réglage de l'heure de l'heure d'été, donc quelque chose dans la cartographie iBatis logique ou le pilote Oracle ne fait pas ce que je m'attendais. Le pilote est ojdbc14.jar, le conducteur mince:
JDBCReadWrite.Driver = oracle.jdbc.OracleDriver
JDBCReadWrite.ConnectionURL = jdbc:oracle:thin:@localhost:1521:XE
Quelle est la bonne façon de faire en sorte que ce code est purement UTC?
Merci d'avance!
quel fichier ajoutez-vous ce tag de typehandler? Est-ce supporté par ibaits 2.3? – DDK