• JavaPersistenceWithHibernate第二版笔记-第五章-Mapping value types-006类型转换器( @Converter(autoApply = true) 、type="converter:qualified.ConverterName" )


    一、结构

    二、代码

    1.

     1 package org.jpwh.model.advanced;
     2 
     3 import java.io.Serializable;
     4 import java.math.BigDecimal;
     5 import java.util.Currency;
     6 
     7 /* 
     8    This value-typed class should be <code>java.io.Serializable</code>: When Hibernate stores entity
     9    instance data in the shared second-level cache (see <a href="#Caching"/>), it <em>disassembles</em>
    10    the entity's state. If an entity has a <code>MonetaryAmount</code> property, the serialized
    11    representation of the property value will be stored in the second-level cache region. When entity
    12    data is retrieved from the cache region, the property value will be deserialized and reassembled.
    13  */
    14 public class MonetaryAmount implements Serializable {
    15 
    16     /*
    17  The class does not need a special constructor, you can make it immutable, even with
    18         <code>final</code> fields, as your code will be the only place an instance is created.
    19      */
    20     protected final BigDecimal value;
    21     protected final Currency currency;
    22 
    23     public MonetaryAmount(BigDecimal value, Currency currency) {
    24         this.value = value;
    25         this.currency = currency;
    26     }
    27 
    28     public BigDecimal getValue() {
    29         return value;
    30     }
    31 
    32     public Currency getCurrency() {
    33         return currency;
    34     }
    35 
    36     /*
    37  You should implement the <code>equals()</code> and <code>hashCode()</code>
    38         methods, and compare monetary amounts "by value".
    39      */
    40     public boolean equals(Object o) {
    41         if (this == o) return true;
    42         if (!(o instanceof MonetaryAmount)) return false;
    43 
    44         final MonetaryAmount monetaryAmount = (MonetaryAmount) o;
    45 
    46         if (!value.equals(monetaryAmount.value)) return false;
    47         if (!currency.equals(monetaryAmount.currency)) return false;
    48 
    49         return true;
    50     }
    51 
    52     public int hashCode() {
    53         int result;
    54         result = value.hashCode();
    55         result = 29 * result + currency.hashCode();
    56         return result;
    57     }
    58 
    59     /*
    60  You will need a <code>String</code> representation of a monetary
    61         amount. Implement the <code>toString()</code> method and a static method to
    62         create an instance from a <code>String</code>.
    63      */
    64     public String toString() {
    65         return getValue() + " " + getCurrency();
    66     }
    67 
    68     public static MonetaryAmount fromString(String s) {
    69         String[] split = s.split(" ");
    70         return new MonetaryAmount(
    71             new BigDecimal(split[0]),
    72             Currency.getInstance(split[1])
    73         );
    74     }
    75 }

    2.

     1 package org.jpwh.converter;
     2 
     3 import org.jpwh.model.advanced.MonetaryAmount;
     4 
     5 import javax.persistence.AttributeConverter;
     6 import javax.persistence.Converter;
     7 
     8 @Converter(autoApply = true) // Default for MonetaryAmount properties
     9 public class MonetaryAmountConverter
    10     implements AttributeConverter<MonetaryAmount, String> {
    11 
    12     @Override
    13     public String convertToDatabaseColumn(MonetaryAmount monetaryAmount) {
    14         return monetaryAmount.toString();
    15     }
    16 
    17     @Override
    18     public MonetaryAmount convertToEntityAttribute(String s) {
    19         return MonetaryAmount.fromString(s);
    20     }
    21 }

    3.

     1 package org.jpwh.model.advanced.converter;
     2 
     3 
     4 import org.jpwh.converter.MonetaryAmountConverter;
     5 import org.jpwh.model.advanced.MonetaryAmount;
     6 
     7 import javax.persistence.Column;
     8 import javax.persistence.Convert;
     9 import javax.persistence.Entity;
    10 import javax.persistence.GeneratedValue;
    11 import javax.persistence.Id;
    12 import javax.validation.constraints.NotNull;
    13 import java.util.Date;
    14 
    15 @Entity
    16 public class Item {
    17 
    18     @Id
    19     @GeneratedValue(generator = "ID_GENERATOR")
    20     protected Long id;
    21 
    22     @NotNull
    23     protected String name;
    24 
    25     @NotNull
    26     @Convert( // Optional, autoApply is enabled
    27         converter = MonetaryAmountConverter.class,
    28         disableConversion = false)
    29     @Column(name = "PRICE", length = 63)
    30     protected MonetaryAmount buyNowPrice;
    31 
    32     @NotNull
    33     protected Date createdOn = new Date();
    34 
    35     public Long getId() {
    36         return id;
    37     }
    38 
    39     public String getName() {
    40         return name;
    41     }
    42 
    43     public void setName(String name) {
    44         this.name = name;
    45     }
    46 
    47     public MonetaryAmount getBuyNowPrice() {
    48         return buyNowPrice;
    49     }
    50 
    51     public void setBuyNowPrice(MonetaryAmount buyNowPrice) {
    52         this.buyNowPrice = buyNowPrice;
    53     }
    54 
    55     // ...
    56 }

    4.

     1 package org.jpwh.model.advanced.converter;
     2 
     3 abstract public class Zipcode {
     4 
     5     protected String value;
     6 
     7     public Zipcode(String value) {
     8         this.value = value;
     9     }
    10 
    11     public String getValue() {
    12         return value;
    13     }
    14 
    15     @Override
    16     public boolean equals(Object o) {
    17         if (this == o) return true;
    18         if (o == null || getClass() != o.getClass()) return false;
    19         Zipcode zipcode = (Zipcode) o;
    20         return value.equals(zipcode.value);
    21     }
    22 
    23     @Override
    24     public int hashCode() {
    25         return value.hashCode();
    26     }
    27 }

    5.

     1 package org.jpwh.converter;
     2 
     3 import org.jpwh.model.advanced.converter.GermanZipcode;
     4 import org.jpwh.model.advanced.converter.SwissZipcode;
     5 import org.jpwh.model.advanced.converter.Zipcode;
     6 
     7 import javax.persistence.AttributeConverter;
     8 import javax.persistence.Converter;
     9 
    10 @Converter
    11 public class ZipcodeConverter
    12     implements AttributeConverter<Zipcode, String> {
    13 
    14     @Override
    15     public String convertToDatabaseColumn(Zipcode attribute) {
    16         return attribute.getValue();
    17     }
    18 
    19     @Override
    20     public Zipcode convertToEntityAttribute(String s) {
    21         if (s.length() == 5)
    22             return new GermanZipcode(s);
    23         else if (s.length() == 4)
    24             return new SwissZipcode(s);
    25 
    26         // If you get to this point, you should consider
    27         // cleaning up your database... or you can create
    28         // an InvalidZipCode subclass and return it here.
    29 
    30         throw new IllegalArgumentException(
    31             "Unsupported zipcode in database: " + s
    32         );
    33     }
    34 }

    6.

    1 package org.jpwh.model.advanced.converter;
    2 
    3 public class GermanZipcode extends Zipcode {
    4 
    5     public GermanZipcode(String value) {
    6         super(value);
    7     }
    8 }

    7.

    1 package org.jpwh.model.advanced.converter;
    2 
    3 public class SwissZipcode extends Zipcode {
    4 
    5     public SwissZipcode(String value) {
    6         super(value);
    7     }
    8 }

    8.

     1 package org.jpwh.model.advanced.converter;
     2 
     3 import org.jpwh.converter.ZipcodeConverter;
     4 import org.jpwh.model.Constants;
     5 
     6 import javax.persistence.Convert;
     7 import javax.persistence.Entity;
     8 import javax.persistence.GeneratedValue;
     9 import javax.persistence.Id;
    10 import javax.persistence.Table;
    11 import javax.validation.constraints.NotNull;
    12 import java.io.Serializable;
    13 
    14 @Entity
    15 @Table(name = "USERS")
    16 public class User implements Serializable {
    17 
    18     @Id
    19     @GeneratedValue(generator = Constants.ID_GENERATOR)
    20     protected Long id;
    21 
    22     @NotNull
    23     protected String username;
    24 
    25     // Group multiple attribute conversions with @Converts
    26     @Convert(
    27         converter = ZipcodeConverter.class,
    28         attributeName = "zipcode" // Or "city.zipcode" for nested embeddables
    29     )
    30     protected Address homeAddress;
    31 
    32     public Long getId() {
    33         return id;
    34     }
    35     public String getUsername() {
    36         return username;
    37     }
    38 
    39     public void setUsername(String username) {
    40         this.username = username;
    41     }
    42 
    43     public Address getHomeAddress() {
    44         return homeAddress;
    45     }
    46 
    47     public void setHomeAddress(Address homeAddress) {
    48         this.homeAddress = homeAddress;
    49     }
    50 
    51     // ...
    52 }

    9.

     1 package org.jpwh.model.advanced.converter;
     2 
     3 import javax.persistence.Column;
     4 import javax.persistence.Embeddable;
     5 import javax.validation.constraints.NotNull;
     6 
     7 @Embeddable
     8 public class Address {
     9 
    10     @NotNull
    11     @Column(nullable = false)
    12     protected String street;
    13 
    14     @NotNull
    15     @Column(nullable = false, length = 5)
    16     protected Zipcode zipcode;
    17 
    18     @NotNull
    19     @Column(nullable = false)
    20     protected String city;
    21 
    22     protected Address() {
    23     }
    24 
    25     public Address(String street, Zipcode zipcode, String city) {
    26         this.street = street;
    27         this.zipcode = zipcode;
    28         this.city = city;
    29     }
    30 
    31     public String getStreet() {
    32         return street;
    33     }
    34 
    35     public void setStreet(String street) {
    36         this.street = street;
    37     }
    38 
    39     public Zipcode getZipcode() {
    40         return zipcode;
    41     }
    42 
    43     public void setZipcode(Zipcode zipcode) {
    44         this.zipcode = zipcode;
    45     }
    46 
    47     public String getCity() {
    48         return city;
    49     }
    50 
    51     public void setCity(String city) {
    52         this.city = city;
    53     }
    54 }

    也可以转换集合,If several @Convert annotations are required on a single embedded property, to convert several attributes of the Address , for example, you can group them within an @Converts annotation. You can also apply converters to values of collections and maps, if their values and/or keys are of basic or embeddable type. For example, you can add the @Convert annotation on a persistent Set<Zipcode> . We’ll show you how

    to map persistent collections later, with @ElementCollection , in chapter 7.
    For persistent maps, the attributeName option of the @Convert annotation has some special syntax:

     On a persistent Map<Address, String> , you can apply a converter for the zipcode property of each map key with the attribute name key.zipcode .
     On a persistent Map<String, Address> , you can apply a converter for the zipcode property of each map value with the attribute name value.zipcode .
     On a persistent Map<Zipcode, String> , you can apply a converter for the key of each map entry with the attribute name key .
     On a persistent Map<String, Zipcode> , you can apply a converter for the value of each map entry by not setting any attributeName .
    As before, the attribute name can be a dot-separated path if your embeddable classes are nested; you can write key.city.zipcode to reference the zipcode property of the City class, in a composition with the Address class.
    Some limitations of the JPA converters are as follows:
     You can’t apply them to identifier or version properties of an entity.
     You shouldn’t apply a converter on a property mapped with @Enumerated or @Temporal , because these annotations already declare what kind of conversion has to occur. If you want to apply a custom converter for enums or date/time properties, don’t annotate them with @Enumerated or @Temporal .
     You can apply a converter to a property mapping in an hbm.xml file, but you have to prefix the name: type="converter:qualified.ConverterName" .

  • 相关阅读:
    【vim】分割窗口、标签页与Quickfix窗口
    新手学cocos2dx,centos7下的安装过程
    外部排序,杀鸡焉用牛刀?
    5亿整数的大文件,怎么排?
    【Hadoop】HDFS
    你好,树
    写给博客园博客团队,md的预览在哪里?
    老菜鸟致青春,程序员应该选择java 还是 c#-
    高性能server分析
    高性能服务端漫谈
  • 原文地址:https://www.cnblogs.com/shamgod/p/5364587.html
Copyright © 2020-2023  润新知