Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ID data type mismatches in PostgreSQL #9

Closed
randomf opened this issue Oct 6, 2015 · 6 comments
Closed

ID data type mismatches in PostgreSQL #9

randomf opened this issue Oct 6, 2015 · 6 comments

Comments

@randomf
Copy link
Contributor

randomf commented Oct 6, 2015

When inserting record to a table with ID defined as "serial" data type in PostgreSQL and having @id @GeneratedValue annotations on getter method in POJO, ID generated and returned by database is of Long type. However when I perform db.results() on the same class IDs are retrieved as Integer. This behaviour leads to type mismatch. Any idea how to approach the fix? Should we automatically convert Integers to Longs where possible and vice versa (if the value doesn't overflow)? Or is there better way?

@randomf
Copy link
Contributor Author

randomf commented Oct 7, 2015

Not sure if this is the right solution, but something like this should do... randomf@bdd0187

@dieselpoint
Copy link
Collaborator

dieselpoint commented Oct 7, 2015 via email

@randomf
Copy link
Contributor Author

randomf commented Oct 13, 2015

Hello,

please see the attached files. Let me know if you need more information on the problem. I added stack traces to the comments next to jUnit routines. I hope this helps...

Thank you

POJO

package test;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;


@Table(name = "pojo") 
public class NormPojo {

    /** Database record ID. */
    private Integer databaseId;

    /** Unique identifier of the object. */
    private String id;

    /** Human readable name. */
    private String name;

    /**
     * @return the id
     */
    @Column(name = "object_id", unique = true)
    public String getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(String id) {
        this.id = id;
    }

    /**
     * @return the name
     */
    @Column(name = "name")
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    @Id
    @GeneratedValue
    @Column(name = "id")
    public Integer getDatabaseId() {
        return databaseId;
    }

    public void setDatabaseId(Integer databaseId) {
        this.databaseId = databaseId;
    }   

}

jUnit routines

package test;


import java.util.List;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.dieselpoint.norm.Database;

public class NormPojoPersistenceTest {

    static String DB_DRIVER_CLASS_NAME = "org.postgresql.ds.PGSimpleDataSource";
    static String DB_SERVER_NAME = "localhost";
    static String DB_DATABASE = "testdb";
    static String DB_USERNAME = "testuser";
    static String DB_PASSWORD = "testpass";

    private Database db;

    @Before
    public void setUp() {
        System.setProperty("norm.dataSourceClassName", DB_DRIVER_CLASS_NAME);
        System.setProperty("norm.serverName", DB_SERVER_NAME);
        System.setProperty("norm.databaseName", DB_DATABASE);
        System.setProperty("norm.user", DB_USERNAME);
        System.setProperty("norm.password", DB_PASSWORD);

        db = new Database();
    }

    /*
     * This test doesn't work when NormPojo.databaseId is of type Integer. However the record is inserted in the database.
     * 
     * com.dieselpoint.norm.DbException: com.dieselpoint.norm.DbException: Could not write value into pojo. Property: id method: public void test.NormPojo.setDatabaseId(java.lang.Integer) value: 1
    at com.dieselpoint.norm.sqlmakers.StandardSqlMaker.populateGeneratedKey(StandardSqlMaker.java:356)
    at com.dieselpoint.norm.Query.execute(Query.java:339)
    at com.dieselpoint.norm.Query.insert(Query.java:256)
    at com.dieselpoint.norm.Database.insert(Database.java:109)
    at test.NormPojoPersistenceTest.testCreate(NormPojoPersistenceTest.java:38)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: com.dieselpoint.norm.DbException: Could not write value into pojo. Property: id method: public void test.NormPojo.setDatabaseId(java.lang.Integer) value: 1
    at com.dieselpoint.norm.sqlmakers.StandardPojoInfo.putValue(StandardPojoInfo.java:257)
    at com.dieselpoint.norm.sqlmakers.StandardSqlMaker.populateGeneratedKey(StandardSqlMaker.java:353)
    ... 28 more
Caused by: java.lang.IllegalArgumentException: argument type mismatch
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.dieselpoint.norm.sqlmakers.StandardPojoInfo.putValue(StandardPojoInfo.java:254)
    ... 29 more


     */
    @Test
    public void testCreate() {
        NormPojo np = new NormPojo();
        np.setId("MyID");
        np.setName("My name");
        db.insert(np);
        Assert.assertNotNull(np.getDatabaseId());
    }

    /*
     * Test test runs correctly when NormPojo.databaseId is of type Integer.
     * 
     * However when changing NormPojo.databaseId to type Long, following exception is thrown:
     * com.dieselpoint.norm.DbException: Could not write value into pojo. Property: id method: public void test.NormPojo.setDatabaseId(java.lang.Long) value: 1
    at com.dieselpoint.norm.sqlmakers.StandardPojoInfo.putValue(StandardPojoInfo.java:257)
    at com.dieselpoint.norm.Query.results(Query.java:207)
    at com.dieselpoint.norm.Database.results(Database.java:128)
    at test.NormPojoPersistenceTest.testRetrieval(NormPojoPersistenceTest.java:98)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.IllegalArgumentException: argument type mismatch
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.dieselpoint.norm.sqlmakers.StandardPojoInfo.putValue(StandardPojoInfo.java:254)
    ... 27 more


     */
    @Test
    public void testRetrieval() {
        List<NormPojo> npList = null;
        npList = db.results(NormPojo.class);
        Assert.assertNotNull(npList);
        Assert.assertTrue(npList.size() > 0);
    }

}

Schema

CREATE TABLE pojo (
    id serial,
    object_id varchar(128) NOT NULL,
    name varchar(128) NOT NULL,
    CONSTRAINT pk PRIMARY KEY (id)
);

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>norm</groupId>
  <artifactId>test</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>  
        <dependency>
            <groupId>com.dieselpoint</groupId>
            <artifactId>norm</artifactId>
            <version>0.8.1-rc2</version>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.4-1201-jdbc41</version>
        </dependency>  
  </dependencies>

  <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>  
  </build>  
</project>

@johngray
Copy link

I can confirm the issue on H2 database.

@johngray
Copy link

The check if the filed is an int or Integer should be like this:

prop.dataType.equals(Integer.class) || prop.dataType.equals(Integer.TYPE)

isAssignableFrom() is working only for classes in the same object hierarchy. int and Integer are completely diferent classes.

@ccleve
Copy link
Member

ccleve commented May 26, 2018

Fixed. Sorry it took so long. Will be in today's release.

@ccleve ccleve closed this as completed in 0f33aca May 26, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants