[ https://issues.apache.org/jira/browse/IGNITE-20024?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
bin.yin updated IGNITE-20024: ----------------------------- Description: h3. Question: {{First, I use ??IgniteCache#loadCache?? load from RDBMS. When I use IgniteCache.get(key) to get the corresponding entity, ignite throws the following error "Can not set java.time.LocalDateTime field org.apache.ignite.examples.model.Person.createdTime to java.sql .Timestamp"}} h3. Conditions and usage: # This code run in 'ignite-examples' module; # In ignite 2.14.0, I use H2 as the underlying storage; # In {{{}CacheJdbcPojoStoreFactory{}}}, I configured the mapping between the {{datetime type}} of the database and JDK8's {{{}LocalDateTime{}}}: {{new JdbcTypeField(Types.TIMESTAMP, "created_time", LocalDateTime.class, "createdTime")}} h3. Problem analysis: By default, {{CacheJdbcPojoStore}} uses {{org.apache.ignite.cache.store.jdbc.JdbcTypesTransformer#getColumnValue}} to parse jdbc's ResultSet. For the {{LocalDateTime}} type of JDK8, {{java.sql.ResultSet#getObject(int)}} is used to obtain the value of the specified column (here it is read as {{{}java.sql.Timestamp{}}}). When the object is finally constructed, the type is inconsistent Causes {{sun.reflect.FieldAccessor#set}} assignment to fail. *Java Code:* CacheJdbcPojoStore.java: {code:java} package org.apache.ignite.examples.datagrid.store.auto; import org.apache.ignite.Ignite; import org.apache.ignite.IgniteCache; import org.apache.ignite.Ignition; import org.apache.ignite.cache.CacheAtomicityMode; import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory; import org.apache.ignite.cache.store.jdbc.JdbcType; import org.apache.ignite.cache.store.jdbc.JdbcTypeField; import org.apache.ignite.cache.store.jdbc.dialect.H2Dialect; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.examples.model.Person; import org.apache.ignite.examples.util.DbH2ServerStartup; import org.h2.jdbcx.JdbcConnectionPool; import javax.cache.configuration.Factory; import javax.sql.DataSource; import java.sql.Types; import java.time.LocalDateTime; /** * To start the example, you should: * <ul> * <li>Start H2 database TCP server using {@link DbH2ServerStartup}.</li> * <li>Start example using {@link CacheAutoStoreExample}.</li> * </ul> * <p> */ public class CacheJdbcPojoStore { private static final String CACHE_NAME = CacheJdbcPojoStore.class.getSimpleName(); public static void main(String[] args) throws Exception { DbH2ServerStartup.populateDatabase(); try (Ignite ignite = Ignition.start("example-ignite.xml")) { System.out.println(); System.out.println(">>> Cache store example started."); try (IgniteCache<Long, Person> cache = ignite.getOrCreateCache(cacheConfiguration())) { cache.loadCache(null, Long.class.getName(), "SELECT * FROM PERSON WHERE ID = 3"); System.out.println(cache.get(3L)); } finally { ignite.destroyCache(CACHE_NAME); } } } private static CacheConfiguration<Long, Person> cacheConfiguration() { CacheConfiguration<Long, Person> cacheCfg = new CacheConfiguration<>(CACHE_NAME); cacheCfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL); // Configure JDBC store. CacheJdbcPojoStoreFactory<Long, Person> factory = new CacheJdbcPojoStoreFactory<>(); factory.setDialect(new H2Dialect()); factory.setDataSourceFactory((Factory<DataSource>) () -> { return JdbcConnectionPool.create("jdbc:h2:tcp://localhost/mem:ExampleDb", "sa", ""); }); JdbcType jdbcType = new JdbcType(); jdbcType.setCacheName(CACHE_NAME); jdbcType.setDatabaseTable("PERSON"); jdbcType.setKeyType(Long.class); jdbcType.setValueType(Person.class); jdbcType.setKeyFields(new JdbcTypeField(Types.BIGINT, "id", Long.class, "id")); jdbcType.setValueFields( new JdbcTypeField(Types.BIGINT, "id", Long.class, "id"), new JdbcTypeField(Types.VARCHAR, "first_name", String.class, "firstName"), new JdbcTypeField(Types.VARCHAR, "last_name", String.class, "lastName"), new JdbcTypeField(Types.TIMESTAMP, "created_time", LocalDateTime.class, "createdTime") ); factory.setTypes(jdbcType); cacheCfg.setCacheStoreFactory(factory); cacheCfg.setIndexedTypes(Long.class, Person.class); return cacheCfg; } } {code} Person.java: {code:java} package org.apache.ignite.examples.model; import java.io.Serializable; import java.time.LocalDateTime; import java.util.concurrent.atomic.AtomicLong; import org.apache.ignite.cache.affinity.AffinityKey; import org.apache.ignite.cache.query.annotations.QuerySqlField; import org.apache.ignite.cache.query.annotations.QueryTextField; /** * Person class. */ public class Person implements Serializable { /** */ private static final AtomicLong ID_GEN = new AtomicLong(); /** Name of index by two fields (orgId, salary). */ public static final String ORG_SALARY_IDX = "ORG_SALARY_IDX"; /** Person ID (indexed). */ @QuerySqlField(index = true) public Long id; /** Organization ID (indexed). */ @QuerySqlField(index = true, orderedGroups = @QuerySqlField.Group(name = ORG_SALARY_IDX, order = 0)) public Long orgId; /** First name (not-indexed). */ @QuerySqlField public String firstName; /** Last name (not indexed). */ @QuerySqlField public String lastName; @QuerySqlField public LocalDateTime createdTime; /** Resume text (create LUCENE-based TEXT index for this field). */ @QueryTextField public String resume; /** Salary (indexed). */ @QuerySqlField(index = true, orderedGroups = @QuerySqlField.Group(name = ORG_SALARY_IDX, order = 1)) public double salary; /** Custom cache key to guarantee that person is always colocated with its organization. */ private transient AffinityKey<Long> key; /** * Default constructor. */ public Person() { // No-op. } /** * Constructs person record. * * @param org Organization. * @param firstName First name. * @param lastName Last name. * @param salary Salary. * @param resume Resume text. */ public Person(Organization org, String firstName, String lastName, double salary, String resume) { // Generate unique ID for this person. id = ID_GEN.incrementAndGet(); orgId = org.id(); this.firstName = firstName; this.lastName = lastName; this.createdTime = LocalDateTime.now(); this.salary = salary; this.resume = resume; } /** * Constructs person record. * * @param id Person ID. * @param orgId Organization ID. * @param firstName First name. * @param lastName Last name. * @param salary Salary. * @param resume Resume text. */ public Person(Long id, Long orgId, String firstName, String lastName, double salary, String resume) { this.id = id; this.orgId = orgId; this.firstName = firstName; this.lastName = lastName; this.createdTime = LocalDateTime.now(); this.salary = salary; this.resume = resume; } /** * Constructs person record. * * @param id Person ID. * @param firstName First name. * @param lastName Last name. */ public Person(Long id, String firstName, String lastName) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.createdTime = LocalDateTime.now(); } /** * Gets cache affinity key. Since in some examples person needs to be collocated with organization, we create * custom affinity key to guarantee this collocation. * * @return Custom affinity key to guarantee that person is always collocated with organization. */ public AffinityKey<Long> key() { if (key == null) key = new AffinityKey<>(id, orgId); return key; } /** * {@inheritDoc} */ @Override public String toString() { return "Person [id=" + id + ", orgId=" + orgId + ", lastName=" + lastName + ", firstName=" + firstName + ", createdTime=" + createdTime + ", salary=" + salary + ", resume=" + resume + ']'; } } {code} DbH2ServerStartup.java: {code:java} package org.apache.ignite.examples.util; import java.io.IOException; import java.io.StringReader; import java.sql.SQLException; import org.apache.ignite.IgniteException; import org.h2.jdbcx.JdbcConnectionPool; import org.h2.tools.RunScript; import org.h2.tools.Server; /** * Start H2 database TCP server in order to access sample in-memory database from other processes. */ public class DbH2ServerStartup { /** Create table script. */ private static final String CREATE_PERSON_TABLE = "create table if not exists PERSON(id bigint AUTO_INCREMENT PRIMARY KEY, first_name varchar(50), last_name varchar(50), created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP);"; /** Sample data script. */ private static final String POPULATE_PERSON_TABLE = "delete from PERSON;\n" + "insert into PERSON(id, first_name, last_name) values(1, 'Johannes', 'Kepler');\n" + "insert into PERSON(id, first_name, last_name) values(2, 'Galileo', 'Galilei');\n" + "insert into PERSON(id, first_name, last_name) values(3, 'Henry', 'More');\n" + "insert into PERSON(id, first_name, last_name) values(4, 'Polish', 'Brethren');\n" + "insert into PERSON(id, first_name, last_name) values(5, 'Robert', 'Boyle');\n" + "insert into PERSON(id, first_name, last_name) values(6, 'Wilhelm', 'Leibniz');"; /** * 初始化数据库 * * @throws SQLException if */ public static void populateDatabase() throws SQLException { // Try to connect to database TCP server. JdbcConnectionPool dataSrc = JdbcConnectionPool.create("jdbc:h2:tcp://localhost/mem:ExampleDb", "sa", ""); // Create Person table in database. RunScript.execute(dataSrc.getConnection(), new StringReader(CREATE_PERSON_TABLE)); // Populates Person table with sample data in database. RunScript.execute(dataSrc.getConnection(), new StringReader(POPULATE_PERSON_TABLE)); } /** * Start H2 database TCP server. * * @param args Command line arguments, none required. * @throws IgniteException If start H2 database TCP server failed. */ public static void main(String[] args) throws IgniteException { try { // Start H2 database TCP server in order to access sample in-memory database from other processes. Server.createTcpServer("-tcpDaemon").start(); Server.createWebServer("-webDaemon").start(); populateDatabase(); } catch (SQLException e) { throw new IgniteException("Failed to start database TCP server", e); } try { do { System.out.println("Type 'q' and press 'Enter' to stop H2 TCP server..."); } while ('q' != System.in.read()); } catch (IOException ignored) { // No-op. } } } {code} was: h3. Question: First, I use ??IgniteCache#loadCache?? load from RDBMS. When I use IgniteCache.get(key) to get the corresponding entity, ignite throws the following error "Can not set java.time.LocalDateTime field org.apache.ignite.examples.model.Person.createdTime to java.sql .Timestamp" h3. Conditions and usage: # This code run in 'ignite-examples' module; # In ignite 2.14.0, I use H2 as the underlying storage; # In {{{}CacheJdbcPojoStoreFactory{}}}, I configured the mapping between the {{datetime type}} of the database and JDK8's {{{}LocalDateTime{}}}: {{new JdbcTypeField(Types.TIMESTAMP, "created_time", LocalDateTime.class, "createdTime")}} h3. Problem analysis: By default, {{CacheJdbcPojoStore}} uses {{org.apache.ignite.cache.store.jdbc.JdbcTypesTransformer#getColumnValue}} to parse jdbc's ResultSet. For the {{LocalDateTime}} type of JDK8, {{java.sql.ResultSet#getObject(int)}} is used to obtain the value of the specified column (here it is read as {{{}java.sql.Timestamp{}}}). When the object is finally constructed, the type is inconsistent Causes {{sun.reflect.FieldAccessor#set}} assignment to fail. *Java Code:* CacheJdbcPojoStore.java: {code:java} package org.apache.ignite.examples.datagrid.store.auto; import org.apache.ignite.Ignite; import org.apache.ignite.IgniteCache; import org.apache.ignite.Ignition; import org.apache.ignite.cache.CacheAtomicityMode; import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory; import org.apache.ignite.cache.store.jdbc.JdbcType; import org.apache.ignite.cache.store.jdbc.JdbcTypeField; import org.apache.ignite.cache.store.jdbc.dialect.H2Dialect; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.examples.model.Person; import org.apache.ignite.examples.util.DbH2ServerStartup; import org.h2.jdbcx.JdbcConnectionPool; import javax.cache.configuration.Factory; import javax.sql.DataSource; import java.sql.Types; import java.time.LocalDateTime; /** * To start the example, you should: * <ul> * <li>Start H2 database TCP server using {@link DbH2ServerStartup}.</li> * <li>Start example using {@link CacheAutoStoreExample}.</li> * </ul> * <p> */ public class CacheJdbcPojoStore { private static final String CACHE_NAME = CacheJdbcPojoStore.class.getSimpleName(); public static void main(String[] args) throws Exception { DbH2ServerStartup.populateDatabase(); try (Ignite ignite = Ignition.start("example-ignite.xml")) { System.out.println(); System.out.println(">>> Cache store example started."); try (IgniteCache<Long, Person> cache = ignite.getOrCreateCache(cacheConfiguration())) { cache.loadCache(null, Long.class.getName(), "SELECT * FROM PERSON WHERE ID = 3"); System.out.println(cache.get(3L)); } finally { ignite.destroyCache(CACHE_NAME); } } } private static CacheConfiguration<Long, Person> cacheConfiguration() { CacheConfiguration<Long, Person> cacheCfg = new CacheConfiguration<>(CACHE_NAME); cacheCfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL); // Configure JDBC store. CacheJdbcPojoStoreFactory<Long, Person> factory = new CacheJdbcPojoStoreFactory<>(); factory.setDialect(new H2Dialect()); factory.setDataSourceFactory((Factory<DataSource>) () -> { return JdbcConnectionPool.create("jdbc:h2:tcp://localhost/mem:ExampleDb", "sa", ""); }); JdbcType jdbcType = new JdbcType(); jdbcType.setCacheName(CACHE_NAME); jdbcType.setDatabaseTable("PERSON"); jdbcType.setKeyType(Long.class); jdbcType.setValueType(Person.class); jdbcType.setKeyFields(new JdbcTypeField(Types.BIGINT, "id", Long.class, "id")); jdbcType.setValueFields( new JdbcTypeField(Types.BIGINT, "id", Long.class, "id"), new JdbcTypeField(Types.VARCHAR, "first_name", String.class, "firstName"), new JdbcTypeField(Types.VARCHAR, "last_name", String.class, "lastName"), new JdbcTypeField(Types.TIMESTAMP, "created_time", LocalDateTime.class, "createdTime") ); factory.setTypes(jdbcType); cacheCfg.setCacheStoreFactory(factory); cacheCfg.setIndexedTypes(Long.class, Person.class); return cacheCfg; } } {code} Person.java: {code:java} package org.apache.ignite.examples.model; import java.io.Serializable; import java.time.LocalDateTime; import java.util.concurrent.atomic.AtomicLong; import org.apache.ignite.cache.affinity.AffinityKey; import org.apache.ignite.cache.query.annotations.QuerySqlField; import org.apache.ignite.cache.query.annotations.QueryTextField; /** * Person class. */ public class Person implements Serializable { /** */ private static final AtomicLong ID_GEN = new AtomicLong(); /** Name of index by two fields (orgId, salary). */ public static final String ORG_SALARY_IDX = "ORG_SALARY_IDX"; /** Person ID (indexed). */ @QuerySqlField(index = true) public Long id; /** Organization ID (indexed). */ @QuerySqlField(index = true, orderedGroups = @QuerySqlField.Group(name = ORG_SALARY_IDX, order = 0)) public Long orgId; /** First name (not-indexed). */ @QuerySqlField public String firstName; /** Last name (not indexed). */ @QuerySqlField public String lastName; @QuerySqlField public LocalDateTime createdTime; /** Resume text (create LUCENE-based TEXT index for this field). */ @QueryTextField public String resume; /** Salary (indexed). */ @QuerySqlField(index = true, orderedGroups = @QuerySqlField.Group(name = ORG_SALARY_IDX, order = 1)) public double salary; /** Custom cache key to guarantee that person is always colocated with its organization. */ private transient AffinityKey<Long> key; /** * Default constructor. */ public Person() { // No-op. } /** * Constructs person record. * * @param org Organization. * @param firstName First name. * @param lastName Last name. * @param salary Salary. * @param resume Resume text. */ public Person(Organization org, String firstName, String lastName, double salary, String resume) { // Generate unique ID for this person. id = ID_GEN.incrementAndGet(); orgId = org.id(); this.firstName = firstName; this.lastName = lastName; this.createdTime = LocalDateTime.now(); this.salary = salary; this.resume = resume; } /** * Constructs person record. * * @param id Person ID. * @param orgId Organization ID. * @param firstName First name. * @param lastName Last name. * @param salary Salary. * @param resume Resume text. */ public Person(Long id, Long orgId, String firstName, String lastName, double salary, String resume) { this.id = id; this.orgId = orgId; this.firstName = firstName; this.lastName = lastName; this.createdTime = LocalDateTime.now(); this.salary = salary; this.resume = resume; } /** * Constructs person record. * * @param id Person ID. * @param firstName First name. * @param lastName Last name. */ public Person(Long id, String firstName, String lastName) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.createdTime = LocalDateTime.now(); } /** * Gets cache affinity key. Since in some examples person needs to be collocated with organization, we create * custom affinity key to guarantee this collocation. * * @return Custom affinity key to guarantee that person is always collocated with organization. */ public AffinityKey<Long> key() { if (key == null) key = new AffinityKey<>(id, orgId); return key; } /** * {@inheritDoc} */ @Override public String toString() { return "Person [id=" + id + ", orgId=" + orgId + ", lastName=" + lastName + ", firstName=" + firstName + ", createdTime=" + createdTime + ", salary=" + salary + ", resume=" + resume + ']'; } } {code} DbH2ServerStartup.java: {code:java} package org.apache.ignite.examples.util; import java.io.IOException; import java.io.StringReader; import java.sql.SQLException; import org.apache.ignite.IgniteException; import org.h2.jdbcx.JdbcConnectionPool; import org.h2.tools.RunScript; import org.h2.tools.Server; /** * Start H2 database TCP server in order to access sample in-memory database from other processes. */ public class DbH2ServerStartup { /** Create table script. */ private static final String CREATE_PERSON_TABLE = "create table if not exists PERSON(id bigint AUTO_INCREMENT PRIMARY KEY, first_name varchar(50), last_name varchar(50), created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP);"; /** Sample data script. */ private static final String POPULATE_PERSON_TABLE = "delete from PERSON;\n" + "insert into PERSON(id, first_name, last_name) values(1, 'Johannes', 'Kepler');\n" + "insert into PERSON(id, first_name, last_name) values(2, 'Galileo', 'Galilei');\n" + "insert into PERSON(id, first_name, last_name) values(3, 'Henry', 'More');\n" + "insert into PERSON(id, first_name, last_name) values(4, 'Polish', 'Brethren');\n" + "insert into PERSON(id, first_name, last_name) values(5, 'Robert', 'Boyle');\n" + "insert into PERSON(id, first_name, last_name) values(6, 'Wilhelm', 'Leibniz');"; /** * 初始化数据库 * * @throws SQLException if */ public static void populateDatabase() throws SQLException { // Try to connect to database TCP server. JdbcConnectionPool dataSrc = JdbcConnectionPool.create("jdbc:h2:tcp://localhost/mem:ExampleDb", "sa", ""); // Create Person table in database. RunScript.execute(dataSrc.getConnection(), new StringReader(CREATE_PERSON_TABLE)); // Populates Person table with sample data in database. RunScript.execute(dataSrc.getConnection(), new StringReader(POPULATE_PERSON_TABLE)); } /** * Start H2 database TCP server. * * @param args Command line arguments, none required. * @throws IgniteException If start H2 database TCP server failed. */ public static void main(String[] args) throws IgniteException { try { // Start H2 database TCP server in order to access sample in-memory database from other processes. Server.createTcpServer("-tcpDaemon").start(); Server.createWebServer("-webDaemon").start(); populateDatabase(); } catch (SQLException e) { throw new IgniteException("Failed to start database TCP server", e); } try { do { System.out.println("Type 'q' and press 'Enter' to stop H2 TCP server..."); } while ('q' != System.in.read()); } catch (IOException ignored) { // No-op. } } } {code} > When MySQL is used as the underlying storage, an exception is thrown "Can not > set java.time.LocalDateTime field > org.apache.ignite.examples.model.Person.createdTime to java.sql.Timestamp" > ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ > > Key: IGNITE-20024 > URL: https://issues.apache.org/jira/browse/IGNITE-20024 > Project: Ignite > Issue Type: Bug > Components: persistence > Reporter: bin.yin > Assignee: bin.yin > Priority: Major > > h3. Question: > {{First, I use ??IgniteCache#loadCache?? load from RDBMS. When I use > IgniteCache.get(key) to get the corresponding entity, ignite throws the > following error "Can not set java.time.LocalDateTime field > org.apache.ignite.examples.model.Person.createdTime to java.sql .Timestamp"}} > h3. Conditions and usage: > # This code run in 'ignite-examples' module; > # In ignite 2.14.0, I use H2 as the underlying storage; > # In {{{}CacheJdbcPojoStoreFactory{}}}, I configured the mapping between the > {{datetime type}} of the database and JDK8's {{{}LocalDateTime{}}}: > {{new JdbcTypeField(Types.TIMESTAMP, "created_time", LocalDateTime.class, > "createdTime")}} > h3. Problem analysis: > By default, {{CacheJdbcPojoStore}} uses > {{org.apache.ignite.cache.store.jdbc.JdbcTypesTransformer#getColumnValue}} to > parse jdbc's ResultSet. > For the {{LocalDateTime}} type of JDK8, {{java.sql.ResultSet#getObject(int)}} > is used to obtain the value of the specified column (here it is read as > {{{}java.sql.Timestamp{}}}). When the object is finally constructed, the type > is inconsistent Causes {{sun.reflect.FieldAccessor#set}} assignment to fail. > > *Java Code:* > CacheJdbcPojoStore.java: > > {code:java} > package org.apache.ignite.examples.datagrid.store.auto; > import org.apache.ignite.Ignite; > import org.apache.ignite.IgniteCache; > import org.apache.ignite.Ignition; > import org.apache.ignite.cache.CacheAtomicityMode; > import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory; > import org.apache.ignite.cache.store.jdbc.JdbcType; > import org.apache.ignite.cache.store.jdbc.JdbcTypeField; > import org.apache.ignite.cache.store.jdbc.dialect.H2Dialect; > import org.apache.ignite.configuration.CacheConfiguration; > import org.apache.ignite.examples.model.Person; > import org.apache.ignite.examples.util.DbH2ServerStartup; > import org.h2.jdbcx.JdbcConnectionPool; > import javax.cache.configuration.Factory; > import javax.sql.DataSource; > import java.sql.Types; > import java.time.LocalDateTime; > /** > * To start the example, you should: > * <ul> > * <li>Start H2 database TCP server using {@link DbH2ServerStartup}.</li> > * <li>Start example using {@link CacheAutoStoreExample}.</li> > * </ul> > * <p> > */ > public class CacheJdbcPojoStore { > private static final String CACHE_NAME = > CacheJdbcPojoStore.class.getSimpleName(); > public static void main(String[] args) throws Exception { > DbH2ServerStartup.populateDatabase(); > try (Ignite ignite = Ignition.start("example-ignite.xml")) { > System.out.println(); > System.out.println(">>> Cache store example started."); > try (IgniteCache<Long, Person> cache = > ignite.getOrCreateCache(cacheConfiguration())) { > cache.loadCache(null, Long.class.getName(), "SELECT * FROM > PERSON WHERE ID = 3"); > System.out.println(cache.get(3L)); > } > finally { > ignite.destroyCache(CACHE_NAME); > } > } > } > private static CacheConfiguration<Long, Person> cacheConfiguration() { > CacheConfiguration<Long, Person> cacheCfg = new > CacheConfiguration<>(CACHE_NAME); > cacheCfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL); > // Configure JDBC store. > CacheJdbcPojoStoreFactory<Long, Person> factory = new > CacheJdbcPojoStoreFactory<>(); > factory.setDialect(new H2Dialect()); > factory.setDataSourceFactory((Factory<DataSource>) () -> { > return > JdbcConnectionPool.create("jdbc:h2:tcp://localhost/mem:ExampleDb", "sa", ""); > }); > JdbcType jdbcType = new JdbcType(); > jdbcType.setCacheName(CACHE_NAME); > jdbcType.setDatabaseTable("PERSON"); > jdbcType.setKeyType(Long.class); > jdbcType.setValueType(Person.class); > jdbcType.setKeyFields(new JdbcTypeField(Types.BIGINT, "id", > Long.class, "id")); > jdbcType.setValueFields( > new JdbcTypeField(Types.BIGINT, "id", Long.class, "id"), > new JdbcTypeField(Types.VARCHAR, "first_name", String.class, > "firstName"), > new JdbcTypeField(Types.VARCHAR, "last_name", String.class, > "lastName"), > new JdbcTypeField(Types.TIMESTAMP, "created_time", > LocalDateTime.class, "createdTime") > ); > factory.setTypes(jdbcType); > cacheCfg.setCacheStoreFactory(factory); > cacheCfg.setIndexedTypes(Long.class, Person.class); > return cacheCfg; > } > } > {code} > Person.java: > > {code:java} > package org.apache.ignite.examples.model; > import java.io.Serializable; > import java.time.LocalDateTime; > import java.util.concurrent.atomic.AtomicLong; > import org.apache.ignite.cache.affinity.AffinityKey; > import org.apache.ignite.cache.query.annotations.QuerySqlField; > import org.apache.ignite.cache.query.annotations.QueryTextField; > /** > * Person class. > */ > public class Person implements Serializable { > /** */ > private static final AtomicLong ID_GEN = new AtomicLong(); > /** Name of index by two fields (orgId, salary). */ > public static final String ORG_SALARY_IDX = "ORG_SALARY_IDX"; > /** Person ID (indexed). */ > @QuerySqlField(index = true) > public Long id; > /** Organization ID (indexed). */ > @QuerySqlField(index = true, orderedGroups = @QuerySqlField.Group(name = > ORG_SALARY_IDX, order = 0)) > public Long orgId; > /** First name (not-indexed). */ > @QuerySqlField > public String firstName; > /** Last name (not indexed). */ > @QuerySqlField > public String lastName; > @QuerySqlField > public LocalDateTime createdTime; > /** Resume text (create LUCENE-based TEXT index for this field). */ > @QueryTextField > public String resume; > /** Salary (indexed). */ > @QuerySqlField(index = true, orderedGroups = @QuerySqlField.Group(name = > ORG_SALARY_IDX, order = 1)) > public double salary; > /** Custom cache key to guarantee that person is always colocated with > its organization. */ > private transient AffinityKey<Long> key; > /** > * Default constructor. > */ > public Person() { > // No-op. > } > /** > * Constructs person record. > * > * @param org Organization. > * @param firstName First name. > * @param lastName Last name. > * @param salary Salary. > * @param resume Resume text. > */ > public Person(Organization org, String firstName, String lastName, double > salary, String resume) { > // Generate unique ID for this person. > id = ID_GEN.incrementAndGet(); > orgId = org.id(); > this.firstName = firstName; > this.lastName = lastName; > this.createdTime = LocalDateTime.now(); > this.salary = salary; > this.resume = resume; > } > /** > * Constructs person record. > * > * @param id Person ID. > * @param orgId Organization ID. > * @param firstName First name. > * @param lastName Last name. > * @param salary Salary. > * @param resume Resume text. > */ > public Person(Long id, Long orgId, String firstName, String lastName, > double salary, String resume) { > this.id = id; > this.orgId = orgId; > this.firstName = firstName; > this.lastName = lastName; > this.createdTime = LocalDateTime.now(); > this.salary = salary; > this.resume = resume; > } > /** > * Constructs person record. > * > * @param id Person ID. > * @param firstName First name. > * @param lastName Last name. > */ > public Person(Long id, String firstName, String lastName) { > this.id = id; > this.firstName = firstName; > this.lastName = lastName; > this.createdTime = LocalDateTime.now(); > } > /** > * Gets cache affinity key. Since in some examples person needs to be > collocated with organization, we create > * custom affinity key to guarantee this collocation. > * > * @return Custom affinity key to guarantee that person is always > collocated with organization. > */ > public AffinityKey<Long> key() { > if (key == null) > key = new AffinityKey<>(id, orgId); > return key; > } > /** > * {@inheritDoc} > */ > @Override public String toString() { > return "Person [id=" + id + > ", orgId=" + orgId + > ", lastName=" + lastName + > ", firstName=" + firstName + > ", createdTime=" + createdTime + > ", salary=" + salary + > ", resume=" + resume + ']'; > } > } {code} > DbH2ServerStartup.java: > > > {code:java} > package org.apache.ignite.examples.util; > import java.io.IOException; > import java.io.StringReader; > import java.sql.SQLException; > import org.apache.ignite.IgniteException; > import org.h2.jdbcx.JdbcConnectionPool; > import org.h2.tools.RunScript; > import org.h2.tools.Server; > /** > * Start H2 database TCP server in order to access sample in-memory database > from other processes. > */ > public class DbH2ServerStartup { > /** Create table script. */ > private static final String CREATE_PERSON_TABLE = > "create table if not exists PERSON(id bigint AUTO_INCREMENT PRIMARY > KEY, first_name varchar(50), last_name varchar(50), created_time TIMESTAMP > DEFAULT CURRENT_TIMESTAMP);"; > /** Sample data script. */ > private static final String POPULATE_PERSON_TABLE = > "delete from PERSON;\n" + > "insert into PERSON(id, first_name, last_name) values(1, 'Johannes', > 'Kepler');\n" + > "insert into PERSON(id, first_name, last_name) values(2, 'Galileo', > 'Galilei');\n" + > "insert into PERSON(id, first_name, last_name) values(3, 'Henry', > 'More');\n" + > "insert into PERSON(id, first_name, last_name) values(4, 'Polish', > 'Brethren');\n" + > "insert into PERSON(id, first_name, last_name) values(5, 'Robert', > 'Boyle');\n" + > "insert into PERSON(id, first_name, last_name) values(6, 'Wilhelm', > 'Leibniz');"; > /** > * 初始化数据库 > * > * @throws SQLException if > */ > public static void populateDatabase() throws SQLException { > // Try to connect to database TCP server. > JdbcConnectionPool dataSrc = > JdbcConnectionPool.create("jdbc:h2:tcp://localhost/mem:ExampleDb", "sa", ""); > // Create Person table in database. > RunScript.execute(dataSrc.getConnection(), new > StringReader(CREATE_PERSON_TABLE)); > // Populates Person table with sample data in database. > RunScript.execute(dataSrc.getConnection(), new > StringReader(POPULATE_PERSON_TABLE)); > } > /** > * Start H2 database TCP server. > * > * @param args Command line arguments, none required. > * @throws IgniteException If start H2 database TCP server failed. > */ > public static void main(String[] args) throws IgniteException { > try { > // Start H2 database TCP server in order to access sample > in-memory database from other processes. > Server.createTcpServer("-tcpDaemon").start(); > Server.createWebServer("-webDaemon").start(); > populateDatabase(); > } > catch (SQLException e) { > throw new IgniteException("Failed to start database TCP server", > e); > } > try { > do { > System.out.println("Type 'q' and press 'Enter' to stop H2 TCP > server..."); > } > while ('q' != System.in.read()); > } > catch (IOException ignored) { > // No-op. > } > } > } > {code} > > > -- This message was sent by Atlassian Jira (v8.20.10#820010)