Hibernate / JPA -> Обнуляемые значения и объекты? - PullRequest
3 голосов
/ 12 июля 2010

Мой основной вопрос: как заставить Hibernate сделать float NULLable и принять NULL для float, datetime, blob, соответственно? Я действительно имею в виду NULL, а не (float) 0.0.

Еще хуже, когда я пытаюсь сохранить объект с нужными NULLable полями, фактически равными NULL, и использую диспетчер сущностей, я получаю ошибки для атрибутов, которые Hibernate помечает как NULLable даже в таблице БД.

Вот то, что я пытался напрасно:

Рассмотрим эту таблицу:

+--------+--------------+------+-----+---------+----------------+
| Field  | Type         | Null | Key | Default | Extra          |
+--------+--------------+------+-----+---------+----------------+
| id     | int(11)      | NO   | PRI | NULL    | auto_increment |
| name   | varchar(255) | NO   |     | NULL    |                |
| number | float        | YES  |     | NULL    |                |
| url    | varchar(3)   | YES  |     | NULL    |                |
| mydate | date         | YES  |     | NULL    |                |
+--------+--------------+------+-----+---------+----------------+

который был создан этими утверждениями:

DROP SCHEMA IF EXISTS `mydb` ;
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
USE `mydb` ;

DROP TABLE IF EXISTS `mydb`.`test` ;
CREATE  TABLE IF NOT EXISTS `mydb`.`test` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(255) NOT NULL ,
  `number` FLOAT NULL,
  `url` VARCHAR(3) NULL ,
  `mydate` DATE NULL ,
  PRIMARY KEY (`id`) ,
  UNIQUE INDEX `id_UNIQUE` (`id` ASC) )
ENGINE = InnoDB;

Если я выполняю следующую вставку:

INSERT INTO `mydb`.`test` (`name`) VALUES ('MyName');
SELECT * FROM `mydb`.`test`;

Я получаю следующий результат:

+----+--------+--------+------+--------+
| id | name   | number | url  | mydate |
+----+--------+--------+------+--------+
|  1 | MyName |   NULL | NULL | NULL   |
+----+--------+--------+------+--------+
1 row in set (0.00 sec)

это именно то, что я хочу.

В Hibernate 3.5 / JPA2 я пытаюсь сделать мой ORM следующим образом:

BO:

public class BodyStat extends BusinessObject {

@Id
private int id;

private String name;

@Column(nullable = true)
private float number;

@Column(nullable = true)
private URL url;

@Column(nullable = true)
private Date myDate;

... C'Tor / setters / getters / eof

и сущность в моем orm.xml выглядит так:

<entity class="test">
    <table name="&quot;test&quot;"/>
    <attributes>
        <id name="id">
            <generated-value strategy="TABLE"/>
        </id>
        <basic name="name"/>
        <basic name="number" optional="true"/>
        <basic name="url"  optional="true"/>
        <basic name="myDate"  optional="true"/>
    </attributes>
</entity>

Теперь таблица, сгенерированная Hibernate, выглядит следующим образом:

+--------+--------------+------+-----+---------+------------+
| Field  | Type         | Null | Key | Default | Extra      |
+--------+--------------+------+-----+---------+------------+
| id     | int(11)      | NO   | PRI | NULL    |            |
| name   | varchar(255) | NO   |     | NULL    |            |
| number | float        | NO   |     | NULL    |            |
| url    | tinyblob     | YES  |     | NULL    |            |
| mydate | date         | YES  |     | NULL    |            |
+--------+--------------+------+-----+---------+------------+

что не совсем то, что я хочу. Как видите

  1. число с плавающей запятой не допускается,
  2. тип "url" оказался как блоб, а не как varchar и
  3. mydate как "дата", а не "datetime"

Ответы [ 3 ]

3 голосов
/ 12 июля 2010

float не обнуляется,

Это странно.nullable используется только как свойство столбца для создания таблицы и должно выполнять свою работу независимо от того, является ли сопоставленное свойство примитивным или нет .По крайней мере, ваш код работает для меня с Derby, я получаю пустую колонку для сгенерированной таблицы.Но очевидно, что использование оболочки (т. Е. Float) на уровне объекта будет иметь смысл, если вы хотите иметь возможность "передавать" значение null.

, к которому обратился тип "url"в виде BLOB-объекта, а не varchar и

Из спецификации JPA 1.0:

2.1.1 Постоянные поля и свойства

...

Постоянные поля или свойства объекта могут быть следующих типов: примитивные типы Java;java.lang.String;другие сериализуемые типы Java (включая обертки примитивных типов, java.math.BigInteger, java.math.BigDecimal, java.util.Date, java.util.Calendar, java.sql.Date, java.sql.Time, java.sql.Timestamp, определяемые пользователем сериализуемые типы, byte[],Byte[], char[] и Character[]);перечисления;типы сущностей и / или коллекции типов сущностей;и встраиваемые классы (см. раздел 2.1.5).

java.net.URL является сериализуемым, вот и все (с точки зрения JPA), поэтому он рассматривается как сериализуемый (и хранится в BLOB).

Если вы действительно хотите сохранить его как String, либо используйте пользовательский UserType (специфичный для Hibernate), либо используйте держатель String и предоставьте метод получения / установки, выполняющий преобразование (ипометить получатель как переходный).Примерно так:

private String urlAsString;

@Transient
public URL getUrl() throws MalformedURLException {
    return new URL(this.urlAsString);
}

public void setUrl(URL url) {
    this.urlAsString = url.toString();
}

@Column(nullable = true)
protected String getUrlAsString() {
    return urlAsString; 
}

protected void setUrlAsString(String urlAsString) {
    this.urlAsString = urlAsString;
}

mydate как "дата", а не "datetime"

Если вы хотите также сохранить часть временивашей даты, сопоставьте ее как метку времени, используя аннотацию @Temporal:

@Column(nullable = true)
@Temporal(TemporalType.TIMESTAMP)
private Date myDate;

PS: Кстати, почему вы предоставляете обе аннотации И orm.xml?Вы знаете, что они как-то эквивалентны?Если вы можете использовать аннотации, просто используйте их, в этом нет необходимости orm.xml.

1 голос
/ 16 июля 2010

Еще раз спасибо за вашу большую поддержку и предложения. На самом деле, я нашел решение сейчас. Как упоминал Паскаль, я использовал как аннотацию, так и конфигурацию xml. Как только я удалил конфигурацию xml, эта проблема была решена.

Я не буду открывать ошибку в спящем режиме, потому что в любом случае лучше не смешивать типы конфигурации, поэтому я бы лучше советовал использовать передовой опыт, чем смешивать типы конфигурации.

Приветствие ER

0 голосов
/ 12 июля 2010

Примитив с плавающей запятой не обнуляем, но java.lang.Float или java.lang.Double is.

Если это не сработает, возможно, вам нужно мыслить более абстрактно.Что представляет этот поплавок?«Число» не очень наглядно.Это баланс счета?Что-то еще, что имеет значение для вашей проблемы?Если да, оберните его в объект, который лучше описывает и абстрагирует его.

Java - объектно-ориентированный язык, а "O" в ORM обозначает объекты.Думайте меньше с точки зрения примитивов и реляционных столбцов и больше с точки зрения объектов.Если вы сделаете это, вам будет проще найти Hibernate.

...