[#912] Add <R extends Record> R newRecord(Table<R>, Object) as the inverse of various into(Class<?>) methods
[#932] Let the bound of R in TableRecord extend TableRecord<R>, in UpdatableRecord to extend UpdatableRecord<R> [#934] Don't consider static members in reflection utilities when used with Record.into(Class<?>) and similar methods [#935] Don't consider final member fields in reflection utilities when used with Record.into(Class<?>) and similar methods
This commit is contained in:
parent
37802d86d8
commit
16efd8d2fb
@ -324,10 +324,15 @@ public class FactoryProxy implements FactoryOperations, MethodInterceptor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <R extends Record> R newRecord(Table<R> table) {
|
||||
public final <R extends TableRecord<R>> R newRecord(Table<R> table) {
|
||||
return getDelegate().newRecord(table);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <R extends TableRecord<R>> R newRecord(Table<R> table, Object source) {
|
||||
return getDelegate().newRecord(table, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Result<Record> fetch(ResultSet rs) {
|
||||
return getDelegate().fetch(rs);
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.jooq.test;
|
||||
package org.jooq.test.$;
|
||||
|
||||
import org.jooq.impl.CustomRecord;
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.jooq.test;
|
||||
package org.jooq.test.$;
|
||||
|
||||
import org.jooq.TableField;
|
||||
import org.jooq.impl.CustomTable;
|
||||
@ -33,7 +33,7 @@
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.jooq.test;
|
||||
package org.jooq.test.$;
|
||||
|
||||
import javax.persistence.Column;
|
||||
|
||||
@ -47,6 +47,9 @@ public class BookWithAnnotations {
|
||||
@Column(name = "ID")
|
||||
public Integer id;
|
||||
|
||||
@Column(name = "ID")
|
||||
public Long id4;
|
||||
|
||||
@Column(name = "ID")
|
||||
public int id2;
|
||||
|
||||
@ -62,6 +65,7 @@ public class BookWithAnnotations {
|
||||
// Members without annotations
|
||||
// ---------------------------
|
||||
public int id3;
|
||||
public long id5;
|
||||
public String firstName2;
|
||||
public String lastName;
|
||||
public String lastName2;
|
||||
@ -69,8 +73,13 @@ public class BookWithAnnotations {
|
||||
// Methods with annotations
|
||||
// ------------------------
|
||||
@Column(name = "ID")
|
||||
public void setId(int id) {
|
||||
id3 = id;
|
||||
public void setId(long id) {
|
||||
id3 = (int) id;
|
||||
}
|
||||
|
||||
@Column(name = "ID")
|
||||
public void setId(Long id) {
|
||||
id5 = (int) (long) id;
|
||||
}
|
||||
|
||||
@Column(name = "FIRST_NAME")
|
||||
@ -33,7 +33,7 @@
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.jooq.test;
|
||||
package org.jooq.test.$;
|
||||
|
||||
|
||||
/**
|
||||
@ -53,8 +53,8 @@ public class BookWithoutAnnotations {
|
||||
public java.util.Date DATE_OF_BIRTH;
|
||||
public java.sql.Date dateOfBirth;
|
||||
|
||||
public void setId(int id) {
|
||||
id2 = id;
|
||||
public void setId(long id) {
|
||||
id2 = (int) id;
|
||||
}
|
||||
|
||||
public void setFirstName(String f) {
|
||||
@ -33,7 +33,7 @@
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.jooq.test;
|
||||
package org.jooq.test.$;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
48
jOOQ-test/src/org/jooq/test/$/FinalWithAnnotations.java
Normal file
48
jOOQ-test/src/org/jooq/test/$/FinalWithAnnotations.java
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2011, Lukas Eder, lukas.eder@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed to you under the Apache License, Version 2.0
|
||||
* (the "License"); You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* . Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* . Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* . Neither the name "jOOQ" nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.jooq.test.$;
|
||||
|
||||
import javax.persistence.Column;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public class FinalWithAnnotations {
|
||||
|
||||
@Column(name = "ID")
|
||||
public final int ID = 13;
|
||||
|
||||
}
|
||||
46
jOOQ-test/src/org/jooq/test/$/FinalWithoutAnnotations.java
Normal file
46
jOOQ-test/src/org/jooq/test/$/FinalWithoutAnnotations.java
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2011, Lukas Eder, lukas.eder@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed to you under the Apache License, Version 2.0
|
||||
* (the "License"); You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* . Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* . Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* . Neither the name "jOOQ" nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.jooq.test.$;
|
||||
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public class FinalWithoutAnnotations {
|
||||
|
||||
public final int ID = 13;
|
||||
|
||||
}
|
||||
57
jOOQ-test/src/org/jooq/test/$/StaticWithAnnotations.java
Normal file
57
jOOQ-test/src/org/jooq/test/$/StaticWithAnnotations.java
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2011, Lukas Eder, lukas.eder@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed to you under the Apache License, Version 2.0
|
||||
* (the "License"); You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* . Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* . Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* . Neither the name "jOOQ" nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.jooq.test.$;
|
||||
|
||||
import javax.persistence.Column;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public class StaticWithAnnotations {
|
||||
|
||||
@Column(name = "ID")
|
||||
public static int ID = 13;
|
||||
|
||||
@Column(name = "ID")
|
||||
public static int getID() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Column(name = "ID")
|
||||
public static void setID(int id) {
|
||||
ID = id;
|
||||
}
|
||||
}
|
||||
52
jOOQ-test/src/org/jooq/test/$/StaticWithoutAnnotations.java
Normal file
52
jOOQ-test/src/org/jooq/test/$/StaticWithoutAnnotations.java
Normal file
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2011, Lukas Eder, lukas.eder@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed to you under the Apache License, Version 2.0
|
||||
* (the "License"); You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* . Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* . Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* . Neither the name "jOOQ" nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.jooq.test.$;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public class StaticWithoutAnnotations {
|
||||
|
||||
public static int ID = 13;
|
||||
|
||||
public static int getID() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public static void setID(int id) {
|
||||
ID = id;
|
||||
}
|
||||
}
|
||||
@ -132,12 +132,21 @@ import org.jooq.UpdatableTable;
|
||||
import org.jooq.UpdateQuery;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.exception.DetachedException;
|
||||
import org.jooq.exception.FetchIntoException;
|
||||
import org.jooq.exception.InvalidResultException;
|
||||
import org.jooq.exception.MappingException;
|
||||
import org.jooq.impl.CustomCondition;
|
||||
import org.jooq.impl.CustomField;
|
||||
import org.jooq.impl.Factory;
|
||||
import org.jooq.impl.SQLDataType;
|
||||
import org.jooq.test.$.BookRecord;
|
||||
import org.jooq.test.$.BookTable;
|
||||
import org.jooq.test.$.BookWithAnnotations;
|
||||
import org.jooq.test.$.BookWithoutAnnotations;
|
||||
import org.jooq.test.$.DatesWithAnnotations;
|
||||
import org.jooq.test.$.FinalWithAnnotations;
|
||||
import org.jooq.test.$.FinalWithoutAnnotations;
|
||||
import org.jooq.test.$.StaticWithAnnotations;
|
||||
import org.jooq.test.$.StaticWithoutAnnotations;
|
||||
import org.jooq.tools.JooqLogger;
|
||||
import org.jooq.tools.StopWatch;
|
||||
import org.jooq.tools.StringUtils;
|
||||
@ -2716,6 +2725,16 @@ public abstract class jOOQAbstractTest<
|
||||
assertEquals(3, result.get(2).id3);
|
||||
assertEquals(4, result.get(3).id3);
|
||||
|
||||
assertEquals(Long.valueOf(1), result.get(0).id4);
|
||||
assertEquals(Long.valueOf(2), result.get(1).id4);
|
||||
assertEquals(Long.valueOf(3), result.get(2).id4);
|
||||
assertEquals(Long.valueOf(4), result.get(3).id4);
|
||||
|
||||
assertEquals(1L, result.get(0).id5);
|
||||
assertEquals(2L, result.get(1).id5);
|
||||
assertEquals(3L, result.get(2).id5);
|
||||
assertEquals(4L, result.get(3).id5);
|
||||
|
||||
assertEquals("1984", result.get(0).title);
|
||||
assertEquals("Animal Farm", result.get(1).title);
|
||||
assertEquals("O Alquimista", result.get(2).title);
|
||||
@ -2747,7 +2766,7 @@ public abstract class jOOQAbstractTest<
|
||||
.fetchInto(AbstractList.class);
|
||||
fail();
|
||||
}
|
||||
catch (FetchIntoException expected) {}
|
||||
catch (MappingException expected) {}
|
||||
|
||||
try {
|
||||
// Cannot a class without default constructor
|
||||
@ -2755,7 +2774,7 @@ public abstract class jOOQAbstractTest<
|
||||
.fetchInto(Math.class);
|
||||
fail();
|
||||
}
|
||||
catch (FetchIntoException expected) {}
|
||||
catch (MappingException expected) {}
|
||||
|
||||
// [#930] Calendar/Date conversion checks
|
||||
// --------------------------------------
|
||||
@ -2891,8 +2910,113 @@ public abstract class jOOQAbstractTest<
|
||||
assertEquals("Coelho", result.get(3).LAST_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecordFromWithAnnotations() throws Exception {
|
||||
BookWithAnnotations b = new BookWithAnnotations();
|
||||
b.firstName = "Edgar Allen";
|
||||
b.lastName2 = "Poe";
|
||||
b.dateOfBirth = new Date(1);
|
||||
b.id = 17;
|
||||
b.title = "The Raven";
|
||||
|
||||
// This data shouldn't be considered
|
||||
b.id2 = 18;
|
||||
b.lastName = "Poet";
|
||||
|
||||
B book = create().newRecord(TBook(), b);
|
||||
A author = create().newRecord(TAuthor(), b);
|
||||
|
||||
assertEquals(b.id, author.getValue(TAuthor_ID()));
|
||||
assertEquals(b.firstName, author.getValue(TAuthor_FIRST_NAME()));
|
||||
assertEquals(b.lastName2, author.getValue(TAuthor_LAST_NAME()));
|
||||
assertEquals(b.dateOfBirth, author.getValue(TAuthor_DATE_OF_BIRTH()));
|
||||
assertNull(author.getValue(TAuthor_YEAR_OF_BIRTH()));
|
||||
|
||||
assertEquals(b.id, book.getValue(TBook_ID()));
|
||||
assertEquals(b.title, book.getValue(TBook_TITLE()));
|
||||
assertNull(book.getValue(TBook_AUTHOR_ID()));
|
||||
assertNull(book.getValue(TBook_CONTENT_PDF()));
|
||||
assertNull(book.getValue(TBook_CONTENT_TEXT()));
|
||||
assertNull(book.getValue(TBook_LANGUAGE_ID()));
|
||||
assertNull(book.getValue(TBook_PUBLISHED_IN()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecordFromWithoutAnnotations() throws Exception {
|
||||
BookWithoutAnnotations b = new BookWithoutAnnotations();
|
||||
b.firstName = "Edgar Allen";
|
||||
b.lastName = "Poe";
|
||||
b.DATE_OF_BIRTH = new Date(1);
|
||||
b.id = 17;
|
||||
b.title = "The Raven";
|
||||
|
||||
// This data shouldn't be considered
|
||||
b.id2 = 18;
|
||||
b.ID = 19;
|
||||
b.LAST_NAME = "Poet";
|
||||
b.dateOfBirth = new Date(2);
|
||||
|
||||
B book = create().newRecord(TBook(), b);
|
||||
A author = create().newRecord(TAuthor(), b);
|
||||
|
||||
assertEquals(b.id, author.getValue(TAuthor_ID()));
|
||||
assertEquals(b.firstName, author.getValue(TAuthor_FIRST_NAME()));
|
||||
assertEquals(b.lastName, author.getValue(TAuthor_LAST_NAME()));
|
||||
assertEquals(b.DATE_OF_BIRTH, author.getValue(TAuthor_DATE_OF_BIRTH()));
|
||||
assertNull(author.getValue(TAuthor_YEAR_OF_BIRTH()));
|
||||
|
||||
assertEquals(b.id, book.getValue(TBook_ID()));
|
||||
assertEquals(b.title, book.getValue(TBook_TITLE()));
|
||||
assertNull(book.getValue(TBook_AUTHOR_ID()));
|
||||
assertNull(book.getValue(TBook_CONTENT_PDF()));
|
||||
assertNull(book.getValue(TBook_CONTENT_TEXT()));
|
||||
assertNull(book.getValue(TBook_LANGUAGE_ID()));
|
||||
assertNull(book.getValue(TBook_PUBLISHED_IN()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReflectionWithAnnotations() throws Exception {
|
||||
|
||||
// [#934] Static members are not to be considered
|
||||
assertEquals(create().newRecord(TBook()), create().newRecord(TBook(), new StaticWithAnnotations()));
|
||||
create().newRecord(TBook()).into(StaticWithAnnotations.class);
|
||||
assertEquals(13, StaticWithAnnotations.ID);
|
||||
|
||||
// [#935] Final member fields are considered when reading
|
||||
B book = create().newRecord(TBook());
|
||||
book.setValue(TBook_ID(), new FinalWithAnnotations().ID);
|
||||
assertEquals(book, create().newRecord(TBook(), new FinalWithAnnotations()));
|
||||
|
||||
// [#935] ... but not when writing
|
||||
FinalWithAnnotations f = create().newRecord(TBook()).into(FinalWithAnnotations.class);
|
||||
assertEquals(f.ID, new FinalWithAnnotations().ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReflectionWithoutAnnotations() throws Exception {
|
||||
|
||||
// Arbitrary sources should have no effect
|
||||
assertEquals(create().newRecord(TBook()), create().newRecord(TBook(), (Object) null));
|
||||
assertEquals(create().newRecord(TBook()), create().newRecord(TBook(), new Object()));
|
||||
|
||||
// [#934] Static members are not to be considered
|
||||
assertEquals(create().newRecord(TBook()), create().newRecord(TBook(), new StaticWithoutAnnotations()));
|
||||
create().newRecord(TBook()).into(StaticWithoutAnnotations.class);
|
||||
assertEquals(13, StaticWithoutAnnotations.ID);
|
||||
|
||||
// [#935] Final member fields are considered when reading
|
||||
B book = create().newRecord(TBook());
|
||||
book.setValue(TBook_ID(), new FinalWithoutAnnotations().ID);
|
||||
assertEquals(book, create().newRecord(TBook(), new FinalWithoutAnnotations()));
|
||||
|
||||
// [#935] ... but not when writing
|
||||
FinalWithoutAnnotations f = create().newRecord(TBook()).into(FinalWithoutAnnotations.class);
|
||||
assertEquals(f.ID, new FinalWithoutAnnotations().ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFetchIntoCustomTable() throws Exception {
|
||||
|
||||
// TODO [#791] Fix test data and have all upper case columns everywhere
|
||||
switch (getDialect()) {
|
||||
case ASE:
|
||||
|
||||
@ -41,7 +41,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.exception.FetchIntoException;
|
||||
import org.jooq.exception.MappingException;
|
||||
|
||||
/**
|
||||
* Cursors allow for lazy, sequential access to an underlying JDBC
|
||||
@ -135,10 +135,10 @@ public interface Cursor<R extends Record> extends FieldProvider, Iterable<R> {
|
||||
* @see Record#into(Class)
|
||||
* @see Result#into(Class)
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
* @throws FetchIntoException wrapping any reflection exception that might
|
||||
* @throws MappingException wrapping any reflection exception that might
|
||||
* have occurred while mapping records
|
||||
*/
|
||||
<E> E fetchOneInto(Class<? extends E> type) throws DataAccessException, FetchIntoException;
|
||||
<E> E fetchOneInto(Class<? extends E> type) throws DataAccessException, MappingException;
|
||||
|
||||
/**
|
||||
* Map resulting records onto a custom type.
|
||||
@ -151,10 +151,10 @@ public interface Cursor<R extends Record> extends FieldProvider, Iterable<R> {
|
||||
* @see Record#into(Class)
|
||||
* @see Result#into(Class)
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
* @throws FetchIntoException wrapping any reflection exception that might
|
||||
* @throws MappingException wrapping any reflection exception that might
|
||||
* have occurred while mapping records
|
||||
*/
|
||||
<E> List<E> fetchInto(Class<? extends E> type) throws DataAccessException, FetchIntoException;
|
||||
<E> List<E> fetchInto(Class<? extends E> type) throws DataAccessException, MappingException;
|
||||
|
||||
/**
|
||||
* Map the next resulting record onto a custom record.
|
||||
@ -167,10 +167,10 @@ public interface Cursor<R extends Record> extends FieldProvider, Iterable<R> {
|
||||
* @see Record#into(Class)
|
||||
* @see Result#into(Class)
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
* @throws FetchIntoException wrapping any reflection exception that might
|
||||
* @throws MappingException wrapping any reflection exception that might
|
||||
* have occurred while mapping records
|
||||
*/
|
||||
<Z extends TableRecord<Z>> Z fetchOneInto(Table<Z> table) throws DataAccessException, FetchIntoException;
|
||||
<Z extends TableRecord<Z>> Z fetchOneInto(Table<Z> table) throws DataAccessException, MappingException;
|
||||
|
||||
/**
|
||||
* Map resulting records onto a custom record.
|
||||
@ -183,10 +183,10 @@ public interface Cursor<R extends Record> extends FieldProvider, Iterable<R> {
|
||||
* @see Record#into(Class)
|
||||
* @see Result#into(Class)
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
* @throws FetchIntoException wrapping any reflection exception that might
|
||||
* @throws MappingException wrapping any reflection exception that might
|
||||
* have occurred while mapping records
|
||||
*/
|
||||
<Z extends TableRecord<Z>> List<Z> fetchInto(Table<Z> table) throws DataAccessException, FetchIntoException;
|
||||
<Z extends TableRecord<Z>> List<Z> fetchInto(Table<Z> table) throws DataAccessException, MappingException;
|
||||
|
||||
/**
|
||||
* Explicitly close the underlying {@link PreparedStatement} and
|
||||
|
||||
@ -662,7 +662,22 @@ public interface FactoryOperations extends Configuration {
|
||||
* @param table The table holding records of type <R>
|
||||
* @return The new record
|
||||
*/
|
||||
<R extends Record> R newRecord(Table<R> table);
|
||||
<R extends TableRecord<R>> R newRecord(Table<R> table);
|
||||
|
||||
/**
|
||||
* Create a new pre-filled {@link Record} that can be inserted into the
|
||||
* corresponding table.
|
||||
* <p>
|
||||
* This performs roughly the inverse operation of {@link Record#into(Class)}
|
||||
*
|
||||
* @param <R> The generic record type
|
||||
* @param table The table holding records of type <R>
|
||||
* @param source The source to be used to fill the new record
|
||||
* @return The new record
|
||||
* @see Record#from(Object)
|
||||
* @see Record#into(Class)
|
||||
*/
|
||||
<R extends TableRecord<R>> R newRecord(Table<R> table, Object source);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Fast querying
|
||||
|
||||
@ -45,7 +45,7 @@ import java.sql.Timestamp;
|
||||
|
||||
import javax.persistence.Column;
|
||||
|
||||
import org.jooq.exception.FetchIntoException;
|
||||
import org.jooq.exception.MappingException;
|
||||
|
||||
/**
|
||||
* A wrapper for database result records returned by
|
||||
@ -863,30 +863,35 @@ public interface Record extends FieldProvider, Store<Object> {
|
||||
* <h3>If any JPA {@link Column} annotations are found on the provided
|
||||
* <code>type</code>, only those are used:</h3>
|
||||
* <ul>
|
||||
* <li>If <code>type</code> contains public single-argument methods
|
||||
* <li>If <code>type</code> contains public single-argument instance methods
|
||||
* annotated with <code>Column</code>, those methods are invoked</li>
|
||||
* <li>If <code>type</code> contains public no-argument methods starting
|
||||
* with <code>getXXX</code> or <code>isXXX</code>, annotated with
|
||||
* <code>Column</code>, then matching <code>setXXX()</code> methods are
|
||||
* invoked</li>
|
||||
* <li>If <code>type</code> contains public members annotated with
|
||||
* <code>Column</code>, those members are set</li>
|
||||
* <li>If <code>type</code> contains public no-argument instance methods
|
||||
* starting with <code>getXXX</code> or <code>isXXX</code>, annotated with
|
||||
* <code>Column</code>, then matching public <code>setXXX()</code> instance
|
||||
* methods are invoked</li>
|
||||
* <li>If <code>type</code> contains public instance member fields annotated
|
||||
* with <code>Column</code>, those members are set</li>
|
||||
* </ul>
|
||||
* Additional rules:
|
||||
* <ul>
|
||||
* <li>The same annotation can be re-used for several methods/members</li>
|
||||
* <li>{@link Column#name()} must match {@link Field#getName()}. All other
|
||||
* annotation attributes are ignored</li>
|
||||
* <li>Static methods / member fields are ignored</li>
|
||||
* <li>Final member fields are ignored</li>
|
||||
* </ul>
|
||||
* <h3>If there are no JPA <code>Column</code> annotations, or jOOQ can't
|
||||
* find the <code>javax.persistence</code> API on the classpath, jOOQ will
|
||||
* map <code>Record</code> values by naming convention:</h3> If a field's
|
||||
* value for {@link Field#getName()} is <code>MY_field</code>
|
||||
* (case-sensitive!), then this field's value will be set on all of these:
|
||||
* map <code>Record</code> values by naming convention:</h3> If
|
||||
* {@link Field#getName()} is <code>MY_field</code> (case-sensitive!), then
|
||||
* this field's value will be set on all of these:
|
||||
* <ul>
|
||||
* <li>Public member <code>MY_field</code></li>
|
||||
* <li>Public member <code>myField</code></li>
|
||||
* <li>Public method <code>MY_field(...)</code></li>
|
||||
* <li>Public method <code>myField(...)</code></li>
|
||||
* <li>Public method <code>setMY_field(...)</code></li>
|
||||
* <li>Public method <code>setMyField(...)</code></li>
|
||||
* <li>Public single-argument instance method <code>MY_field(...)</code></li>
|
||||
* <li>Public single-argument instance method <code>myField(...)</code></li>
|
||||
* <li>Public single-argument instance method <code>setMY_field(...)</code></li>
|
||||
* <li>Public single-argument instance method <code>setMyField(...)</code></li>
|
||||
* <li>Public non-final instance member field <code>MY_field</code></li>
|
||||
* <li>Public non-final instance member field <code>myField</code></li>
|
||||
* </ul>
|
||||
* <h3>Other restrictions</h3>
|
||||
* <ul>
|
||||
@ -898,11 +903,12 @@ public interface Record extends FieldProvider, Store<Object> {
|
||||
* numbers, or <code>false</code> for booleans). Hence, there is no way of
|
||||
* distinguishing <code>null</code> and <code>0</code> in that case.</li>
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* @param <E> The generic entity type.
|
||||
* @param type The entity type.
|
||||
* @see #from(Object)
|
||||
*/
|
||||
<E> E into(Class<? extends E> type) throws FetchIntoException;
|
||||
<E> E into(Class<? extends E> type) throws MappingException;
|
||||
|
||||
/**
|
||||
* Map resulting records onto a custom record type. The mapping algorithm is
|
||||
@ -916,9 +922,57 @@ public interface Record extends FieldProvider, Store<Object> {
|
||||
* default constructors are made accessible using
|
||||
* {@link Constructor#setAccessible(boolean)}</li>
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* @param <R> The generic table record type.
|
||||
* @param table The table type.
|
||||
*/
|
||||
<R extends TableRecord<R>> R into(Table<R> table);
|
||||
|
||||
/**
|
||||
* Load data into this record from a source. The mapping algorithm is this:
|
||||
* <h3>If any JPA {@link Column} annotations are found on the {@link Class}
|
||||
* of the provided <code>source</code>, only those are used. Matching
|
||||
* candidates are:</h3>
|
||||
* <ul>
|
||||
* <li>Public no-argument instance methods annotated with
|
||||
* <code>Column</code></li>
|
||||
* <li>Public no-argument instance methods starting with <code>getXXX</code>
|
||||
* or <code>isXXX</code>, if there exists a matching public single-argument
|
||||
* <code>setXXX()</code> instance method that is annotated with
|
||||
* <code>Column</code></li>
|
||||
* <li>Public instance member fields annotated with <code>Column</code></li>
|
||||
* </ul>
|
||||
* Additional matching rules:
|
||||
* <ul>
|
||||
* <li>{@link Column#name()} must match {@link Field#getName()}. All other
|
||||
* annotation attributes are ignored</li>
|
||||
* <li>Only the first match per field is used</li>
|
||||
* <li>Matching methods have a higher priority than matching member fields</li>
|
||||
* <li>Explicitly matching methods have a higher priority than implicitly
|
||||
* matching methods (implicitly matching getter = setter is annotated)</li>
|
||||
* <li>Static methods / member fields are ignored</li>
|
||||
* </ul>
|
||||
* <h3>If there are no JPA <code>Column</code> annotations, or jOOQ can't
|
||||
* find the <code>javax.persistence</code> API on the classpath, jOOQ will
|
||||
* map members by naming convention:</h3> If {@link Field#getName()} is
|
||||
* <code>MY_field</code> (case-sensitive!), then this field's value will be
|
||||
* fetched from the first of these:
|
||||
* <ul>
|
||||
* <li>Public no-argument instance method <code>MY_field()</code></li>
|
||||
* <li>Public no-argument instance method <code>myField()</code></li>
|
||||
* <li>Public no-argument instance method <code>getMY_field()</code></li>
|
||||
* <li>Public no-argument instance method <code>getMyField()</code></li>
|
||||
* <li>Public instance member field <code>MY_field</code></li>
|
||||
* <li>Public instance member field <code>myField</code></li>
|
||||
* </ul>
|
||||
* <h3>Other restrictions</h3>
|
||||
* <ul>
|
||||
* <li>primitive types are supported.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param source The source object to copy data from
|
||||
* @see #into(Class)
|
||||
*/
|
||||
void from(Object source) throws MappingException;
|
||||
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.exception.FetchIntoException;
|
||||
import org.jooq.exception.MappingException;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
@ -1727,11 +1727,11 @@ public interface Result<R extends Record> extends FieldProvider, List<R>, Attach
|
||||
*
|
||||
* @param <E> The generic entity type.
|
||||
* @param type The entity type.
|
||||
* @throws FetchIntoException wrapping any reflection exception that might
|
||||
* @throws MappingException wrapping any reflection exception that might
|
||||
* have occurred while mapping records
|
||||
* @see Record#into(Class)
|
||||
*/
|
||||
<E> List<E> into(Class<? extends E> type) throws FetchIntoException;
|
||||
<E> List<E> into(Class<? extends E> type) throws MappingException;
|
||||
|
||||
/**
|
||||
* Map resulting records onto a custom record.
|
||||
@ -1742,11 +1742,11 @@ public interface Result<R extends Record> extends FieldProvider, List<R>, Attach
|
||||
*
|
||||
* @param <Z> The generic table record type.
|
||||
* @param table The table type.
|
||||
* @throws FetchIntoException wrapping any reflection exception that might
|
||||
* @throws MappingException wrapping any reflection exception that might
|
||||
* have occurred while mapping records
|
||||
* @see Record#into(Table)
|
||||
*/
|
||||
<Z extends TableRecord<Z>> Result<Z> into(Table<Z> table) throws FetchIntoException;
|
||||
<Z extends TableRecord<Z>> Result<Z> into(Table<Z> table) throws MappingException;
|
||||
|
||||
/**
|
||||
* Map results into a custom handler callback
|
||||
|
||||
@ -43,7 +43,7 @@ import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.exception.FetchIntoException;
|
||||
import org.jooq.exception.MappingException;
|
||||
|
||||
/**
|
||||
* A query that can return results. Mostly, this is a {@link Select} query used
|
||||
@ -443,10 +443,10 @@ public interface ResultQuery<R extends Record> extends Query {
|
||||
* @see Record#into(Class)
|
||||
* @see Result#into(Class)
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
* @throws FetchIntoException wrapping any reflection exception that might
|
||||
* @throws MappingException wrapping any reflection exception that might
|
||||
* have occurred while mapping records
|
||||
*/
|
||||
<E> List<E> fetchInto(Class<? extends E> type) throws DataAccessException, FetchIntoException;
|
||||
<E> List<E> fetchInto(Class<? extends E> type) throws DataAccessException, MappingException;
|
||||
|
||||
/**
|
||||
* Map resulting records onto a custom record.
|
||||
|
||||
@ -43,7 +43,7 @@ import org.jooq.exception.DataAccessException;
|
||||
* @param <R> The record type
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public interface TableRecord<R extends Record> extends Record {
|
||||
public interface TableRecord<R extends TableRecord<R>> extends Record {
|
||||
|
||||
/**
|
||||
* The table from which this record was read
|
||||
|
||||
@ -68,7 +68,7 @@ import org.jooq.exception.DataAccessException;
|
||||
* @param <R> The record type
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public interface UpdatableRecord<R extends Record> extends Updatable<R>, TableRecord<R> {
|
||||
public interface UpdatableRecord<R extends UpdatableRecord<R>> extends Updatable<R>, TableRecord<R> {
|
||||
|
||||
/**
|
||||
* The table from which this record was read
|
||||
|
||||
@ -52,7 +52,7 @@ import org.jooq.ResultQuery;
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public class FetchIntoException extends DataAccessException {
|
||||
public class MappingException extends DataAccessException {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
@ -64,7 +64,7 @@ public class FetchIntoException extends DataAccessException {
|
||||
*
|
||||
* @param message the detail message
|
||||
*/
|
||||
public FetchIntoException(String message) {
|
||||
public MappingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ public class FetchIntoException extends DataAccessException {
|
||||
* @param cause the root cause (usually from using a underlying data access
|
||||
* API such as JDBC)
|
||||
*/
|
||||
public FetchIntoException(String message, Throwable cause) {
|
||||
public MappingException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@ -103,11 +103,11 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query {
|
||||
return result;
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw JooqUtil.translate("AbstractQuery.execute", sql, e);
|
||||
throw Util.translate("AbstractQuery.execute", sql, e);
|
||||
}
|
||||
finally {
|
||||
if (!keepStatementOpen()) {
|
||||
JooqUtil.safeClose(statement);
|
||||
Util.safeClose(statement);
|
||||
}
|
||||
|
||||
watch.splitDebug("Statement executed");
|
||||
|
||||
@ -276,6 +276,6 @@ abstract class AbstractQueryPart implements QueryPartInternal, AttachableInterna
|
||||
* Internal convenience method
|
||||
*/
|
||||
protected final DataAccessException translate(String task, String sql, SQLException e) {
|
||||
return JooqUtil.translate(task, sql, e);
|
||||
return Util.translate(task, sql, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,8 +36,18 @@
|
||||
|
||||
package org.jooq.impl;
|
||||
|
||||
import static org.jooq.impl.Util.getAnnotatedGetter;
|
||||
import static org.jooq.impl.Util.getAnnotatedMembers;
|
||||
import static org.jooq.impl.Util.getAnnotatedSetters;
|
||||
import static org.jooq.impl.Util.getMatchingGetter;
|
||||
import static org.jooq.impl.Util.getMatchingMembers;
|
||||
import static org.jooq.impl.Util.getMatchingSetters;
|
||||
import static org.jooq.impl.Util.hasColumnAnnotations;
|
||||
import static org.jooq.impl.Util.isJPAAvailable;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.Date;
|
||||
@ -54,7 +64,7 @@ import org.jooq.FieldProvider;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableRecord;
|
||||
import org.jooq.exception.FetchIntoException;
|
||||
import org.jooq.exception.MappingException;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
@ -487,29 +497,34 @@ abstract class AbstractRecord extends AbstractStore<Object> implements Record {
|
||||
public final <T> T into(Class<? extends T> type) {
|
||||
try {
|
||||
T result = type.newInstance();
|
||||
boolean useAnnotations = isJPAAvailable() && hasColumnAnnotations(type);
|
||||
|
||||
for (Field<?> field : getFields()) {
|
||||
List<java.lang.reflect.Field> members;
|
||||
List<java.lang.reflect.Method> methods;
|
||||
|
||||
// Annotations are available and present
|
||||
if (JooqUtil.isJPAAvailable() && JooqUtil.hasColumnAnnotations(type)) {
|
||||
members = JooqUtil.getAnnotatedMembers(type, field.getName());
|
||||
methods = JooqUtil.getAnnotatedMethods(type, field.getName());
|
||||
if (useAnnotations) {
|
||||
members = getAnnotatedMembers(type, field.getName());
|
||||
methods = getAnnotatedSetters(type, field.getName());
|
||||
}
|
||||
|
||||
// No annotations are present
|
||||
else {
|
||||
members = JooqUtil.getMatchingMembers(type, field.getName());
|
||||
methods = JooqUtil.getMatchingMethods(type, field.getName());
|
||||
members = getMatchingMembers(type, field.getName());
|
||||
methods = getMatchingSetters(type, field.getName());
|
||||
}
|
||||
|
||||
for (java.lang.reflect.Field member : members) {
|
||||
copyInto(result, member, field);
|
||||
|
||||
// [#935] Avoid setting final fields
|
||||
if ((member.getModifiers() & Modifier.FINAL) == 0) {
|
||||
into(result, member, field);
|
||||
}
|
||||
}
|
||||
|
||||
for (java.lang.reflect.Method method : methods) {
|
||||
copyInto(result, method, field);
|
||||
into(result, method, field);
|
||||
}
|
||||
}
|
||||
|
||||
@ -518,11 +533,74 @@ abstract class AbstractRecord extends AbstractStore<Object> implements Record {
|
||||
|
||||
// All reflection exceptions are intercepted
|
||||
catch (Exception e) {
|
||||
throw new FetchIntoException("An error ocurred when mapping record to " + type, e);
|
||||
throw new MappingException("An error ocurred when mapping record to " + type, e);
|
||||
}
|
||||
}
|
||||
|
||||
private final void copyInto(Object result, Method method, Field<?> field)
|
||||
@Override
|
||||
public final <R extends TableRecord<R>> R into(Table<R> table) {
|
||||
try {
|
||||
R result = Util.newRecord(table, getConfiguration());
|
||||
|
||||
for (Field<?> sourceField : getFields()) {
|
||||
Field<?> targetField = result.getField(sourceField);
|
||||
|
||||
if (targetField != null) {
|
||||
Util.setValue(result, targetField, this, sourceField);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// All reflection exceptions are intercepted
|
||||
catch (Exception e) {
|
||||
throw new MappingException("An error ocurred when mapping record to " + table, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void from(Object source) {
|
||||
if (source == null) return;
|
||||
|
||||
Class<?> type = source.getClass();
|
||||
|
||||
try {
|
||||
boolean useAnnotations = isJPAAvailable() && hasColumnAnnotations(type);
|
||||
|
||||
for (Field<?> field : getFields()) {
|
||||
List<java.lang.reflect.Field> members;
|
||||
Method method;
|
||||
|
||||
// Annotations are available and present
|
||||
if (useAnnotations) {
|
||||
members = getAnnotatedMembers(type, field.getName());
|
||||
method = getAnnotatedGetter(type, field.getName());
|
||||
}
|
||||
|
||||
// No annotations are present
|
||||
else {
|
||||
members = getMatchingMembers(type, field.getName());
|
||||
method = getMatchingGetter(type, field.getName());
|
||||
}
|
||||
|
||||
// Use only the first applicable method or member
|
||||
if (method != null) {
|
||||
Util.setValue(this, field, method.invoke(source));
|
||||
}
|
||||
else if (members.size() > 0) {
|
||||
from(source, members.get(0), field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All reflection exceptions are intercepted
|
||||
catch (Exception e) {
|
||||
throw new MappingException("An error ocurred when mapping record from " + type, e);
|
||||
}
|
||||
}
|
||||
|
||||
private final void into(Object result, Method method, Field<?> field)
|
||||
throws IllegalAccessException, InvocationTargetException {
|
||||
|
||||
Class<?> mType = method.getParameterTypes()[0];
|
||||
@ -555,7 +633,7 @@ abstract class AbstractRecord extends AbstractStore<Object> implements Record {
|
||||
}
|
||||
}
|
||||
|
||||
private final void copyInto(Object result, java.lang.reflect.Field member, Field<?> field) throws IllegalAccessException {
|
||||
private final void into(Object result, java.lang.reflect.Field member, Field<?> field) throws IllegalAccessException {
|
||||
Class<?> mType = member.getType();
|
||||
|
||||
if (mType.isPrimitive()) {
|
||||
@ -586,32 +664,36 @@ abstract class AbstractRecord extends AbstractStore<Object> implements Record {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <R extends TableRecord<R>> R into(Table<R> table) {
|
||||
try {
|
||||
R result = JooqUtil.newRecord(table, getConfiguration());
|
||||
private final void from(Object source, java.lang.reflect.Field member, Field<?> field)
|
||||
throws IllegalAccessException {
|
||||
|
||||
for (Field<?> field : getFields()) {
|
||||
Field<?> targetField = result.getField(field);
|
||||
Class<?> mType = member.getType();
|
||||
|
||||
if (targetField != null) {
|
||||
setValue(result, field, targetField);
|
||||
}
|
||||
if (mType.isPrimitive()) {
|
||||
if (mType == byte.class) {
|
||||
Util.setValue(this, field, member.getByte(source));
|
||||
}
|
||||
else if (mType == short.class) {
|
||||
Util.setValue(this, field, member.getShort(source));
|
||||
}
|
||||
else if (mType == int.class) {
|
||||
Util.setValue(this, field, member.getInt(source));
|
||||
}
|
||||
else if (mType == long.class) {
|
||||
Util.setValue(this, field, member.getLong(source));
|
||||
}
|
||||
else if (mType == float.class) {
|
||||
Util.setValue(this, field, member.getFloat(source));
|
||||
}
|
||||
else if (mType == double.class) {
|
||||
Util.setValue(this, field, member.getDouble(source));
|
||||
}
|
||||
else if (mType == boolean.class) {
|
||||
Util.setValue(this, field, member.getBoolean(source));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// All reflection exceptions are intercepted
|
||||
catch (Exception e) {
|
||||
throw new FetchIntoException("An error ocurred when mapping record to " + table, e);
|
||||
else {
|
||||
Util.setValue(this, field, member.get(source));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Type-safely copy a value from one record to another
|
||||
*/
|
||||
final <T> void setValue(Record target, Field<?> sourceField, Field<T> targetField) {
|
||||
target.setValue(targetField, targetField.getDataType().convert(getValue(sourceField)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,7 +290,7 @@ public abstract class AbstractRoutine<T> extends AbstractSchemaProviderQueryPart
|
||||
throw translate("AbstractRoutine.executeCallableStatement", sql, exc);
|
||||
}
|
||||
finally {
|
||||
JooqUtil.safeClose(statement);
|
||||
Util.safeClose(statement);
|
||||
watch.splitDebug("Routine executed");
|
||||
}
|
||||
}
|
||||
@ -408,12 +408,12 @@ public abstract class AbstractRoutine<T> extends AbstractSchemaProviderQueryPart
|
||||
// also the type name
|
||||
case ORACLE: {
|
||||
if (sqlType == Types.STRUCT) {
|
||||
UDTRecord<?> record = JooqUtil.newRecord((Class<? extends UDTRecord<?>>) parameter.getType());
|
||||
UDTRecord<?> record = Util.newRecord((Class<? extends UDTRecord<?>>) parameter.getType());
|
||||
statement.registerOutParameter(index, Types.STRUCT, record.getSQLTypeName());
|
||||
}
|
||||
|
||||
else if (sqlType == Types.ARRAY) {
|
||||
ArrayRecord<?> record = JooqUtil.newArrayRecord(
|
||||
ArrayRecord<?> record = Util.newArrayRecord(
|
||||
(Class<? extends ArrayRecord<?>>) parameter.getType(), configuration);
|
||||
statement.registerOutParameter(index, Types.ARRAY, record.getName());
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ abstract class AbstractStoreQuery<R extends TableRecord<R>> extends AbstractQuer
|
||||
}
|
||||
else {
|
||||
try {
|
||||
A record = JooqUtil.newArrayRecord(field.getType(), getConfiguration());
|
||||
A record = Util.newArrayRecord(field.getType(), getConfiguration());
|
||||
record.setList(value);
|
||||
addValue(field, record);
|
||||
}
|
||||
|
||||
@ -236,7 +236,7 @@ implements
|
||||
|
||||
if (!forUpdateOf.isEmpty()) {
|
||||
context.sql(" of ");
|
||||
JooqUtil.toSQLNames(context, forUpdateOf);
|
||||
Util.toSQLNames(context, forUpdateOf);
|
||||
}
|
||||
else if (!forUpdateOfTables.isEmpty()) {
|
||||
context.sql(" of ");
|
||||
@ -255,7 +255,7 @@ implements
|
||||
|
||||
// Render the OF [table-names] clause
|
||||
default:
|
||||
JooqUtil.toSQLNames(context, forUpdateOfTables);
|
||||
Util.toSQLNames(context, forUpdateOfTables);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ class AliasProviderImpl<T extends AliasProvider<T>> extends AbstractNamedQueryPa
|
||||
ArrayTable<?> table = (ArrayTable<?>) o;
|
||||
|
||||
context.sql("(");
|
||||
JooqUtil.toSQLNames(context, table.getFields());
|
||||
Util.toSQLNames(context, table.getFields());
|
||||
context.sql(")");
|
||||
}
|
||||
|
||||
|
||||
@ -88,10 +88,10 @@ class BatchMultiple implements Batch {
|
||||
return result;
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw JooqUtil.translate("BatchMultiple.execute", sql, e);
|
||||
throw Util.translate("BatchMultiple.execute", sql, e);
|
||||
}
|
||||
finally {
|
||||
JooqUtil.safeClose(statement);
|
||||
Util.safeClose(statement);
|
||||
watch.splitDebug("Statement executed");
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,10 +104,10 @@ class BatchSingle implements BatchBindStep {
|
||||
return result;
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw JooqUtil.translate("BatchSingle.execute", sql, e);
|
||||
throw Util.translate("BatchSingle.execute", sql, e);
|
||||
}
|
||||
finally {
|
||||
JooqUtil.safeClose(statement);
|
||||
Util.safeClose(statement);
|
||||
watch.splitDebug("Statement executed");
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,7 +191,7 @@ class CursorImpl<R extends Record> implements Cursor<R> {
|
||||
|
||||
@Override
|
||||
public final void close() {
|
||||
JooqUtil.safeClose(rs, stmt);
|
||||
Util.safeClose(rs, stmt);
|
||||
rs = null;
|
||||
stmt = null;
|
||||
isClosed = true;
|
||||
@ -246,7 +246,7 @@ class CursorImpl<R extends Record> implements Cursor<R> {
|
||||
|
||||
try {
|
||||
if (!isClosed && rs.next()) {
|
||||
record = JooqUtil.newRecord(type, fields, configuration);
|
||||
record = Util.newRecord(type, fields, configuration);
|
||||
final List<Field<?>> fieldList = fields.getFields();
|
||||
final int size = fieldList.size();
|
||||
|
||||
@ -260,7 +260,7 @@ class CursorImpl<R extends Record> implements Cursor<R> {
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw JooqUtil.translate("Cursor.fetch", null, e);
|
||||
throw Util.translate("Cursor.fetch", null, e);
|
||||
}
|
||||
|
||||
// Conveniently close cursors and underlying objects after the last
|
||||
|
||||
@ -55,7 +55,7 @@ class Decode<T, Z> extends AbstractFunction<Z> {
|
||||
private final Field<?>[] more;
|
||||
|
||||
public Decode(Field<T> field, Field<T> search, Field<Z> result, Field<?>[] more) {
|
||||
super("decode", result.getDataType(), JooqUtil.combine(field, search, result, more));
|
||||
super("decode", result.getDataType(), Util.combine(field, search, result, more));
|
||||
|
||||
this.field = field;
|
||||
this.search = search;
|
||||
|
||||
@ -68,7 +68,7 @@ class DefaultBindContext extends AbstractContext<BindContext> implements BindCon
|
||||
* Generated UID
|
||||
*/
|
||||
private static final long serialVersionUID = -5457385919209241505L;
|
||||
private static final JooqLogger log = JooqLogger.getLogger(JooqUtil.class);
|
||||
private static final JooqLogger log = JooqLogger.getLogger(Util.class);
|
||||
|
||||
private final PreparedStatement stmt;
|
||||
private int index;
|
||||
@ -169,7 +169,7 @@ class DefaultBindContext extends AbstractContext<BindContext> implements BindCon
|
||||
return bindValue0(value, type);
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw JooqUtil.translate("DefaultBindContext.bindValue", null, e);
|
||||
throw Util.translate("DefaultBindContext.bindValue", null, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ class DefaultBindContext extends AbstractContext<BindContext> implements BindCon
|
||||
|
||||
// Treat Oracle-style ARRAY types specially
|
||||
if (ArrayRecord.class.isAssignableFrom(type)) {
|
||||
String typeName = JooqUtil.newArrayRecord((Class<ArrayRecord<?>>) type, configuration).getName();
|
||||
String typeName = Util.newArrayRecord((Class<ArrayRecord<?>>) type, configuration).getName();
|
||||
stmt.setNull(nextIndex(), sqlType, typeName);
|
||||
}
|
||||
|
||||
|
||||
@ -84,7 +84,7 @@ class Expression<T> extends AbstractFunction<T> {
|
||||
private final ExpressionOperator operator;
|
||||
|
||||
Expression(ExpressionOperator operator, Field<T> lhs, Field<?>... rhs) {
|
||||
super(operator.toSQL(), lhs.getDataType(), JooqUtil.combine(lhs, rhs));
|
||||
super(operator.toSQL(), lhs.getDataType(), Util.combine(lhs, rhs));
|
||||
|
||||
this.operator = operator;
|
||||
this.lhs = lhs;
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
|
||||
package org.jooq.impl;
|
||||
|
||||
import static org.jooq.impl.JooqUtil.combine;
|
||||
import static org.jooq.impl.Util.combine;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
@ -795,7 +795,7 @@ public class Factory implements FactoryOperations {
|
||||
return new CursorImpl<Record>(this, fields, rs).fetch();
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw JooqUtil.translate("Factory.fetch", null, e);
|
||||
throw Util.translate("Factory.fetch", null, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1149,8 +1149,18 @@ public class Factory implements FactoryOperations {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final <R extends Record> R newRecord(Table<R> table) {
|
||||
return JooqUtil.newRecord(table, this);
|
||||
public final <R extends TableRecord<R>> R newRecord(Table<R> table) {
|
||||
return Util.newRecord(table, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final <R extends TableRecord<R>> R newRecord(Table<R> table, Object source) {
|
||||
R result = newRecord(table);
|
||||
result.from(source);
|
||||
return result;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -501,7 +501,7 @@ public final class FieldTypeHelper {
|
||||
}
|
||||
else {
|
||||
// TODO: [#523] Use array record meta data instead
|
||||
ArrayRecord<?> record = JooqUtil.newArrayRecord(type, configuration);
|
||||
ArrayRecord<?> record = Util.newArrayRecord(type, configuration);
|
||||
record.set(array);
|
||||
return record;
|
||||
}
|
||||
@ -963,7 +963,7 @@ public final class FieldTypeHelper {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
UDTRecord<?> record = (UDTRecord<?>) JooqUtil.newRecord((Class) type);
|
||||
UDTRecord<?> record = (UDTRecord<?>) Util.newRecord((Class) type);
|
||||
List<String> values = new PGobjectParser().parse(object.toString());
|
||||
|
||||
List<Field<?>> fields = record.getFields();
|
||||
|
||||
@ -463,7 +463,7 @@ class InsertQueryImpl<R extends TableRecord<R>> extends AbstractStoreQuery<R> im
|
||||
// additional query
|
||||
if (returning.size() == 1 && returning.get(0).equals(field)) {
|
||||
for (Number id : ids) {
|
||||
R typed = JooqUtil.newRecord(getInto(), configuration);
|
||||
R typed = Util.newRecord(getInto(), configuration);
|
||||
((AbstractRecord) typed).setValue(field, new Value<Number>(id));
|
||||
getReturnedRecords().add(typed);
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ class Join extends AbstractQueryPart {
|
||||
private void toSQL0(RenderContext context) {
|
||||
if (usingSyntax) {
|
||||
context.sql(" using (");
|
||||
JooqUtil.toSQLNames(context, using);
|
||||
Util.toSQLNames(context, using);
|
||||
context.sql(")");
|
||||
}
|
||||
else {
|
||||
|
||||
@ -434,7 +434,7 @@ class LoaderImpl<R extends TableRecord<R>> implements
|
||||
// SQLExceptions originating from rollbacks or commits are always fatal
|
||||
// They are propagated, and not swallowed
|
||||
catch (SQLException e) {
|
||||
throw JooqUtil.translate("LoaderImpl.executeCSV", null, e);
|
||||
throw Util.translate("LoaderImpl.executeCSV", null, e);
|
||||
}
|
||||
finally {
|
||||
reader.close();
|
||||
|
||||
@ -122,7 +122,7 @@ class MetaDataFieldProvider implements FieldProvider, Serializable {
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw JooqUtil.translate("MetaFieldProvider.init", null, e);
|
||||
throw Util.translate("MetaFieldProvider.init", null, e);
|
||||
}
|
||||
|
||||
meta = null;
|
||||
|
||||
@ -67,7 +67,7 @@ class SQLCondition extends AbstractCondition {
|
||||
// We have no control over the plain SQL content, hence we MUST put it
|
||||
// in parentheses to ensure correct semantics
|
||||
|
||||
JooqUtil.toSQLReferenceWithParentheses(context, sql, bindings);
|
||||
Util.toSQLReferenceWithParentheses(context, sql, bindings);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -67,7 +67,7 @@ class SQLField<T> extends AbstractField<T> {
|
||||
|
||||
@Override
|
||||
public final void toSQL(RenderContext context) {
|
||||
JooqUtil.toSQLReference(context, sql, bindings);
|
||||
Util.toSQLReference(context, sql, bindings);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -65,7 +65,7 @@ class SQLQuery extends AbstractQuery {
|
||||
|
||||
@Override
|
||||
public final void toSQL(RenderContext context) {
|
||||
JooqUtil.toSQLReference(context, sql, bindings);
|
||||
Util.toSQLReference(context, sql, bindings);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -70,7 +70,7 @@ class SQLResultQuery extends AbstractResultQuery<Record> {
|
||||
|
||||
@Override
|
||||
public final void toSQL(RenderContext context) {
|
||||
JooqUtil.toSQLReference(context, sql, bindings);
|
||||
Util.toSQLReference(context, sql, bindings);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -78,7 +78,7 @@ class SQLTable extends AbstractTable<Record> {
|
||||
|
||||
@Override
|
||||
public final void toSQL(RenderContext context) {
|
||||
JooqUtil.toSQLReference(context, sql, bindings);
|
||||
Util.toSQLReference(context, sql, bindings);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -43,7 +43,6 @@ import java.util.Set;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Identity;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.TableRecord;
|
||||
import org.jooq.UniqueKey;
|
||||
import org.jooq.UpdatableRecord;
|
||||
import org.jooq.UpdatableTable;
|
||||
@ -55,7 +54,7 @@ import org.jooq.UpdatableTable;
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public class UpdatableRecordImpl<R extends TableRecord<R>> extends TableRecordImpl<R> implements UpdatableRecord<R> {
|
||||
public class UpdatableRecordImpl<R extends UpdatableRecord<R>> extends TableRecordImpl<R> implements UpdatableRecord<R> {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
|
||||
@ -37,6 +37,7 @@ package org.jooq.impl;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
@ -65,7 +66,7 @@ import org.jooq.tools.StringUtils;
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
final class JooqUtil {
|
||||
final class Util {
|
||||
|
||||
/**
|
||||
* Indicating whether JPA (<code>javax.persistence</code>) is on the
|
||||
@ -338,13 +339,13 @@ final class JooqUtil {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (java.lang.reflect.Field member : type.getFields()) {
|
||||
for (java.lang.reflect.Field member : getInstanceMembers(type)) {
|
||||
if (member.getAnnotation(Column.class) != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (Method method : type.getMethods()) {
|
||||
for (Method method : getInstanceMethods(type)) {
|
||||
if (method.getAnnotation(Column.class) != null) {
|
||||
return true;
|
||||
}
|
||||
@ -359,7 +360,7 @@ final class JooqUtil {
|
||||
static final List<java.lang.reflect.Field> getAnnotatedMembers(Class<?> type, String name) {
|
||||
List<java.lang.reflect.Field> result = new ArrayList<java.lang.reflect.Field>();
|
||||
|
||||
for (java.lang.reflect.Field member : type.getFields()) {
|
||||
for (java.lang.reflect.Field member : getInstanceMembers(type)) {
|
||||
Column annotation = member.getAnnotation(Column.class);
|
||||
|
||||
if (annotation != null) {
|
||||
@ -378,7 +379,7 @@ final class JooqUtil {
|
||||
static final List<java.lang.reflect.Field> getMatchingMembers(Class<?> type, String name) {
|
||||
List<java.lang.reflect.Field> result = new ArrayList<java.lang.reflect.Field>();
|
||||
|
||||
for (java.lang.reflect.Field member : type.getFields()) {
|
||||
for (java.lang.reflect.Field member : getInstanceMembers(type)) {
|
||||
if (name.equals(member.getName())) {
|
||||
result.add(member);
|
||||
}
|
||||
@ -391,12 +392,12 @@ final class JooqUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all methods annotated with a given column name
|
||||
* Get all setter methods annotated with a given column name
|
||||
*/
|
||||
static final List<Method> getAnnotatedMethods(Class<?> type, String name) {
|
||||
static final List<Method> getAnnotatedSetters(Class<?> type, String name) {
|
||||
List<Method> result = new ArrayList<Method>();
|
||||
|
||||
for (Method method : type.getMethods()) {
|
||||
for (Method method : getInstanceMethods(type)) {
|
||||
Column annotation = method.getAnnotation(Column.class);
|
||||
|
||||
if (annotation != null && name.equals(annotation.name())) {
|
||||
@ -429,12 +430,58 @@ final class JooqUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all methods matching a given column name
|
||||
* Get the first getter method annotated with a given column name
|
||||
*/
|
||||
static final List<Method> getMatchingMethods(Class<?> type, String name) {
|
||||
static final Method getAnnotatedGetter(Class<?> type, String name) {
|
||||
for (Method method : getInstanceMethods(type)) {
|
||||
Column annotation = method.getAnnotation(Column.class);
|
||||
|
||||
if (annotation != null && name.equals(annotation.name())) {
|
||||
|
||||
// Annotated getter
|
||||
if (method.getParameterTypes().length == 0) {
|
||||
return method;
|
||||
}
|
||||
|
||||
// Annotated setter with matching getter
|
||||
else if (method.getParameterTypes().length == 1) {
|
||||
String m = method.getName();
|
||||
|
||||
if (m.startsWith("set")) {
|
||||
try {
|
||||
Method getter = type.getMethod("get" + m.substring(3));
|
||||
|
||||
// Getter annotation is more relevant
|
||||
if (getter.getAnnotation(Column.class) == null) {
|
||||
return getter;
|
||||
}
|
||||
}
|
||||
catch (NoSuchMethodException ignore) {}
|
||||
|
||||
try {
|
||||
Method getter = type.getMethod("is" + m.substring(3));
|
||||
|
||||
// Getter annotation is more relevant
|
||||
if (getter.getAnnotation(Column.class) == null) {
|
||||
return getter;
|
||||
}
|
||||
}
|
||||
catch (NoSuchMethodException ignore) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all setter methods matching a given column name
|
||||
*/
|
||||
static final List<Method> getMatchingSetters(Class<?> type, String name) {
|
||||
List<Method> result = new ArrayList<Method>();
|
||||
|
||||
for (Method method : type.getMethods()) {
|
||||
for (Method method : getInstanceMethods(type)) {
|
||||
if (method.getParameterTypes().length == 1) {
|
||||
if (name.equals(method.getName())) {
|
||||
result.add(method);
|
||||
@ -453,4 +500,73 @@ final class JooqUtil {
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the first getter method matching a given column name
|
||||
*/
|
||||
static final Method getMatchingGetter(Class<?> type, String name) {
|
||||
for (Method method : getInstanceMethods(type)) {
|
||||
if (method.getParameterTypes().length == 0) {
|
||||
if (name.equals(method.getName())) {
|
||||
return method;
|
||||
}
|
||||
else if (StringUtils.toCamelCaseLC(name).equals(method.getName())) {
|
||||
return method;
|
||||
}
|
||||
else if (("get" + name).equals(method.getName())) {
|
||||
return method;
|
||||
}
|
||||
else if (("get" + StringUtils.toCamelCase(name)).equals(method.getName())) {
|
||||
return method;
|
||||
}
|
||||
else if (("is" + name).equals(method.getName())) {
|
||||
return method;
|
||||
}
|
||||
else if (("is" + StringUtils.toCamelCase(name)).equals(method.getName())) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final List<Method> getInstanceMethods(Class<?> type) {
|
||||
List<Method> result = new ArrayList<Method>();
|
||||
|
||||
for (Method method : type.getMethods()) {
|
||||
if ((method.getModifiers() & Modifier.STATIC) == 0) {
|
||||
result.add(method);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final List<java.lang.reflect.Field> getInstanceMembers(Class<?> type) {
|
||||
List<java.lang.reflect.Field> result = new ArrayList<java.lang.reflect.Field>();
|
||||
|
||||
for (java.lang.reflect.Field field : type.getFields()) {
|
||||
if ((field.getModifiers() & Modifier.STATIC) == 0) {
|
||||
result.add(field);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type-safely copy a value from one record to another
|
||||
*/
|
||||
static final <T> void setValue(Record target, Field<T> targetField, Record source, Field<?> sourceField) {
|
||||
setValue(target, targetField, source.getValue(sourceField));
|
||||
}
|
||||
|
||||
/**
|
||||
* Type-safely set a value to a record
|
||||
*/
|
||||
static final <T> void setValue(Record target, Field<T> targetField, Object value) {
|
||||
target.setValue(targetField, targetField.getDataType().convert(value));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user