0

I have a column that contains a string, representing the name (and thereby primary key) of another entity, to which I am attempting to join the columns to store the entity in the parent. The entities look like so:

@Entity
public class Thing {

    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Id
    @Column(name = "thingname")
    private String name;
}

@Entity
public class Consumer {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    
    @Column(name = "sourcething")
    private String source;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "sourcething", referencedColumnName = "thingname")
    private Thing thing;
}

This will throw a mapping error, denoting duplicate column mappings, so from this question I added the additional arguments:

@JoinColumn(name = "sourcething", referencedColumnName = "thingname", insertable = false, updatable = false)

However, this beings to fail with ConstraintViolationExceptions during unit testing.

Is there something I am missing for completing this mapping/column join?

pstatix
  • 3,611
  • 4
  • 18
  • 40
  • The issue is because you have the column name 'sourcething' used twice. One probably by mistake at the field 'source'. – Mar-Z Jun 07 '23 at 18:35
  • @Mar-Z its not by mistake, the `Thing` entity is being added in, and I want to map the entities in the `thing` table by their `name` which is what is populated in the `sourcething` column. So inside `sourcething` is a string that may say `ABC` and in one of the rows of the `thing` table in the `name` column is `ABC` and we want to map them. – pstatix Jun 07 '23 at 18:41
  • Yes, but in the entity Consumer you have another field called 'source' which name in the Column annotation is 'sourcething' too. – Mar-Z Jun 07 '23 at 18:49
  • @Mar-Z is `@JoinColumn` attempting to create another `sourcething` column? Is it not possible to tell an entity to have a field that uses an existing column and join from it? – pstatix Jun 07 '23 at 19:14

1 Answers1

0

I do not know your exact use case but the table defintions look strange to me. First of all an identifier (@ID) should be a numeric value or at least an UUID but not an arbitrary string. Why do not store the numeric ID in the table you mentioned pointing to that string? Something like this:

@Entity
public class Thing {

    @GeneratedValue(strategy = GenerationType.AUTO)
    @Id
    private Long id;

    @Column(name = "thingname")
    private String name;
}

@Entity
public class Consumer {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "sourcething_id")
    private Thing thing;
}

By this you can also access the string bby Consumer.thing.name

BTW: the constraint violation presumably occurrs as you defined the sourcething as @JoinColumn(name = "sourcething", referencedColumnName = "thingname", insertable = false, updatable = false) but at the same time you insert a value using @Column(name = "sourcething") private String source; column.

Arno
  • 308
  • 3
  • 10
  • A couple follow ups: 1) Why should the PK not be a string other than potentially performance? A UUID is a string, and that's commonly used. 2) Does `@JoinColumn` attempt to create a column and that's why this is problematic? I would just like to use the existing `sourcething` column and join from that. – pstatix Jun 07 '23 at 19:14