gpt4 book ai didi

java - 使用 ormlite 访问现有的 postgres 数据库

转载 作者:行者123 更新时间:2023-11-29 13:31:20 24 4
gpt4 key购买 nike

我刚开始编写一个应用程序,该应用程序应该使用 ormlite 来访问我已经创建的 postgreSQL 数据库。它使用下面的数据库方案和域对象类。但是,我无法创建运行下面测试方法的新用户。使用此类访问数据库没有问题。我得到的异常只是告诉我 postgre 无法插入:

java.sql.SQLException: Unable to run insert stmt on object net.avedo.spozz.models.User@78412176: INSERT INTO "users" ("id" ,"cdate" ,"mdate" ,"name" ,"email" ,"password" ,"avatar_id" ) VALUES (?,?,?,?,?,?,?)
at com.j256.ormlite.misc.SqlExceptionUtil.create(SqlExceptionUtil.java:22)
at com.j256.ormlite.stmt.mapped.MappedCreate.insert(MappedCreate.java:135)
at com.j256.ormlite.stmt.StatementExecutor.create(StatementExecutor.java:450)
at com.j256.ormlite.dao.BaseDaoImpl.create(BaseDaoImpl.java:310)
at net.avedo.spozz.models.UserTest.testUserCreation(UserTest.java:178)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
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.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:264)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:200)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:153)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
Caused by: org.postgresql.util.PSQLException: ERROR: column "cdate" is of type timestamp without time zone but expression is of type character varying
Hint: You will need to rewrite or cast the expression.
Position: 100
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2103)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1836)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:512)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:388)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:334)
at com.j256.ormlite.jdbc.JdbcDatabaseConnection.insert(JdbcDatabaseConnection.java:170)
at com.j256.ormlite.stmt.mapped.MappedCreate.insert(MappedCreate.java:91)
... 28 more

那我错过了什么?我该如何扩展 Avatar 类才能支持像 avatar bytea NOT NULL 这样的 bytea 字段?

postgreSQL数据库方案

CREATE TABLE avatars (
id BIGSERIAL PRIMARY KEY,
cdate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
mdate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
cdate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
mdate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
name VARCHAR(160) UNIQUE NOT NULL,
email VARCHAR (355) UNIQUE NOT NULL,
password VARCHAR(30) NOT NULL,
avatar_id BIGINT,
CONSTRAINT user_avatar_id FOREIGN KEY (avatar_id)
REFERENCES avatars (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
);

一个简单的测试用例

@Test
public void testUserCreation() throws Exception {
try {
// Setup the user database object, ...
Dao<User, Integer> userDao = getUserDao();

// ... create a new user ...
User user = new User();
user.setName("Andi");
user.setEmail("info@avedo.net");
user.setPassword("geheim");
userDao.create(user);

// ... and finally query all users.
List<User> userList = userDao.query(
userDao.queryBuilder().where()
.eq("name", "Andi")
.prepare());

Assert.assertTrue("User creation failed.", userList.get(0).getName().equals("Andi"));
Assert.assertTrue("User creation failed." + userList.get(0).getName(), userList.get(0).getName().equals("Andi"));
} catch (SQLException e) {
throw new Exception("Failed to create user: " + e.getMessage());
}
}

Avatar.java

@DatabaseTable(tableName = "avatars")
public class Avatar {
@DatabaseField(generatedIdSequence = "avatars_id_seq", useGetSet = true)
private long id;

@DatabaseField(canBeNull = false, defaultValue="CURRENT_TIMESTAMP", useGetSet = true)
private String cdate;

@DatabaseField(canBeNull = false, defaultValue="CURRENT_TIMESTAMP", useGetSet = true)
private String mdate;

public Avatar() {
// ORMLite needs a no-arg constructor
}

// Getter and setter methods.
}

用户.java

@DatabaseTable(tableName = "users")
public class User {
@DatabaseField(generatedIdSequence = "users_id_seq", useGetSet = true)
private long id;

@DatabaseField(canBeNull = false, defaultValue="CURRENT_TIMESTAMP", useGetSet = true)
private String cdate;

@DatabaseField(canBeNull = false, defaultValue="CURRENT_TIMESTAMP", useGetSet = true)
private String mdate;

@DatabaseField(canBeNull = false, useGetSet = true)
private String name;

@DatabaseField(canBeNull = false, useGetSet = true)
private String email;

@DatabaseField(canBeNull = false, useGetSet = true)
private String password;

@DatabaseField(columnName = "avatar_id", foreign = true, useGetSet = true)
private Avatar avatar;

public User() {
// ORMLite needs a no-arg constructor
}

// Getter and setter methods.
}

最佳答案

我能够通过将 cdate 和 mdate 的属性类型从 String 更改为 Date 来解决我的问题。此外,我必须从 @DatabaseField 注释中删除 defaultValuecanBeNull 参数。这给我留下了以下类(class):

@DatabaseTable(tableName = "users")
public class User {
@DatabaseField(generatedIdSequence = "users_id_seq", useGetSet = true)
private long id;

@DatabaseField(useGetSet = true)
private Date cdate;

@DatabaseField(useGetSet = true)
private Date mdate;

@DatabaseField(canBeNull = false, useGetSet = true)
private String name;

@DatabaseField(canBeNull = false, useGetSet = true)
private String email;

@DatabaseField(canBeNull = false, useGetSet = true)
private String password;

@DatabaseField(columnName = "avatar_id", foreign = true, useGetSet = true)
private Avatar avatar;

public User() {
// ORMLite needs a no-arg constructor
}

// Getter and setter methods.
}

最后,我不得不相应地调整数据库方案:

CREATE TABLE avatars (
id BIGSERIAL PRIMARY KEY,
cdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
mdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP
-- avatar bytea NOT NULL
);

CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
cdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
mdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
name VARCHAR(160) NOT NULL,
email VARCHAR (355) UNIQUE NOT NULL,
password VARCHAR(30) NOT NULL,
avatar_id BIGINT,
CONSTRAINT user_avatar_id FOREIGN KEY (avatar_id)
REFERENCES avatars (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
);

为了避免出现NULL值,我将cdate和mdate的默认值设置为CURRENT_TIMESTAMP,并添加了一个触发器,如果​​相应的行发生变化,它会自动更新mdate的值:

CREATE OR REPLACE FUNCTION update_timestamp() RETURNS TRIGGER AS 
$update_timestamp$
BEGIN
NEW.mdate := CURRENT_TIMESTAMP;
RETURN NEW;
END;
$update_timestamp$
LANGUAGE plpgsql;

CREATE TRIGGER update_timestamp BEFORE INSERT OR UPDATE ON avatars
FOR EACH ROW EXECUTE PROCEDURE update_timestamp();

CREATE TRIGGER update_timestamp BEFORE INSERT OR UPDATE ON users
FOR EACH ROW EXECUTE PROCEDURE update_timestamp();

关于java - 使用 ormlite 访问现有的 postgres 数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22345235/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com