Java 一对多冬眠
嗨,我正试图做一对多的插入,但我有问题。 我有两张桌子:Java 一对多冬眠,java,hibernate,Java,Hibernate,嗨,我正试图做一对多的插入,但我有问题。 我有两张桌子: CREATE TABLE users_app ( user_id int UNSIGNED NOT NULL AUTO_INCREMENT, user_number varchar(45) NOT NULL default '0', user_password varchar(45) NOT NULL default '0', os int(1) unsigned NOT NULL, token varchar(500
CREATE TABLE users_app (
user_id int UNSIGNED NOT NULL AUTO_INCREMENT,
user_number varchar(45) NOT NULL default '0',
user_password varchar(45) NOT NULL default '0',
os int(1) unsigned NOT NULL,
token varchar(500) NOT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8;
CREATE TABLE user_app_devices(
id int AUTO_INCREMENT PRIMARY KEY,
user_id int UNSIGNED NOT NULL,
device_name varchar(45) NOT NULL,
FOREIGN KEY (user_id) REFERENCES users_app (user_id)
)ENGINE=InnoDB CHARSET=utf8;
我的班级:
@Entity
@Table(name="user_app_devices")
public class UserAppDevice implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private int id;
@Column(name="device_name")
private String deviceName;
//bi-directional many-to-one association to UsersApp
@ManyToOne
@JoinColumn(name="user_id")
private UsersApp usersApp;
public UserAppDevice() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getDeviceName() {
return this.deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public UsersApp getUsersApp() {
return this.usersApp;
}
public void setUsersApp(UsersApp usersApp) {
this.usersApp = usersApp;
}
}
@Entity
@Table(name="users_app")
public class UsersApp implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="user_id")
private int userId;
private int os;
private String token;
@Column(name="user_number")
private String userNumber;
@Column(name="user_password")
private String userPassword;
//bi-directional many-to-one association to UserAppDevice
@OneToMany(mappedBy="usersApp")
private List<UserAppDevice> userAppDevices;
public UsersApp() {
}
public int getUserId() {
return this.userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getOs() {
return this.os;
}
public void setOs(int os) {
this.os = os;
}
public String getToken() {
return this.token;
}
public void setToken(String token) {
this.token = token;
}
public String getUserNumber() {
return this.userNumber;
}
public void setUserNumber(String userNumber) {
this.userNumber = userNumber;
}
public String getUserPassword() {
return this.userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
public List<UserAppDevice> getUserAppDevices() {
return this.userAppDevices;
}
public void setUserAppDevices(List<UserAppDevice> userAppDevices) {
this.userAppDevices = userAppDevices;
}
public UsersApp(int os, String token, String userNumber, String userPassword) {
this.os = os;
this.token = token;
this.userNumber = userNumber;
this.userPassword = userPassword;
}
但我面临一个例外:
13:16:48,516 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--0.0.0.0-8080-3) SQL Error: 1452, SQLState: 23000
13:16:48,517 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--0.0.0.0-8080-3) Cannot add or update a child row: a foreign key constraint fails (`application`.`user_a
pp_devices`, CONSTRAINT `user_app_devices_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users_app` (`user_id`))
13:16:48,520 ERROR [org.jboss.as.ejb3.tx.CMTTxInterceptor] (http--0.0.0.0-8080-3) javax.ejb.EJBTransactionRolledbackException: Cannot add or update a child row: a foreign key const
raint fails (`application`.`user_app_devices`, CONSTRAINT `user_app_devices_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users_app` (`user_id`))
13:16:48,524 ERROR [org.jboss.ejb3.invocation] (http--0.0.0.0-8080-3) JBAS014134: EJB Invocation failed on component DeviceRegisterDAOImpl for method public abstract void com.break
id.ejb.model.DeviceRegisterDAO.add(int,java.lang.String,java.lang.String,java.lang.String,java.lang.String): javax.ejb.EJBTransactionRolledbackException: Cannot add or update a chi
ld row: a foreign key constraint fails (`application`.`user_app_devices`, CONSTRAINT `user_app_devices_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users_app` (`user_id`))
at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleInCallerTx(CMTTxInterceptor.java:139) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInCallerTx(CMTTxInterceptor.java:204) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:306) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:190) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.1.Final.jar:1.1.1.Final]
at org.jboss.as.ejb3.remote.EJBRemoteTransactionPropagatingInterceptor.processInvocation(EJBRemoteTransactionPropagatingInterceptor.java:80) [jboss-as-ejb3-7.1.1.Final.jar:
7.1.1.Final]
我遗漏了什么?您没有告诉Hibernate UserApp的ID是由数据库自动生成的:
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name="user_id")
private int userId;
(并对其他实体执行相同操作)由于您使用的是双向的,请按如下所示更改您的客户端代码
Session session = (Session) em.getDelegate();
session.beginTransaction();
UserAppDevice ud = new UserAppDevice();
ud.setDeviceName(device);
UsersApp user = new UsersApp(os, token, userNumber, userPassword);
user.setUserAppDevices(new ArrayList<UserAppDevice>())
user.getUserAppDevices().add(ud);
session.save(user);
session.getTransaction().commit();
Session Session=(Session)em.getDelegate();
session.beginTransaction();
UserAppDevice ud=新的UserAppDevice();
ud.setDeviceName(设备);
UsersApp user=newusersapp(操作系统、令牌、用户号、用户密码);
user.setUserAppDevices(新ArrayList())
user.getUserAppDevices().add(ud);
session.save(用户);
session.getTransaction().commit();
正如JB Nizet所提到的,您缺少自动生成的策略
另一种方法是使用UUID
作为id
列,自己创建值
@Id
private UUID id = UUID.randomUUID();
另外,不要忘记设置equals/hashCode
以使用id
字段,如中所述
顺便提一下,为什么要使用
会话
(特定于hibernate)而不是坚持JPA的API?OP有一个mappedBy属性,无论使用联接表还是联接列,它在每个双向关联中都是必需的。关于equals/hashCode:它们根本不是强制性的,Hibernate建议不要使用ID。你太晚了:-P我实际上发现了这一点,并在7分钟前更新了我的评论。我没有看到代码片段上的滚动条,我最初也没有看到第二个类定义。我知道Hibernate推荐了一个业务密钥,但这个论点是老生常谈——现代惯例是使用id
并在构造时自己生成密钥。我使用UUID
,因为它避免了使用奇怪的系统来确保数据库中的唯一性。这在你的地方才是现代的。对于PKs来说,UUID的效率比数字低,序列或自动增量比UUID更容易使用。UUID
的使用是我自己对它的理解——关于性能,你是对的,但是它从来没有影响到我——尽管我很确定Hibernate的人现在都同意,如果主键是在构造过程中生成的,那么可以使用主键。如果未设置id
,我宁愿在hashCode
中抛出一个异常,也不愿麻烦地获取一个合适的Long
,以便在构建时使用。这不起作用,只有用户添加到数据库中,设备没有
@Id
private UUID id = UUID.randomUUID();