java你能在没有外键的情况下用OneToOne关系链接两个实体吗?
您好,我在分配项目中的OneToOne关系时遇到问题。 这是我的球员。爪哇
@Table(name = "player")
public class Player implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "player_id", unique = true, nullable = false)
private Integer id;
@NotNull
private String username, password, email;
@NotNull
private Integer rank;
private Integer userType; // 0 - regular user, 1 - admin
private Review review;
public Player() {}
public Player(@NotNull String username, @NotNull String password, @NotNull String email, @NotNull Integer rank, Integer userType) {
this.username = username;
this.password = password;
this.email = email;
this.rank = rank;
this.userType = userType;
}
// Getters and Setters
@JsonGetter("id")
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
@JsonGetter("username")
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
@JsonGetter("password")
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
@JsonGetter("email")
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
@JsonGetter("rank")
public Integer getRank() { return rank; }
public void setRank(Integer rank) { this.rank = rank; }
@JsonGetter("user_type")
public Integer getUserType() { return userType; }
public void setUserType(Integer userType) { this.userType = userType; }
public Review getReview() {
return review;
}
public void setReview(Review review) {
this.review = review;
}
}
复习。爪哇
@Entity
@Table(name = "review")
public class Review {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "review_id", insertable = false, updatable = false, unique = true, nullable = false)
private int id;
@Column(name = "timestamp")
private Timestamp timestamp;
@Column(name = "description")
private String description;
private Player player;
// Constructors
public Review() {
}
public Review(int Id, Timestamp timestamp, String description) {
this.id = Id;
this.timestamp = timestamp;
this.description = description;
}
// Getters and Setters
@JsonGetter("id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@JsonGetter("timestamp")
public Timestamp getTimestamp() {
return timestamp;
}
public void setTimestamp(Timestamp timestamp) {
this.timestamp = timestamp;
}
@JsonGetter("description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@JsonGetter("player")
public Player getPlayer() {
return player;
}
public void setPlayer(Player player) {
this.player = player;
}
}
玩家。哈佛商学院。xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.montini.teamsports.model">
<class name="Player" table="player">
<meta attribute="class-description">
This class contains the player detail.
</meta>
<id name="id" type="int" column="player_id">
<generator class="native"/>
</id>
<property name="username" column="username" type="string"/>
<property name="password" column="password" type="string"/>
<property name="email" column="email" type="string"/>
<property name="rank" column="user_rank" type="int"/>
<property name="userType" column="user_type" type="int"/>
<one-to-one name="review" class="com.montini.teamsports.model.Review"
constrained="true"></one-to-one>
<!--<property name="userType">-->
<!-- <type name="org.hibernate.type.EnumType">-->
<!-- <param name="enumClass">com.montini.teamsports.model.UserType</param>-->
<!-- <param name="useNamed">true</param>-->
<!-- </type>-->
<!--</property>-->
</class>
</hibernate-mapping>
复习。哈佛商学院。xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.montini.teamsports.model">
<class name="Review" table="review">
<id name="id" column="review_id">
</id>
<one-to-one name="player" foreign-key="player_id" class="com.montini.teamsports.model.Player" cascade="save-update">
</one-to-one>
<property name="timestamp" column="timestamp" type="timestamp"/>
<property name="description" column="description" type="string"/>
</class>
</hibernate-mapping>
这是DDL
CREATE TABLE player
(
player_id int primary key not null auto_increment,
username varchar(30),
password varchar(30),
email varchar(50),
user_rank int,
user_type int,
unique (player_id)
);
CREATE TABLE review
(
review_id int PRIMARY KEY NOT NULL AUTO_INCREMENT,
player_id int not null,
timestamp datetime,
description text,
unique (review_id),
KEY FK_player_review (player_id),
CONSTRAINT FK_player_review FOREIGN KEY (player_id) REFERENCES player (player_id)
);
测试类别为:
public class ReviewTest {
public static final Logger log = LoggerFactory.getLogger(Review.class);
@Test
public void test1() {
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
Player player = new Player();
player.setUsername("Ignas");
player.setPassword("kokokok");
player.setEmail("jojo@jojo.com");
player.setUserType(0);
player.setRank(10);
Review review = new Review();
review.setTimestamp(new Timestamp(System.currentTimeMillis()));
review.setDescription("New message from team-sport user.");
review.setPlayer(player);
player.setReview(review);
session.save(player);
session.save(review);
transaction.commit();
} catch (RuntimeException e) {
e.printStackTrace();
} finally {
if (session != null) {
session.close();
}
}
}
}
我得到的错误是:
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not execute statement
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1348)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:435)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3221)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2389)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
at com.montini.teamsports.ReviewTest.test1(ReviewTest.java:47)
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:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:436)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:170)
at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:166)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:113)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:58)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:112)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:55)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.hibernate.exception.GenericJDBCException: could not execute statement
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:200)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3208)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3722)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:91)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)
at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:349)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:108)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1344)
... 63 more
Caused by: java.sql.SQLException: Field 'player_id' doesn't have a default value
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:121)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:116)
at com.mysql.cj.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1867)
at com.mysql.cj.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2029)
at com.mysql.cj.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:1970)
at com.mysql.cj.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:4996)
at com.mysql.cj.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1955)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)
... 74 more
我认为主要的问题是,玩家id没有默认值。但当调试这个测试时,它显示玩家被分配去查看
# 1 楼答案
看起来,你并没有在坚持的同时让球员复习。 您必须首先持久化player,然后在持久化审阅之前,获取要添加审阅的player,并在业务逻辑中手动设置它