JDBC 4 增加了显式处理 nationalized character data 的能力,为此 java.sql.Types 增加了
- NCHAR
- NVARCHAR
- LONGNVARCHAR
- NCLOB
Hibernate 使用 @Nationalized map a specific attribute to a nationalized variant data type
NVARCHAR
package org.example.demo.hibernate;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Persistence;
import org.hibernate.annotations.Nationalized;
public class Test {
public static void main(String[] args) throws Exception {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("test");
EntityManager em = factory.createEntityManager();
Product product = new Product();
product.warranty = "test";
em.getTransaction().begin();
em.persist(product);
em.getTransaction().commit();
em.clear();
Product p = em.find(Product.class, product.id);
// test
System.out.println(p.warranty);
em.close();
factory.close();
}
@Entity(name = "Product")
public static class Product {
@Id
@GeneratedValue
Integer id;
@Nationalized
String warranty;
}
}
生成的 SQL
drop table if exists Product cascade
drop sequence if exists hibernate_sequence
create sequence hibernate_sequence start 1 increment 1
create table Product (id int4 not null, warranty varchar(255), primary key (id))
select nextval ('hibernate_sequence')
insert into Product (warranty, id) values ('test', 1)
select test_produ0_.id as id1_0_0_, test_produ0_.warranty as warranty2_0_0_ from Product test_produ0_ where test_produ0_.id=1
NCLOB
package org.example.demo.hibernate;
import java.io.BufferedReader;
import java.io.Reader;
import java.sql.NClob;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Persistence;
import org.hibernate.annotations.Nationalized;
import org.hibernate.engine.jdbc.NClobProxy;
public class Test {
public static void main(String[] args) throws Exception {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("test");
EntityManager em = factory.createEntityManager();
Product product = new Product();
product.warranty = NClobProxy.generateProxy("test");
em.getTransaction().begin();
em.persist(product);
em.getTransaction().commit();
em.clear();
em.getTransaction().begin();
Product p = em.find(Product.class, product.id);
try (Reader reader = p.warranty.getCharacterStream()) {
BufferedReader in = new BufferedReader(reader);
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
}
em.getTransaction().commit();
em.close();
factory.close();
}
@Entity(name = "Product")
public static class Product {
@Id
@GeneratedValue
Integer id;
@Lob
@Nationalized
NClob warranty;
}
}
在 postgres 下运行第 28 行抛异常 java.sql.SQLFeatureNotSupportedException: 这个 org.postgresql.jdbc.PgPreparedStatement.setNClob(int, NClob) 方法尚未被实作。
使用 materialized form
package org.example.demo.hibernate;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Persistence;
import org.hibernate.annotations.Nationalized;
public class Test {
public static void main(String[] args) throws Exception {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("test");
EntityManager em = factory.createEntityManager();
Product product = new Product();
product.warranty = "test";
em.getTransaction().begin();
em.persist(product);
em.getTransaction().commit();
em.clear();
Product p = em.find(Product.class, product.id);
// test
System.out.println(p.warranty);
em.close();
factory.close();
}
@Entity(name = "Product")
public static class Product {
@Id
@GeneratedValue
Integer id;
@Lob
@Nationalized
String warranty;
}
}
生成 SQL
drop table if exists Product cascade
drop sequence if exists hibernate_sequence
create sequence hibernate_sequence start 1 increment 1
create table Product (id int4 not null, warranty text, primary key (id))
select nextval ('hibernate_sequence')
insert into Product (warranty, id) values ('test', 1)
select test_produ0_.id as id1_0_0_, test_produ0_.warranty as warranty2_0_0_ from Product test_produ0_ where test_produ0_.id=1
package org.example.demo.hibernate;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Persistence;
import org.hibernate.annotations.Nationalized;
public class Test {
public static void main(String[] args) throws Exception {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("test");
EntityManager em = factory.createEntityManager();
Product product = new Product();
product.warranty = "test".toCharArray();
em.getTransaction().begin();
em.persist(product);
em.getTransaction().commit();
em.clear();
Product p = em.find(Product.class, product.id);
// test
System.out.println(p.warranty);
em.close();
factory.close();
}
@Entity(name = "Product")
public static class Product {
@Id
@GeneratedValue
Integer id;
@Lob
@Nationalized
char[] warranty;
}
}
生成 SQL
drop table if exists Product cascade
drop sequence if exists hibernate_sequence
create sequence hibernate_sequence start 1 increment 1
create table Product (id int4 not null, warranty text, primary key (id))
select nextval ('hibernate_sequence')
insert into Product (warranty, id) values ('test', 1)
select test_produ0_.id as id1_0_0_, test_produ0_.warranty as warranty2_0_0_ from Product test_produ0_ where test_produ0_.id=1
如果 application and database 都是完全 nationalized ,则可以设置 hibernate.use_nationalized_character_data 或者 MetadataBuilder#enableGlobalNationalizedCharacterDataSupport() 以默认启用 nationalized character data 。