首页 \ 问答 \ Hibernate不会在级联上生成子ID所有保存(Hibernate not generating child id on cascade all save)

Hibernate不会在级联上生成子ID所有保存(Hibernate not generating child id on cascade all save)

家长班:

@Entity
@Table(name = "****")
@Audited
public class Ship
{
    @Id
    @Column(name = "id")
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid")
    private String              id;

    @OneToMany(mappedBy = "associatedShip", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private List<ShipLoadlineInformation>   loadlineInformation = new ArrayList<ShipLoadlineInformation>(0);

    .. with other fields constructors, getters and setters.
}

儿童班:

@Entity
@Table(name = "*********")
@Audited
public class ShipLoadlineInformation
{
    @Id
    @Column(name = "id")
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid")
    private String      id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "ASSOCIATED_SHIP")
    private Ship        associatedShip;

    .. with other fields, constructors, getter and setters
}

我将它保存在我的DAO中,如下所示:

    this.sessionFactory.getCurrentSession().save(ship);

当我尝试保存对象时,它会给我以下错误:

org.hibernate.NonUniqueObjectException:具有相同标识符值的另一个对象已与会话关联:[com.tms.model.transportMode.ShipLoadlineInformation#] at org.hibernate.engine.internal.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java: 618)〜[hibernate-core-4.3.11.Final.jar:4.3.11.Final] org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:301)〜[hibernate-core-4.3.11 .Final.jar:4.3.11.Final]在org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:244)〜[hibernate-core-4.3.11.Final.jar:4.3.11.Final]在org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:109)〜[hibernate-core-4.3.11.Final.jar:4.3.11.Final] org.hibernate.event.internal.DefaultSaveOrUpdateEventListener。 onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)〜[hibernate -core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:684)〜[hibernate-core-4.3.11.Final.jar:4.3。 11.Final]在org.hibernate.spi上的org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:676)〜[hibernate-core-4.3.11.Final.jar:4.3.11.Final]。在org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:350)的CascadingActions $ 5.cascade(CascadingActions.java:235)〜[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 〜[hibernate-core-4.3.11.Final.jar:4.3.11.Final]在org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:293)〜[hibernate-core-4.3.11.Final .jar:4.3.11.Final] org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)~ [hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org .hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:379)〜[hibernate-core-4.3.11.Final.jar:4.3.11.Final] org.hibernate.engine.internal.Cascade.cascadeCollection( Cascade.java:319)~ [hibern ate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:296)~ [hibernate-core-4.3.11.Final.jar :4.3.11.Final]在org.hibernate的org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)〜[hibernate-core-4.3.11.Final.jar:4.3.11.Final] .engine.internal.Cascade.cascade(Cascade.java:118)~ [hibernate-core-4.3.11.Final.jar:4.3.11.Final]

在调试它时,发现父类的id正在生成。 但是没有生成子类的id。

我认为这是原因。 如果我错了,请纠正我。

任何帮助表示赞赏。

谢谢。


Parent Class:

@Entity
@Table(name = "****")
@Audited
public class Ship
{
    @Id
    @Column(name = "id")
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid")
    private String              id;

    @OneToMany(mappedBy = "associatedShip", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private List<ShipLoadlineInformation>   loadlineInformation = new ArrayList<ShipLoadlineInformation>(0);

    .. with other fields constructors, getters and setters.
}

Child class:

@Entity
@Table(name = "*********")
@Audited
public class ShipLoadlineInformation
{
    @Id
    @Column(name = "id")
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid")
    private String      id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "ASSOCIATED_SHIP")
    private Ship        associatedShip;

    .. with other fields, constructors, getter and setters
}

I am saving it in my DAO as follows:

    this.sessionFactory.getCurrentSession().save(ship);

When i try to save the object ship its giving me following error:

org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.tms.model.transportMode.ShipLoadlineInformation#] at org.hibernate.engine.internal.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:618) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:301) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:244) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:109) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:684) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:676) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.engine.spi.CascadingActions$5.cascade(CascadingActions.java:235) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:350) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:293) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:379) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:319) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:296) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:118) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]

When debugging it, found out that the id for the parent class is getting generated. But the id for child class is not being generated.

I think this is the cause. Correct me if i am wrong.

Any help is appreciated.

Thanks.


原文:https://stackoverflow.com/questions/35319735
更新时间:2023-07-02 22:07

最满意答案

编辑2:我将CreateFile更改为CreateFileA,这是它给我的eroor代码(驱动器D是USB,它不是硬盘)

这是一个完全不同的问题,与wchar_t无关。

在你的第一个剪辑中,你通过了"\\\\.\\F:" (AKA \\.\F:一旦我们删除了C逃逸); 在您从命令行尝试的所有尝试中,您从未提供此路径,但分别为:

  • D - 所以它试图在当前目录中打开一个名为D的文件,但它没有找到它(错误2,又名ERROR_FILE_NOT_FOUND );
  • D:\ - 根目录,无法使用CreateFile打开(错误3,又名ERROR_PATH_NOT_FOUND ),
  • D: - 驱动器D:上的当前目录,再次无法使用CreateFile打开(错误5,又名ERROR_ACCESS_DENIED );
  • \D: - 当前驱动器根目录中名为“D:”的文件,如果D:不是有效文件名(错误123,又名ERROR_INVALID_NAME ),则无法创建该文件。

要将驱动器作为设备打开, 必须使用\\.\X: path(其中X是驱动器号); 你不能只是扔掉你心中的任何漂浮物,并希望它能起作用。 从命令行调用你的程序,通过"\\.\D:" ,它将正常工作。

当然,如果你想让用户更简单,你可以只接受命令行上的驱动器号并编写一些代码来创建CreateFile所需的字符串。

if(argc<1) {
    printf("Not enough arguments\n");
    return 1;
}
const char *drive = argv[1];
char d = drive[0];
// accept both `d` and `d:` as argument for the drive
if(!((d>='a' && d<='z') || (d>='A' && d<='Z')) ||
     (drive[1]!=0 && drive[1]!=':') ||
      drive[2]!=0) {
    printf("Invalid drive specifier: `%s`\n", drive);
    return 2;
}
char path[]="\\\\.\\X:";
path[4] = d;
// now you can use path as argument to CreateFileA

接下来是原始答案,它仍然有效,但它解决了一个完全不同的问题,与OP正在经历的实际问题无关

你不能让LPWSTR指向一个char * ,特别是不要粗暴地LPWSTR指针 - LPWSTR一个指针只会让编译器闭嘴,它不会改变你指向的东西不是一个wchar_t字符串的事实。 如果要将char *传递给期望wchar_t *的函数,则必须执行指向数据的实际转换。

现在,您有几种可能的解决方案:

  • 你可以使用_wmain直接接收命令行参数作为宽字符;
  • 您可以使用MultiByteToWideChar等函数将本地编码字符串转换为UTF-16字符串; 这可以封装在一个返回std::wstring的函数中;
  • 你可以调用API的ANSI版本并让它处理它; 几乎所有的Win32 API都有ANSI和Unicode版本,后缀为A和W( CreateFile只是一个扩展为CreateFileACreateFileW的宏,具体取决于_UNICODE宏)。 因此,您可以使用CreateFileA并按原样将其传递给它。

最后两个解决方案并不是很好,因为使用本地编码字符串作为命令行参数会阻止程序使用任意Unicode字符打开文件。 OTOH,使用wchar_t几乎无处不在,因为它们“感染”了应用程序中几乎每个字符串处理的角落。 正确的(恕我直言)出路是在任何地方使用UTF-8,并在与操作系统交谈时动态转换; 看详情


EDIT 2: i changed the CreateFile to CreateFileA , and this is the eroor codes it gives me (the drive D is a usb, its not a hard drive)

This is a completely different question, and has nothing to do with wchar_t.

In your first snipped you passed "\\\\.\\F:" (AKA \\.\F: once we remove the C escaping); in all your tries from the command line you never provided this path, but respectively:

  • D - so it tried to open a file named D in the current directory, and it didn't find it (error 2, aka ERROR_FILE_NOT_FOUND);
  • D:\ - the root directory, which cannot be opened with CreateFile (error 3, aka ERROR_PATH_NOT_FOUND),
  • D: - the current directory on the drive D:, which again cannot be opened with CreateFile (error 5, aka ERROR_ACCESS_DENIED);
  • \D: - a file named "D:" in the root of the current drive, which cannot be created given that D: is not a valid file name (error 123, aka ERROR_INVALID_NAME).

To open a drive as a device, you must use the \\.\X: path (where X is the drive letter); you cannot just throw whatever floats in your mind and hope that it'll work. Call your program from the command line passing "\\.\D:" and it'll work fine.

Of course if you want to keep it simpler for the user you can accept just the drive letter on the command line and write some code to create the string required by CreateFile based on it.

if(argc<1) {
    printf("Not enough arguments\n");
    return 1;
}
const char *drive = argv[1];
char d = drive[0];
// accept both `d` and `d:` as argument for the drive
if(!((d>='a' && d<='z') || (d>='A' && d<='Z')) ||
     (drive[1]!=0 && drive[1]!=':') ||
      drive[2]!=0) {
    printf("Invalid drive specifier: `%s`\n", drive);
    return 2;
}
char path[]="\\\\.\\X:";
path[4] = d;
// now you can use path as argument to CreateFileA

What follows was the original answer, which is still valid but it addresses a completely different problem, unrelated to the actual problem OP is experiencing

You cannot make LPWSTR point to a char *, especially not by brutally casting the pointer - casting a pointer just makes the compiler shut up, it doesn't change the fact that what you are pointing at is not a wchar_t string. If you want to pass a char * to a function expecting a wchar_t * you have to perform an actual conversion of the pointed data.

Now, you have several possible solutions:

  • you can use _wmain and receive your command line arguments directly as wide characters;
  • you can convert your local-encoding strings to UTF-16 strings by using a function such as the MultiByteToWideChar; this can be encapsulated in a function returning a std::wstring;
  • you can just invoke the ANSI version of the API and let it deal with it; almost all Win32 APIs have both an ANSI and Unicode version, suffixed with A and W (CreateFile is just a macro that expands to CreateFileA or CreateFileW depending on the _UNICODE macro). So, you can use CreateFileA and pass it your string as-is.

The last two solutions are not great because using local-encoding strings as command line arguments precludes your program from opening files using arbitrary Unicode characters. OTOH, using wchar_t almost everywhere is quite a dread, since they "infect" virtually every string-processing corner of your application. The correct (IMHO) way out is to use UTF-8 everywhere, and convert on the fly when talking to the operating systems; see here for details.

相关问答

更多
  • C ++方式: std::wstring mywstring(mystring); std::wstring concatted_stdstr = L"hello " + mywstring + L" blah"; LPCWSTR concatted = concatted_stdstr.c_str(); The C++ way: std::wstring mywstring(mystring); std::wstring concatted_stdstr = L"hello " + mywstring ...
  • 编辑2:我将CreateFile更改为CreateFileA,这是它给我的eroor代码(驱动器D是USB,它不是硬盘) 这是一个完全不同的问题,与wchar_t无关。 在你的第一个剪辑中,你通过了"\\\\.\\F:" (AKA \\.\F:一旦我们删除了C逃逸); 在您从命令行尝试的所有尝试中,您从未提供此路径,但分别为: D - 所以它试图在当前目录中打开一个名为D的文件,但它没有找到它(错误2,又名ERROR_FILE_NOT_FOUND ); D:\ - 根目录,无法使用CreateFile打开( ...
  • 该文件说: lgrui0_name 指向一个Unicode字符串的指针,指定用户所属的本地组的名称 您需要使用UNICODE方法(通常在Windows上标记为大写W)或者需要将其转换 : for (int i = 0; i
  • 略有修改的代码,但签名是重要的。 此方法将字符串值(第三个参数)分配给传入的未初始化的out数组的第一个元素。 [DllImport("Dll1.Windows.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] public static extern void TestArrayOfStrings( [MarshalAs(UnmanagedType.LPArray, Arra ...
  • 您的程序配置为编译为unicode。 这就是为什么GetCurrentDirectory是GetCurrentDirectoryW,它需要一个LPWSTR ( wchar_t* )。 GetCurrentDirectoryW需要一个wchar_t而不是char数组。 您可以使用TCHAR来完成此操作,它像GetCurrentDirectory一样依赖于unicode设置并始终表示适当的字符类型。 不要忘记用L来预先设置'\0' ,以便使字符文字unicode也可以! Your program is conf ...
  • 不要转换。 使用wprintf代替printf : wprintf 请参阅说明如何使用它的示例 。 或者,你可以使用std::wcout作为: wchar_t *wstr1= L"string"; LPWSTR wstr2= L"string"; //same as above std::wcout << wstr1 << L", " << wstr2; 同样,使用为宽字符设计的函数,并忘记将wchar_t转换为char的想法,因为它可能会丢失数据。 看看这里处理宽字符的函数: Unicode在Vis ...
  • C ++ 11 char16_t类型与wchar_t不同。 从理论上讲,你可以在char16_t*和char16_t*之间reinterpret_cast你的方式(Windows的wchar_t是16位)。 但实际上,Visual C ++ 10.0 - 我认为Visual C ++ 11.0 - 缺乏对u'A'或u"A"等Unicode文字的支持。 总结(我发现在SO上应该更好地明确所有结论): “在我的库中使用C ++ 11的u16string是否可以?” 当然,但不是作为wchar_t字符串的直接插件 ...
  • LPWSTR是一个“宽”字符串,即Unicode。 PtrToStringUni可能会更好地为您服务。 此外,IntPtr确实有+运算符重载,你应该能够做IntPtr ptr = mystruct.items + (IntPtr.Size * x) LPWSTR is a 'wide' string, i.e., Unicode. PtrToStringUni will probably work better for you. Also, IntPtr does have the + operator o ...
  • std::to_wstring更简单,但要指出代码中的问题,你从未创建过缓冲区 。 LPWSTR ret = L""; 使ret成为指向静态内存中保存的数组的指针。 此数组无法修改。 以下是使用std::wstring作为缓冲区来修复代码的一种方法: std::wstring IntToWstring(int value) { std::ostringstream convert; std::string out; convert << value; ou ...
  • 无需转换或复制。 std::wstring nnWString(MAX_PATH, 0); nnWString.resize(LoadStringW(hMod, id, &nnWString[0], nnWString.size()); 注意:您的原始代码会导致未定义的行为,因为它使用未初始化的指针进行写入。 肯定不是你想要的。 这是另一种变化: http://msmvps.com/blogs/gdicanio/archive/2010/01/05/stl-strings-loading-from-res ...

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。