19

I have following definition in Employee class

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "employee_id")
private Integer employeeId;

Now I want to import existing employees with existing employee IDs. Even if I set the employee ID before saving, the assigned ID is ignored and auto incremented ID is stored. How do we override this?

I had similar problem for composite key which has been explained here

sidgate
  • 14,650
  • 11
  • 68
  • 119
  • Obviously some JPA implementations (e.g DataNucleus JPA) may provide a mechanism to allow the auto-generation only when that field is null, but JPA as a spec doesn't. – DataNucleus Jul 26 '12 at 12:43

4 Answers4

28

I wrote my own generator to solve the issue.

public class UseExistingIdOtherwiseGenerateUsingIdentity extends IdentityGenerator {

    @Override
    public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
        Serializable id = session.getEntityPersister(null, object).getClassMetadata().getIdentifier(object, session);
        return id != null ? id : super.generate(session, object);
    }
}

and use it like this: (replace the package name)

@Id
@GenericGenerator(name = "UseExistingIdOtherwiseGenerateUsingIdentity", strategy = "{package}.UseExistingIdOtherwiseGenerateUsingIdentity")
@GeneratedValue(generator = "UseExistingIdOtherwiseGenerateUsingIdentity")
@Column(unique = true, nullable = false)
protected Integer id;
sidgate
  • 14,650
  • 11
  • 68
  • 119
2

You cannot override it. First of all JPA do not provide way to do it. Second problem is that GenerationType.AUTO can produce such a column type that will not accept user assigned value via SQL statement.

Perform import of data manually and do not try to use application itself as an import tool.

Mikko Maunu
  • 41,366
  • 10
  • 132
  • 135
  • :( Any other way than manual import? I cannot do it manually as there is some preprocessing as well. In that case I have to write insert code :( – sidgate Jul 26 '12 at 11:35
  • @sidgate Maybe you could just disable the autogenerated, do your import, and re-enable it? – G-Man Jul 26 '12 at 12:15
  • That can be possible, but it depends about column definition (or how GenerationType.AUTO is actually materilized in database) of id is simple disabling/enabling possible. – Mikko Maunu Jul 26 '12 at 12:33
  • Please refer to the answer below. I was able to solve the issue by having own generator. Do you see any issue with this implementation? – sidgate Aug 02 '12 at 08:06
0

In this case, it might be best to have a @MappedSuperclass

@MappedSuperclass
public AbstractEmployee {
   // declare all properties, getters, setters except for the id
}

@Entity
@Table(name="EMPLOYEE")
public class Employee extends AbstractEmployee {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "employee_id")
    private Integer employeeId;

    ...
}

@Entity
@Table(name="EMPLOYEE")
public class EmployeeWithAssignedId extends AbstractEmployee {
    @Id
    @Column(name = "employee_id")
    private Integer employeeId;

    ...
}

So when you want to assign the ID manually, use the second class. I have not tested this, but I believe it should work for your situation. I don't believe there's any rule in JPA that says two classes can't have the same table name :)

Matt
  • 11,523
  • 2
  • 23
  • 33
  • I had my model classes generated from Roo. Modifying these classes would have been cumbersome. Instead I implemented a new generator, explained below – sidgate Aug 02 '12 at 08:06
  • OK. Please try to mention these things in your questions, as that's important information which could alter people's answers. – Matt Aug 02 '12 at 12:21
0

you must override getEmployeeId() method and use Annotation on this method in this case JPA uses the getter methods for all fields in class and you must move other Annotaions on getter methods

Saeed Shahsavan
  • 35
  • 1
  • 10